Bug Summary

File:var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp
Warning:line 3401, column 9
Value stored to 'error' 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_docshell_base0.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/docshell/base -fcoverage-compilation-dir=/var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/docshell/base -resource-dir /usr/lib/llvm-19/lib/clang/19 -include /var/lib/jenkins/workspace/firefox-scan-build/config/gcc_hidden.h -include /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/mozilla-config.h -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dist/stl_wrappers -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dist/system_wrappers -U _FORTIFY_SOURCE -D _FORTIFY_SOURCE=2 -D DEBUG=1 -D MOZ_HAS_MOZGLUE -D MOZILLA_INTERNAL_API -D IMPL_LIBXUL -D MOZ_SUPPORT_LEAKCHECKING -D STATIC_EXPORTABLE_JS_API -I /var/lib/jenkins/workspace/firefox-scan-build/docshell/base -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/docshell/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/docshell/shistory -I /var/lib/jenkins/workspace/firefox-scan-build/dom/base -I /var/lib/jenkins/workspace/firefox-scan-build/dom/bindings -I /var/lib/jenkins/workspace/firefox-scan-build/js/xpconnect/src -I /var/lib/jenkins/workspace/firefox-scan-build/layout/base -I /var/lib/jenkins/workspace/firefox-scan-build/layout/generic -I /var/lib/jenkins/workspace/firefox-scan-build/layout/style -I /var/lib/jenkins/workspace/firefox-scan-build/layout/xul -I /var/lib/jenkins/workspace/firefox-scan-build/netwerk/base -I /var/lib/jenkins/workspace/firefox-scan-build/netwerk/protocol/viewsource -I /var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/browser -I /var/lib/jenkins/workspace/firefox-scan-build/toolkit/components/find -I /var/lib/jenkins/workspace/firefox-scan-build/tools/profiler -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dist/include -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dist/include/nspr -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dist/include/nss -D MOZILLA_CLIENT -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../include/x86_64-linux-gnu/c++/14 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/backward -internal-isystem /usr/lib/llvm-19/lib/clang/19/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-error=tautological-type-limit-compare -Wno-invalid-offsetof -Wno-range-loop-analysis -Wno-deprecated-anon-enum-enum-conversion -Wno-deprecated-enum-enum-conversion -Wno-deprecated-this-capture -Wno-inline-new-delete -Wno-error=deprecated-declarations -Wno-error=array-bounds -Wno-error=free-nonheap-object -Wno-error=atomic-alignment -Wno-error=deprecated-builtins -Wno-psabi -Wno-error=builtin-macro-redefined -Wno-vla-cxx-extension -Wno-unknown-warning-option -fdeprecated-macro -ferror-limit 19 -fstrict-flex-arrays=1 -stack-protector 2 -fstack-clash-protection -ftrivial-auto-var-init=pattern -fno-rtti -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -fno-sized-deallocation -fno-aligned-allocation -vectorize-loops -vectorize-slp -analyzer-checker optin.performance.Padding -analyzer-output=html -analyzer-config stable-report-filename=true -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/scan-build-2024-09-22-115206-3586786-1 -x c++ Unified_cpp_docshell_base0.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#include "nsDocShell.h"
8
9#include <algorithm>
10
11#ifdef XP_WIN
12# include <process.h>
13# define getpid _getpid
14#else
15# include <unistd.h> // for getpid()
16#endif
17
18#include "mozilla/ArrayUtils.h"
19#include "mozilla/Attributes.h"
20#include "mozilla/AutoRestore.h"
21#include "mozilla/BasePrincipal.h"
22#include "mozilla/Casting.h"
23#include "mozilla/CheckedInt.h"
24#include "mozilla/Components.h"
25#include "mozilla/DebugOnly.h"
26#include "mozilla/Encoding.h"
27#include "mozilla/EventStateManager.h"
28#include "mozilla/HTMLEditor.h"
29#include "mozilla/InputTaskManager.h"
30#include "mozilla/LoadInfo.h"
31#include "mozilla/Logging.h"
32#include "mozilla/MediaFeatureChange.h"
33#include "mozilla/Preferences.h"
34#include "mozilla/PresShell.h"
35#include "mozilla/ResultExtensions.h"
36#include "mozilla/SchedulerGroup.h"
37#include "mozilla/ScopeExit.h"
38#include "mozilla/ScrollContainerFrame.h"
39#include "mozilla/ScrollTypes.h"
40#include "mozilla/SimpleEnumerator.h"
41#include "mozilla/StaticPrefs_browser.h"
42#include "mozilla/StaticPrefs_docshell.h"
43#include "mozilla/StaticPrefs_dom.h"
44#include "mozilla/StaticPrefs_extensions.h"
45#include "mozilla/StaticPrefs_privacy.h"
46#include "mozilla/StaticPrefs_security.h"
47#include "mozilla/StaticPrefs_ui.h"
48#include "mozilla/StaticPrefs_fission.h"
49#include "mozilla/StartupTimeline.h"
50#include "mozilla/StorageAccess.h"
51#include "mozilla/StoragePrincipalHelper.h"
52#include "mozilla/Telemetry.h"
53
54#include "mozilla/Unused.h"
55#include "mozilla/WidgetUtils.h"
56
57#include "mozilla/dom/AutoEntryScript.h"
58#include "mozilla/dom/ChildProcessChannelListener.h"
59#include "mozilla/dom/ClientChannelHelper.h"
60#include "mozilla/dom/ClientHandle.h"
61#include "mozilla/dom/ClientInfo.h"
62#include "mozilla/dom/ClientManager.h"
63#include "mozilla/dom/ClientSource.h"
64#include "mozilla/dom/ContentChild.h"
65#include "mozilla/dom/ContentFrameMessageManager.h"
66#include "mozilla/dom/DocGroup.h"
67#include "mozilla/dom/Element.h"
68#include "mozilla/dom/FragmentDirective.h"
69#include "mozilla/dom/HTMLAnchorElement.h"
70#include "mozilla/dom/HTMLIFrameElement.h"
71#include "mozilla/dom/PerformanceNavigation.h"
72#include "mozilla/dom/PermissionMessageUtils.h"
73#include "mozilla/dom/PopupBlocker.h"
74#include "mozilla/dom/ScreenOrientation.h"
75#include "mozilla/dom/ScriptSettings.h"
76#include "mozilla/dom/ServiceWorkerInterceptController.h"
77#include "mozilla/dom/ServiceWorkerUtils.h"
78#include "mozilla/dom/SessionHistoryEntry.h"
79#include "mozilla/dom/SessionStorageManager.h"
80#include "mozilla/dom/SessionStoreChangeListener.h"
81#include "mozilla/dom/SessionStoreChild.h"
82#include "mozilla/dom/SessionStoreUtils.h"
83#include "mozilla/dom/BrowserChild.h"
84#include "mozilla/dom/ToJSValue.h"
85#include "mozilla/dom/UserActivation.h"
86#include "mozilla/dom/ChildSHistory.h"
87#include "mozilla/dom/nsCSPContext.h"
88#include "mozilla/dom/nsHTTPSOnlyUtils.h"
89#include "mozilla/dom/LoadURIOptionsBinding.h"
90#include "mozilla/dom/JSWindowActorChild.h"
91#include "mozilla/dom/DocumentBinding.h"
92#include "mozilla/ipc/ProtocolUtils.h"
93#include "mozilla/net/DocumentChannel.h"
94#include "mozilla/net/DocumentChannelChild.h"
95#include "mozilla/net/ParentChannelWrapper.h"
96#include "mozilla/net/UrlClassifierFeatureFactory.h"
97#include "ReferrerInfo.h"
98
99#include "nsIAuthPrompt.h"
100#include "nsIAuthPrompt2.h"
101#include "nsICachingChannel.h"
102#include "nsICaptivePortalService.h"
103#include "nsIChannel.h"
104#include "nsIChannelEventSink.h"
105#include "nsIClassOfService.h"
106#include "nsIConsoleReportCollector.h"
107#include "nsIContent.h"
108#include "nsIContentInlines.h"
109#include "nsIContentSecurityPolicy.h"
110#include "nsIController.h"
111#include "nsIDocShellTreeItem.h"
112#include "nsIDocShellTreeOwner.h"
113#include "nsIDocumentViewer.h"
114#include "mozilla/dom/Document.h"
115#include "nsHTMLDocument.h"
116#include "nsIDocumentLoaderFactory.h"
117#include "nsIDOMWindow.h"
118#include "nsIEditingSession.h"
119#include "nsIEffectiveTLDService.h"
120#include "nsIExternalProtocolService.h"
121#include "nsIFormPOSTActionChannel.h"
122#include "nsIFrame.h"
123#include "nsIGlobalObject.h"
124#include "nsIHttpChannel.h"
125#include "nsIHttpChannelInternal.h"
126#include "nsIIDNService.h"
127#include "nsIInputStreamChannel.h"
128#include "nsIInterfaceRequestorUtils.h"
129#include "nsILayoutHistoryState.h"
130#include "nsILoadInfo.h"
131#include "nsILoadURIDelegate.h"
132#include "nsIMultiPartChannel.h"
133#include "nsINestedURI.h"
134#include "nsINetworkPredictor.h"
135#include "nsINode.h"
136#include "nsINSSErrorsService.h"
137#include "nsIObserverService.h"
138#include "nsIOService.h"
139#include "nsIPrincipal.h"
140#include "nsIPrivacyTransitionObserver.h"
141#include "nsIPrompt.h"
142#include "nsIPromptCollection.h"
143#include "nsIPromptFactory.h"
144#include "nsIPublicKeyPinningService.h"
145#include "nsIReflowObserver.h"
146#include "nsIScriptChannel.h"
147#include "nsIScriptObjectPrincipal.h"
148#include "nsIScriptSecurityManager.h"
149#include "nsScriptSecurityManager.h"
150#include "nsIScrollObserver.h"
151#include "nsISupportsPrimitives.h"
152#include "nsISecureBrowserUI.h"
153#include "nsISeekableStream.h"
154#include "nsISelectionDisplay.h"
155#include "nsISHEntry.h"
156#include "nsISiteSecurityService.h"
157#include "nsISocketProvider.h"
158#include "nsIStringBundle.h"
159#include "nsIStructuredCloneContainer.h"
160#include "nsIBrowserChild.h"
161#include "nsITextToSubURI.h"
162#include "nsITimedChannel.h"
163#include "nsITimer.h"
164#include "nsITransportSecurityInfo.h"
165#include "nsIUploadChannel.h"
166#include "nsIURIFixup.h"
167#include "nsIURIMutator.h"
168#include "nsIURILoader.h"
169#include "nsIViewSourceChannel.h"
170#include "nsIWebBrowserChrome.h"
171#include "nsIWebBrowserFind.h"
172#include "nsIWebProgress.h"
173#include "nsIWidget.h"
174#include "nsIWindowWatcher.h"
175#include "nsIWritablePropertyBag2.h"
176#include "nsIX509Cert.h"
177#include "nsIXULRuntime.h"
178
179#include "nsCommandManager.h"
180#include "nsPIDOMWindow.h"
181#include "nsPIWindowRoot.h"
182
183#include "IHistory.h"
184#include "IUrlClassifierUITelemetry.h"
185
186#include "nsArray.h"
187#include "nsArrayUtils.h"
188#include "nsCExternalHandlerService.h"
189#include "nsContentDLF.h"
190#include "nsContentPolicyUtils.h" // NS_CheckContentLoadPolicy(...)
191#include "nsContentSecurityManager.h"
192#include "nsContentSecurityUtils.h"
193#include "nsContentUtils.h"
194#include "nsCURILoader.h"
195#include "nsDocShellCID.h"
196#include "nsDocShellEditorData.h"
197#include "nsDocShellEnumerator.h"
198#include "nsDocShellLoadState.h"
199#include "nsDocShellLoadTypes.h"
200#include "nsDOMCID.h"
201#include "nsDOMNavigationTiming.h"
202#include "nsDSURIContentListener.h"
203#include "nsEditingSession.h"
204#include "nsError.h"
205#include "nsEscape.h"
206#include "nsFocusManager.h"
207#include "nsGlobalWindowInner.h"
208#include "nsGlobalWindowOuter.h"
209#include "nsJSEnvironment.h"
210#include "nsNetCID.h"
211#include "nsNetUtil.h"
212#include "nsObjectLoadingContent.h"
213#include "nsPingListener.h"
214#include "nsPoint.h"
215#include "nsQueryObject.h"
216#include "nsQueryActor.h"
217#include "nsRect.h"
218#include "nsRefreshTimer.h"
219#include "nsSandboxFlags.h"
220#include "nsSHEntry.h"
221#include "nsSHistory.h"
222#include "nsSHEntry.h"
223#include "nsStructuredCloneContainer.h"
224#include "nsSubDocumentFrame.h"
225#include "nsURILoader.h"
226#include "nsURLHelper.h"
227#include "nsView.h"
228#include "nsViewManager.h"
229#include "nsViewSourceHandler.h"
230#include "nsWebBrowserFind.h"
231#include "nsWhitespaceTokenizer.h"
232#include "nsWidgetsCID.h"
233#include "nsXULAppAPI.h"
234
235#include "CertVerifier.h"
236#include "ThirdPartyUtil.h"
237#include "GeckoProfiler.h"
238#include "mozilla/NullPrincipal.h"
239#include "Navigator.h"
240#include "prenv.h"
241#include "mozilla/ipc/URIUtils.h"
242#include "sslerr.h"
243#include "mozpkix/pkix.h"
244#include "NSSErrorsService.h"
245
246#include "nsDocShellTelemetryUtils.h"
247
248#ifdef MOZ_PLACES1
249# include "nsIFaviconService.h"
250# include "mozIPlacesPendingOperation.h"
251#endif
252
253#if NS_PRINT_PREVIEW1
254# include "nsIDocumentViewerPrint.h"
255# include "nsIWebBrowserPrint.h"
256#endif
257
258using namespace mozilla;
259using namespace mozilla::dom;
260using namespace mozilla::net;
261
262using mozilla::ipc::Endpoint;
263
264// Threshold value in ms for META refresh based redirects
265#define REFRESH_REDIRECT_TIMER15000 15000
266
267static mozilla::LazyLogModule gCharsetMenuLog("CharsetMenu");
268
269#define LOGCHARSETMENU(args)do { const ::mozilla::LogModule* moz_real_module = gCharsetMenuLog
; 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
args); } } while (0)
\
270 MOZ_LOG(gCharsetMenuLog, mozilla::LogLevel::Debug, args)do { const ::mozilla::LogModule* moz_real_module = gCharsetMenuLog
; 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
args); } } while (0)
271
272#ifdef DEBUG1
273unsigned long nsDocShell::gNumberOfDocShells = 0;
274static uint64_t gDocshellIDCounter = 0;
275
276static mozilla::LazyLogModule gDocShellLog("nsDocShell");
277static mozilla::LazyLogModule gDocShellAndDOMWindowLeakLogging(
278 "DocShellAndDOMWindowLeak");
279#endif
280static mozilla::LazyLogModule gDocShellLeakLog("nsDocShellLeak");
281extern mozilla::LazyLogModule gPageCacheLog;
282mozilla::LazyLogModule gSHLog("SessionHistory");
283extern mozilla::LazyLogModule gSHIPBFCacheLog;
284
285const char kAppstringsBundleURL[] =
286 "chrome://global/locale/appstrings.properties";
287
288static bool IsTopLevelDoc(BrowsingContext* aBrowsingContext,
289 nsILoadInfo* aLoadInfo) {
290 MOZ_ASSERT(aBrowsingContext)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aBrowsingContext)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aBrowsingContext))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("aBrowsingContext"
, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 290); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aBrowsingContext"
")"); do { *((volatile int*)__null) = 290; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
291 MOZ_ASSERT(aLoadInfo)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aLoadInfo)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aLoadInfo))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aLoadInfo", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 291); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadInfo" ")"
); do { *((volatile int*)__null) = 291; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
292
293 if (aLoadInfo->GetExternalContentPolicyType() !=
294 ExtContentPolicy::TYPE_DOCUMENT) {
295 return false;
296 }
297
298 return aBrowsingContext->IsTopContent();
299}
300
301// True if loading for top level document loading in active tab.
302static bool IsUrgentStart(BrowsingContext* aBrowsingContext,
303 nsILoadInfo* aLoadInfo, uint32_t aLoadType) {
304 MOZ_ASSERT(aBrowsingContext)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aBrowsingContext)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aBrowsingContext))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("aBrowsingContext"
, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 304); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aBrowsingContext"
")"); do { *((volatile int*)__null) = 304; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
305 MOZ_ASSERT(aLoadInfo)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aLoadInfo)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aLoadInfo))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aLoadInfo", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 305); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadInfo" ")"
); do { *((volatile int*)__null) = 305; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
306
307 if (!IsTopLevelDoc(aBrowsingContext, aLoadInfo)) {
308 return false;
309 }
310
311 if (aLoadType &
312 (nsIDocShell::LOAD_CMD_NORMAL | nsIDocShell::LOAD_CMD_HISTORY)) {
313 return true;
314 }
315
316 return aBrowsingContext->IsActive();
317}
318
319nsDocShell::nsDocShell(BrowsingContext* aBrowsingContext,
320 uint64_t aContentWindowID)
321 : nsDocLoader(true),
322 mContentWindowID(aContentWindowID),
323 mBrowsingContext(aBrowsingContext),
324 mParentCharset(nullptr),
325 mTreeOwner(nullptr),
326 mScrollbarPref(ScrollbarPreference::Auto),
327 mCharsetReloadState(eCharsetReloadInit),
328 mParentCharsetSource(0),
329 mFrameMargins(-1, -1),
330 mItemType(aBrowsingContext->IsContent() ? typeContent : typeChrome),
331 mPreviousEntryIndex(-1),
332 mLoadedEntryIndex(-1),
333 mBusyFlags(BUSY_FLAGS_NONE),
334 mAppType(nsIDocShell::APP_TYPE_UNKNOWN),
335 mLoadType(0),
336 mFailedLoadType(0),
337 mChannelToDisconnectOnPageHide(0),
338 mCreatingDocument(false),
339#ifdef DEBUG1
340 mInEnsureScriptEnv(false),
341#endif
342 mInitialized(false),
343 mAllowSubframes(true),
344 mAllowMetaRedirects(true),
345 mAllowImages(true),
346 mAllowMedia(true),
347 mAllowDNSPrefetch(true),
348 mAllowWindowControl(true),
349 mCSSErrorReportingEnabled(false),
350 mAllowAuth(mItemType == typeContent),
351 mAllowKeywordFixup(false),
352 mDisableMetaRefreshWhenInactive(false),
353 mWindowDraggingAllowed(false),
354 mInFrameSwap(false),
355 mFiredUnloadEvent(false),
356 mEODForCurrentDocument(false),
357 mURIResultedInDocument(false),
358 mIsBeingDestroyed(false),
359 mIsExecutingOnLoadHandler(false),
360 mSavingOldViewer(false),
361 mInvisible(false),
362 mHasLoadedNonBlankURI(false),
363 mBlankTiming(false),
364 mTitleValidForCurrentURI(false),
365 mWillChangeProcess(false),
366 mIsNavigating(false),
367 mForcedAutodetection(false),
368 mCheckingSessionHistory(false),
369 mNeedToReportActiveAfterLoadingBecomesActive(false) {
370 // If no outer window ID was provided, generate a new one.
371 if (aContentWindowID == 0) {
372 mContentWindowID = nsContentUtils::GenerateWindowId();
373 }
374
375 MOZ_LOG(gDocShellLeakLog, LogLevel::Debug, ("DOCSHELL %p created\n", this))do { const ::mozilla::LogModule* moz_real_module = gDocShellLeakLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "DOCSHELL %p created\n", this); } } while (
0)
;
376
377#ifdef DEBUG1
378 mDocShellID = gDocshellIDCounter++;
379 // We're counting the number of |nsDocShells| to help find leaks
380 ++gNumberOfDocShells;
381 MOZ_LOG(gDocShellAndDOMWindowLeakLogging, LogLevel::Info,do { const ::mozilla::LogModule* moz_real_module = gDocShellAndDOMWindowLeakLogging
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Info, "++DOCSHELL %p == %ld [pid = %d] [id = %" "l"
"u" "]\n", (void*)this, gNumberOfDocShells, getpid(), mDocShellID
); } } while (0)
382 ("++DOCSHELL %p == %ld [pid = %d] [id = %" PRIu64 "]\n", (void*)this,do { const ::mozilla::LogModule* moz_real_module = gDocShellAndDOMWindowLeakLogging
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Info, "++DOCSHELL %p == %ld [pid = %d] [id = %" "l"
"u" "]\n", (void*)this, gNumberOfDocShells, getpid(), mDocShellID
); } } while (0)
383 gNumberOfDocShells, getpid(), mDocShellID))do { const ::mozilla::LogModule* moz_real_module = gDocShellAndDOMWindowLeakLogging
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Info, "++DOCSHELL %p == %ld [pid = %d] [id = %" "l"
"u" "]\n", (void*)this, gNumberOfDocShells, getpid(), mDocShellID
); } } while (0)
;
384#endif
385}
386
387nsDocShell::~nsDocShell() {
388 // Avoid notifying observers while we're in the dtor.
389 mIsBeingDestroyed = true;
390
391 Destroy();
392
393 if (mDocumentViewer) {
394 mDocumentViewer->Close(nullptr);
395 mDocumentViewer->Destroy();
396 mDocumentViewer = nullptr;
397 }
398
399 MOZ_LOG(gDocShellLeakLog, LogLevel::Debug, ("DOCSHELL %p destroyed\n", this))do { const ::mozilla::LogModule* moz_real_module = gDocShellLeakLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "DOCSHELL %p destroyed\n", this); } } while
(0)
;
400
401#ifdef DEBUG1
402 if (MOZ_LOG_TEST(gDocShellAndDOMWindowLeakLogging, LogLevel::Info)(__builtin_expect(!!(mozilla::detail::log_test(gDocShellAndDOMWindowLeakLogging
, LogLevel::Info)), 0))
) {
403 nsAutoCString url;
404 if (mLastOpenedURI) {
405 url = mLastOpenedURI->GetSpecOrDefault();
406
407 // Data URLs can be very long, so truncate to avoid flooding the log.
408 const uint32_t maxURLLength = 1000;
409 if (url.Length() > maxURLLength) {
410 url.Truncate(maxURLLength);
411 }
412 }
413
414 // We're counting the number of |nsDocShells| to help find leaks
415 --gNumberOfDocShells;
416 MOZ_LOG(do { const ::mozilla::LogModule* moz_real_module = gDocShellAndDOMWindowLeakLogging
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Info, "--DOCSHELL %p == %ld [pid = %d] [id = %" "l"
"u" "] [url = %s]\n", (void*)this, gNumberOfDocShells, getpid
(), mDocShellID, url.get()); } } while (0)
417 gDocShellAndDOMWindowLeakLogging, LogLevel::Info,do { const ::mozilla::LogModule* moz_real_module = gDocShellAndDOMWindowLeakLogging
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Info, "--DOCSHELL %p == %ld [pid = %d] [id = %" "l"
"u" "] [url = %s]\n", (void*)this, gNumberOfDocShells, getpid
(), mDocShellID, url.get()); } } while (0)
418 ("--DOCSHELL %p == %ld [pid = %d] [id = %" PRIu64 "] [url = %s]\n",do { const ::mozilla::LogModule* moz_real_module = gDocShellAndDOMWindowLeakLogging
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Info, "--DOCSHELL %p == %ld [pid = %d] [id = %" "l"
"u" "] [url = %s]\n", (void*)this, gNumberOfDocShells, getpid
(), mDocShellID, url.get()); } } while (0)
419 (void*)this, gNumberOfDocShells, getpid(), mDocShellID, url.get()))do { const ::mozilla::LogModule* moz_real_module = gDocShellAndDOMWindowLeakLogging
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Info, "--DOCSHELL %p == %ld [pid = %d] [id = %" "l"
"u" "] [url = %s]\n", (void*)this, gNumberOfDocShells, getpid
(), mDocShellID, url.get()); } } while (0)
;
420 }
421#endif
422}
423
424bool nsDocShell::Initialize() {
425 if (mInitialized) {
426 // We've already been initialized.
427 return true;
428 }
429
430 NS_ASSERTION(mItemType == typeContent || mItemType == typeChrome,do { if (!(mItemType == typeContent || mItemType == typeChrome
)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "Unexpected item type in docshell"
, "mItemType == typeContent || mItemType == typeChrome", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 431); MOZ_PretendNoReturn(); } } while (0)
431 "Unexpected item type in docshell")do { if (!(mItemType == typeContent || mItemType == typeChrome
)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "Unexpected item type in docshell"
, "mItemType == typeContent || mItemType == typeChrome", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 431); MOZ_PretendNoReturn(); } } while (0)
;
432
433 NS_ENSURE_TRUE(Preferences::GetRootBranch(), false)do { if ((__builtin_expect(!!(!(Preferences::GetRootBranch())
), 0))) { NS_DebugBreak(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "Preferences::GetRootBranch()"
") failed", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 433); return false; } } while (false)
;
434 mInitialized = true;
435
436 mDisableMetaRefreshWhenInactive =
437 Preferences::GetBool("browser.meta_refresh_when_inactive.disabled",
438 mDisableMetaRefreshWhenInactive);
439
440 if (nsCOMPtr<nsIObserverService> serv = services::GetObserverService()) {
441 const char* msg = mItemType == typeContent ? NS_WEBNAVIGATION_CREATE"webnavigation-create"
442 : NS_CHROME_WEBNAVIGATION_CREATE"chrome-webnavigation-create";
443 serv->NotifyWhenScriptSafe(GetAsSupports(this), msg, nullptr);
444 }
445
446 return true;
447}
448
449/* static */
450already_AddRefed<nsDocShell> nsDocShell::Create(
451 BrowsingContext* aBrowsingContext, uint64_t aContentWindowID) {
452 MOZ_ASSERT(aBrowsingContext, "DocShell without a BrowsingContext!")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aBrowsingContext)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aBrowsingContext))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("aBrowsingContext"
" (" "DocShell without a BrowsingContext!" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 452); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aBrowsingContext"
") (" "DocShell without a BrowsingContext!" ")"); do { *((volatile
int*)__null) = 452; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
453
454 nsresult rv;
455 RefPtr<nsDocShell> ds = new nsDocShell(aBrowsingContext, aContentWindowID);
456
457 // Initialize the underlying nsDocLoader.
458 rv = ds->nsDocLoader::InitWithBrowsingContext(aBrowsingContext);
459 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/docshell/base/nsDocShell.cpp"
, 459)
) {
460 return nullptr;
461 }
462
463 // Create our ContentListener
464 ds->mContentListener = new nsDSURIContentListener(ds);
465
466 // We enable if we're in the parent process in order to support non-e10s
467 // configurations.
468 // Note: This check is duplicated in SharedWorkerInterfaceRequestor's
469 // constructor.
470 if (XRE_IsParentProcess()) {
471 ds->mInterceptController = new ServiceWorkerInterceptController();
472 }
473
474 // We want to hold a strong ref to the loadgroup, so it better hold a weak
475 // ref to us... use an InterfaceRequestorProxy to do this.
476 nsCOMPtr<nsIInterfaceRequestor> proxy = new InterfaceRequestorProxy(ds);
477 ds->mLoadGroup->SetNotificationCallbacks(proxy);
478
479 // XXX(nika): We have our BrowsingContext, so we might be able to skip this.
480 // It could be nice to directly set up our DocLoader tree?
481 rv = nsDocLoader::AddDocLoaderAsChildOfRoot(ds);
482 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/docshell/base/nsDocShell.cpp"
, 482)
) {
483 return nullptr;
484 }
485
486 // Add |ds| as a progress listener to itself. A little weird, but simpler
487 // than reproducing all the listener-notification logic in overrides of the
488 // various methods via which nsDocLoader can be notified. Note that this
489 // holds an nsWeakPtr to |ds|, so it's ok.
490 rv = ds->AddProgressListener(ds, nsIWebProgress::NOTIFY_STATE_DOCUMENT |
491 nsIWebProgress::NOTIFY_STATE_NETWORK |
492 nsIWebProgress::NOTIFY_LOCATION);
493 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/docshell/base/nsDocShell.cpp"
, 493)
) {
494 return nullptr;
495 }
496
497 // If our BrowsingContext has private browsing enabled, update the number of
498 // private browsing docshells.
499 if (aBrowsingContext->UsePrivateBrowsing()) {
500 ds->NotifyPrivateBrowsingChanged();
501 }
502
503 // If our parent window is present in this process, set up our parent now.
504 RefPtr<WindowContext> parentWC = aBrowsingContext->GetParentWindowContext();
505 if (parentWC && parentWC->IsInProcess()) {
506 // If we don't have a parent element anymore, we can't finish this load!
507 // How'd we get here?
508 RefPtr<Element> parentElement = aBrowsingContext->GetEmbedderElement();
509 if (!parentElement) {
510 MOZ_ASSERT_UNREACHABLE("nsDocShell::Create() - !parentElement")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "MOZ_ASSERT_UNREACHABLE: "
"nsDocShell::Create() - !parentElement" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 510); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "nsDocShell::Create() - !parentElement"
")"); do { *((volatile int*)__null) = 510; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
511 return nullptr;
512 }
513
514 // We have an in-process parent window, but don't have a parent nsDocShell?
515 // How'd we get here!
516 nsCOMPtr<nsIDocShell> parentShell =
517 parentElement->OwnerDoc()->GetDocShell();
518 if (!parentShell) {
519 MOZ_ASSERT_UNREACHABLE("nsDocShell::Create() - !parentShell")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "MOZ_ASSERT_UNREACHABLE: "
"nsDocShell::Create() - !parentShell" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 519); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "nsDocShell::Create() - !parentShell"
")"); do { *((volatile int*)__null) = 519; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
520 return nullptr;
521 }
522 parentShell->AddChild(ds);
523 }
524
525 // Make |ds| the primary DocShell for the given context.
526 aBrowsingContext->SetDocShell(ds);
527
528 // Set |ds| default load flags on load group.
529 ds->SetLoadGroupDefaultLoadFlags(aBrowsingContext->GetDefaultLoadFlags());
530
531 if (XRE_IsParentProcess()) {
532 aBrowsingContext->Canonical()->MaybeAddAsProgressListener(ds);
533 }
534
535 return ds.forget();
536}
537
538void nsDocShell::DestroyChildren() {
539 for (auto* child : mChildList.ForwardRange()) {
540 nsCOMPtr<nsIDocShellTreeItem> shell = do_QueryObject(child);
541 NS_ASSERTION(shell, "docshell has null child")do { if (!(shell)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "docshell has null child"
, "shell", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 541); MOZ_PretendNoReturn(); } } while (0)
;
542
543 if (shell) {
544 shell->SetTreeOwner(nullptr);
545 }
546 }
547
548 nsDocLoader::DestroyChildren();
549}
550
551NS_IMPL_CYCLE_COLLECTION_WEAK_PTR_INHERITED(nsDocShell, nsDocLoader,nsDocShell::cycleCollection nsDocShell::_cycleCollectorGlobal
; void nsDocShell::cycleCollection::Unlink(void* p) { nsDocShell
* tmp = DowncastCCParticipant<nsDocShell>(p); nsISupports
* s = static_cast<nsISupports*>(p); nsDocLoader::cycleCollection
::Unlink(s); ImplCycleCollectionUnlink(tmp->mScriptGlobal)
; ImplCycleCollectionUnlink(tmp->mInitialClientSource); ImplCycleCollectionUnlink
(tmp->mBrowsingContext); ImplCycleCollectionUnlink(tmp->
mChromeEventHandler); tmp->DetachWeakPtr(); (void)tmp; } nsresult
nsDocShell::cycleCollection::TraverseNative( void* p, nsCycleCollectionTraversalCallback
& cb) { nsDocShell* tmp = DowncastCCParticipant<nsDocShell
>(p); nsISupports* s = static_cast<nsISupports*>(p);
if (nsDocLoader::cycleCollection::TraverseNative(s, cb) == NS_SUCCESS_INTERRUPTED_TRAVERSE
) { return NS_SUCCESS_INTERRUPTED_TRAVERSE; } ImplCycleCollectionTraverse
(cb, tmp->mScriptGlobal, "mScriptGlobal", 0); ImplCycleCollectionTraverse
(cb, tmp->mInitialClientSource, "mInitialClientSource", 0)
; ImplCycleCollectionTraverse(cb, tmp->mBrowsingContext, "mBrowsingContext"
, 0); ImplCycleCollectionTraverse(cb, tmp->mChromeEventHandler
, "mChromeEventHandler", 0); (void)tmp; return NS_OK; }
552 mScriptGlobal, mInitialClientSource,nsDocShell::cycleCollection nsDocShell::_cycleCollectorGlobal
; void nsDocShell::cycleCollection::Unlink(void* p) { nsDocShell
* tmp = DowncastCCParticipant<nsDocShell>(p); nsISupports
* s = static_cast<nsISupports*>(p); nsDocLoader::cycleCollection
::Unlink(s); ImplCycleCollectionUnlink(tmp->mScriptGlobal)
; ImplCycleCollectionUnlink(tmp->mInitialClientSource); ImplCycleCollectionUnlink
(tmp->mBrowsingContext); ImplCycleCollectionUnlink(tmp->
mChromeEventHandler); tmp->DetachWeakPtr(); (void)tmp; } nsresult
nsDocShell::cycleCollection::TraverseNative( void* p, nsCycleCollectionTraversalCallback
& cb) { nsDocShell* tmp = DowncastCCParticipant<nsDocShell
>(p); nsISupports* s = static_cast<nsISupports*>(p);
if (nsDocLoader::cycleCollection::TraverseNative(s, cb) == NS_SUCCESS_INTERRUPTED_TRAVERSE
) { return NS_SUCCESS_INTERRUPTED_TRAVERSE; } ImplCycleCollectionTraverse
(cb, tmp->mScriptGlobal, "mScriptGlobal", 0); ImplCycleCollectionTraverse
(cb, tmp->mInitialClientSource, "mInitialClientSource", 0)
; ImplCycleCollectionTraverse(cb, tmp->mBrowsingContext, "mBrowsingContext"
, 0); ImplCycleCollectionTraverse(cb, tmp->mChromeEventHandler
, "mChromeEventHandler", 0); (void)tmp; return NS_OK; }
553 mBrowsingContext,nsDocShell::cycleCollection nsDocShell::_cycleCollectorGlobal
; void nsDocShell::cycleCollection::Unlink(void* p) { nsDocShell
* tmp = DowncastCCParticipant<nsDocShell>(p); nsISupports
* s = static_cast<nsISupports*>(p); nsDocLoader::cycleCollection
::Unlink(s); ImplCycleCollectionUnlink(tmp->mScriptGlobal)
; ImplCycleCollectionUnlink(tmp->mInitialClientSource); ImplCycleCollectionUnlink
(tmp->mBrowsingContext); ImplCycleCollectionUnlink(tmp->
mChromeEventHandler); tmp->DetachWeakPtr(); (void)tmp; } nsresult
nsDocShell::cycleCollection::TraverseNative( void* p, nsCycleCollectionTraversalCallback
& cb) { nsDocShell* tmp = DowncastCCParticipant<nsDocShell
>(p); nsISupports* s = static_cast<nsISupports*>(p);
if (nsDocLoader::cycleCollection::TraverseNative(s, cb) == NS_SUCCESS_INTERRUPTED_TRAVERSE
) { return NS_SUCCESS_INTERRUPTED_TRAVERSE; } ImplCycleCollectionTraverse
(cb, tmp->mScriptGlobal, "mScriptGlobal", 0); ImplCycleCollectionTraverse
(cb, tmp->mInitialClientSource, "mInitialClientSource", 0)
; ImplCycleCollectionTraverse(cb, tmp->mBrowsingContext, "mBrowsingContext"
, 0); ImplCycleCollectionTraverse(cb, tmp->mChromeEventHandler
, "mChromeEventHandler", 0); (void)tmp; return NS_OK; }
554 mChromeEventHandler)nsDocShell::cycleCollection nsDocShell::_cycleCollectorGlobal
; void nsDocShell::cycleCollection::Unlink(void* p) { nsDocShell
* tmp = DowncastCCParticipant<nsDocShell>(p); nsISupports
* s = static_cast<nsISupports*>(p); nsDocLoader::cycleCollection
::Unlink(s); ImplCycleCollectionUnlink(tmp->mScriptGlobal)
; ImplCycleCollectionUnlink(tmp->mInitialClientSource); ImplCycleCollectionUnlink
(tmp->mBrowsingContext); ImplCycleCollectionUnlink(tmp->
mChromeEventHandler); tmp->DetachWeakPtr(); (void)tmp; } nsresult
nsDocShell::cycleCollection::TraverseNative( void* p, nsCycleCollectionTraversalCallback
& cb) { nsDocShell* tmp = DowncastCCParticipant<nsDocShell
>(p); nsISupports* s = static_cast<nsISupports*>(p);
if (nsDocLoader::cycleCollection::TraverseNative(s, cb) == NS_SUCCESS_INTERRUPTED_TRAVERSE
) { return NS_SUCCESS_INTERRUPTED_TRAVERSE; } ImplCycleCollectionTraverse
(cb, tmp->mScriptGlobal, "mScriptGlobal", 0); ImplCycleCollectionTraverse
(cb, tmp->mInitialClientSource, "mInitialClientSource", 0)
; ImplCycleCollectionTraverse(cb, tmp->mBrowsingContext, "mBrowsingContext"
, 0); ImplCycleCollectionTraverse(cb, tmp->mChromeEventHandler
, "mChromeEventHandler", 0); (void)tmp; return NS_OK; }
555
556NS_IMPL_ADDREF_INHERITED(nsDocShell, nsDocLoader)MozExternalRefCountType nsDocShell::AddRef(void) { static_assert
(!std::is_destructible_v<nsDocShell>, "Reference-counted class "
"nsDocShell" " should not have a public destructor. " "Make this class's destructor non-public"
); nsrefcnt r = nsDocLoader::AddRef(); if constexpr (::mozilla
::detail::ShouldLogInheritedRefcnt<nsDocShell>) { NS_LogAddRef
((this), (r), ("nsDocShell"), (uint32_t)(sizeof(*this))); } return
r; }
557NS_IMPL_RELEASE_INHERITED(nsDocShell, nsDocLoader)MozExternalRefCountType nsDocShell::Release(void) { nsrefcnt r
= nsDocLoader::Release(); if constexpr (::mozilla::detail::ShouldLogInheritedRefcnt
<nsDocShell>) { NS_LogRelease((this), (r), ("nsDocShell"
)); } return r; }
558
559NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsDocShell)nsresult nsDocShell::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/docshell/base/nsDocShell.cpp"
, 559); MOZ_PretendNoReturn(); } } while (0); nsISupports* foundInterface
; if (TopThreeWordsEquals( aIID, (nsXPCOMCycleCollectionParticipant
::COMTypeInfo<nsXPCOMCycleCollectionParticipant, void>::
kIID), (nsCycleCollectionISupports::COMTypeInfo<nsCycleCollectionISupports
, void>::kIID)) && (LowWordEquals(aIID, (nsXPCOMCycleCollectionParticipant
::COMTypeInfo<nsXPCOMCycleCollectionParticipant, void>::
kIID)) || LowWordEquals(aIID, (nsCycleCollectionISupports::COMTypeInfo
<nsCycleCollectionISupports, void>::kIID)))) { if (LowWordEquals
(aIID, (nsXPCOMCycleCollectionParticipant::COMTypeInfo<nsXPCOMCycleCollectionParticipant
, void>::kIID))) { *aInstancePtr = nsDocShell::cycleCollection
::GetParticipant(); return NS_OK; } if (LowWordEquals(aIID, (
nsCycleCollectionISupports::COMTypeInfo<nsCycleCollectionISupports
, void>::kIID))) { *aInstancePtr = nsDocShell::cycleCollection
::Upcast(this); return NS_OK; } foundInterface = nullptr; } else
560 NS_INTERFACE_MAP_ENTRY(nsIDocShell)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIDocShell>)) foundInterface = static_cast
<nsIDocShell*>(this); else
561 NS_INTERFACE_MAP_ENTRY(nsIDocShellTreeItem)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIDocShellTreeItem>)) foundInterface
= static_cast<nsIDocShellTreeItem*>(this); else
562 NS_INTERFACE_MAP_ENTRY(nsIWebNavigation)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIWebNavigation>)) foundInterface
= static_cast<nsIWebNavigation*>(this); else
563 NS_INTERFACE_MAP_ENTRY(nsIBaseWindow)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIBaseWindow>)) foundInterface =
static_cast<nsIBaseWindow*>(this); else
564 NS_INTERFACE_MAP_ENTRY(nsIRefreshURI)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIRefreshURI>)) foundInterface =
static_cast<nsIRefreshURI*>(this); else
565 NS_INTERFACE_MAP_ENTRY(nsIWebProgressListener)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIWebProgressListener>)) foundInterface
= static_cast<nsIWebProgressListener*>(this); else
566 NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsISupportsWeakReference>)) foundInterface
= static_cast<nsISupportsWeakReference*>(this); else
567 NS_INTERFACE_MAP_ENTRY(nsIWebPageDescriptor)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIWebPageDescriptor>)) foundInterface
= static_cast<nsIWebPageDescriptor*>(this); else
568 NS_INTERFACE_MAP_ENTRY(nsIAuthPromptProvider)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIAuthPromptProvider>)) foundInterface
= static_cast<nsIAuthPromptProvider*>(this); else
569 NS_INTERFACE_MAP_ENTRY(nsILoadContext)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsILoadContext>)) foundInterface =
static_cast<nsILoadContext*>(this); else
570 NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsINetworkInterceptController,if ((mInterceptController) && aIID.Equals(mozilla::detail
::kImplementedIID<std::remove_reference_t<decltype(*this
)>, nsINetworkInterceptController>)) foundInterface = static_cast
<nsINetworkInterceptController*>(this); else
571 mInterceptController)if ((mInterceptController) && aIID.Equals(mozilla::detail
::kImplementedIID<std::remove_reference_t<decltype(*this
)>, nsINetworkInterceptController>)) foundInterface = static_cast
<nsINetworkInterceptController*>(this); else
572NS_INTERFACE_MAP_END_INHERITING(nsDocLoader)foundInterface = 0; nsresult status; if (!foundInterface) status
= nsDocLoader::QueryInterface(aIID, (void**)&foundInterface
); else { (foundInterface)->AddRef(); status = NS_OK; } *aInstancePtr
= foundInterface; return status; }
573
574NS_IMETHODIMPnsresult
575nsDocShell::GetInterface(const nsIID& aIID, void** aSink) {
576 MOZ_ASSERT(aSink, "null out param")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aSink)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(aSink))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("aSink" " (" "null out param"
")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 576); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aSink" ") ("
"null out param" ")"); do { *((volatile int*)__null) = 576; __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
;
577
578 *aSink = nullptr;
579
580 if (aIID.Equals(NS_GET_IID(nsICommandManager)(nsICommandManager::COMTypeInfo<nsICommandManager, void>
::kIID)
)) {
581 NS_ENSURE_SUCCESS(EnsureCommandHandler(), NS_ERROR_FAILURE)do { nsresult __rv = EnsureCommandHandler(); 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", "EnsureCommandHandler()", "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/docshell/base/nsDocShell.cpp"
, 581); return NS_ERROR_FAILURE; } } while (false)
;
582 *aSink = static_cast<nsICommandManager*>(mCommandManager.get());
583 } else if (aIID.Equals(NS_GET_IID(nsIURIContentListener)(nsIURIContentListener::COMTypeInfo<nsIURIContentListener,
void>::kIID)
)) {
584 *aSink = mContentListener;
585 } else if ((aIID.Equals(NS_GET_IID(nsIScriptGlobalObject)(nsIScriptGlobalObject::COMTypeInfo<nsIScriptGlobalObject,
void>::kIID)
) ||
586 aIID.Equals(NS_GET_IID(nsIGlobalObject)(nsIGlobalObject::COMTypeInfo<nsIGlobalObject, void>::kIID
)
) ||
587 aIID.Equals(NS_GET_IID(nsPIDOMWindowOuter)(nsPIDOMWindowOuter::COMTypeInfo<nsPIDOMWindowOuter, void>
::kIID)
) ||
588 aIID.Equals(NS_GET_IID(mozIDOMWindowProxy)(mozIDOMWindowProxy::COMTypeInfo<mozIDOMWindowProxy, void>
::kIID)
) ||
589 aIID.Equals(NS_GET_IID(nsIDOMWindow)(nsIDOMWindow::COMTypeInfo<nsIDOMWindow, void>::kIID))) &&
590 NS_SUCCEEDED(EnsureScriptEnvironment())((bool)(__builtin_expect(!!(!NS_FAILED_impl(EnsureScriptEnvironment
())), 1)))
) {
591 return mScriptGlobal->QueryInterface(aIID, aSink);
592 } else if (aIID.Equals(NS_GET_IID(Document)(Document::COMTypeInfo<Document, void>::kIID)) &&
593 NS_SUCCEEDED(EnsureDocumentViewer())((bool)(__builtin_expect(!!(!NS_FAILED_impl(EnsureDocumentViewer
())), 1)))
) {
594 RefPtr<Document> doc = mDocumentViewer->GetDocument();
595 doc.forget(aSink);
596 return *aSink ? NS_OK : NS_NOINTERFACE;
597 } else if (aIID.Equals(NS_GET_IID(nsIPrompt)(nsIPrompt::COMTypeInfo<nsIPrompt, void>::kIID)) &&
598 NS_SUCCEEDED(EnsureScriptEnvironment())((bool)(__builtin_expect(!!(!NS_FAILED_impl(EnsureScriptEnvironment
())), 1)))
) {
599 nsresult rv;
600 nsCOMPtr<nsIWindowWatcher> wwatch =
601 do_GetService(NS_WINDOWWATCHER_CONTRACTID"@mozilla.org/embedcomp/window-watcher;1", &rv);
602 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/docshell/base/nsDocShell.cpp"
, 602); return rv; } } while (false)
;
603
604 // Get the an auth prompter for our window so that the parenting
605 // of the dialogs works as it should when using tabs.
606 nsIPrompt* prompt;
607 rv = wwatch->GetNewPrompter(mScriptGlobal, &prompt);
608 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/docshell/base/nsDocShell.cpp"
, 608); return rv; } } while (false)
;
609
610 *aSink = prompt;
611 return NS_OK;
612 } else if (aIID.Equals(NS_GET_IID(nsIAuthPrompt)(nsIAuthPrompt::COMTypeInfo<nsIAuthPrompt, void>::kIID)) ||
613 aIID.Equals(NS_GET_IID(nsIAuthPrompt2)(nsIAuthPrompt2::COMTypeInfo<nsIAuthPrompt2, void>::kIID
)
)) {
614 return NS_SUCCEEDED(GetAuthPrompt(PROMPT_NORMAL, aIID, aSink))((bool)(__builtin_expect(!!(!NS_FAILED_impl(GetAuthPrompt(PROMPT_NORMAL
, aIID, aSink))), 1)))
615 ? NS_OK
616 : NS_NOINTERFACE;
617 } else if (aIID.Equals(NS_GET_IID(nsISHistory)(nsISHistory::COMTypeInfo<nsISHistory, void>::kIID))) {
618 // This is deprecated, you should instead directly get
619 // ChildSHistory from the browsing context.
620 MOZ_DIAGNOSTIC_ASSERT(do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "Do not try to get a nsISHistory interface from nsIDocShell"
")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 621); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "false"
") (" "Do not try to get a nsISHistory interface from nsIDocShell"
")"); do { *((volatile int*)__null) = 621; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
621 false, "Do not try to get a nsISHistory interface from nsIDocShell")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "Do not try to get a nsISHistory interface from nsIDocShell"
")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 621); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "false"
") (" "Do not try to get a nsISHistory interface from nsIDocShell"
")"); do { *((volatile int*)__null) = 621; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
622 return NS_NOINTERFACE;
623 } else if (aIID.Equals(NS_GET_IID(nsIWebBrowserFind)(nsIWebBrowserFind::COMTypeInfo<nsIWebBrowserFind, void>
::kIID)
)) {
624 nsresult rv = EnsureFind();
625 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
626 return rv;
627 }
628
629 *aSink = mFind;
630 NS_ADDREF((nsISupports*)*aSink)((nsISupports*)*aSink)->AddRef();
631 return NS_OK;
632 } else if (aIID.Equals(NS_GET_IID(nsISelectionDisplay)(nsISelectionDisplay::COMTypeInfo<nsISelectionDisplay, void
>::kIID)
)) {
633 if (PresShell* presShell = GetPresShell()) {
634 return presShell->QueryInterface(aIID, aSink);
635 }
636 } else if (aIID.Equals(NS_GET_IID(nsIDocShellTreeOwner)(nsIDocShellTreeOwner::COMTypeInfo<nsIDocShellTreeOwner, void
>::kIID)
)) {
637 nsCOMPtr<nsIDocShellTreeOwner> treeOwner;
638 nsresult rv = GetTreeOwner(getter_AddRefs(treeOwner));
639 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && treeOwner) {
640 return treeOwner->QueryInterface(aIID, aSink);
641 }
642 } else if (aIID.Equals(NS_GET_IID(nsIBrowserChild)(nsIBrowserChild::COMTypeInfo<nsIBrowserChild, void>::kIID
)
)) {
643 *aSink = GetBrowserChild().take();
644 return *aSink ? NS_OK : NS_ERROR_FAILURE;
645 } else {
646 return nsDocLoader::GetInterface(aIID, aSink);
647 }
648
649 NS_IF_ADDREF(((nsISupports*)*aSink))ns_if_addref(((nsISupports*)*aSink));
650 return *aSink ? NS_OK : NS_NOINTERFACE;
651}
652
653NS_IMETHODIMPnsresult
654nsDocShell::SetCancelContentJSEpoch(int32_t aEpoch) {
655 // Note: this gets called fairly early (before a pageload actually starts).
656 // We could probably defer this even longer.
657 nsCOMPtr<nsIBrowserChild> browserChild = GetBrowserChild();
658 static_cast<BrowserChild*>(browserChild.get())
659 ->SetCancelContentJSEpoch(aEpoch);
660 return NS_OK;
661}
662
663nsresult nsDocShell::CheckDisallowedJavascriptLoad(
664 nsDocShellLoadState* aLoadState) {
665 if (!net::SchemeIsJavascript(aLoadState->URI())) {
666 return NS_OK;
667 }
668
669 if (nsCOMPtr<nsIPrincipal> targetPrincipal =
670 GetInheritedPrincipal(/* aConsiderCurrentDocument */ true)) {
671 if (!aLoadState->TriggeringPrincipal()->Subsumes(targetPrincipal)) {
672 return NS_ERROR_DOM_BAD_CROSS_ORIGIN_URI;
673 }
674 return NS_OK;
675 }
676 return NS_ERROR_DOM_BAD_CROSS_ORIGIN_URI;
677}
678
679NS_IMETHODIMPnsresult
680nsDocShell::LoadURI(nsDocShellLoadState* aLoadState, bool aSetNavigating) {
681 return LoadURI(aLoadState, aSetNavigating, false);
682}
683
684nsresult nsDocShell::LoadURI(nsDocShellLoadState* aLoadState,
685 bool aSetNavigating,
686 bool aContinueHandlingSubframeHistory) {
687 MOZ_ASSERT(aLoadState, "Must have a valid load state!")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aLoadState)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aLoadState))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("aLoadState" " (" "Must have a valid load state!"
")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 687); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState" ") ("
"Must have a valid load state!" ")"); do { *((volatile int*)
__null) = 687; __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
688 // NOTE: This comparison between what appears to be internal/external load
689 // flags is intentional, as it's ensuring that the caller isn't using any of
690 // the flags reserved for implementations by the `nsIWebNavigation` interface.
691 // In the future, this check may be dropped.
692 MOZ_ASSERT(do { static_assert( mozilla::detail::AssertionConditionType<
decltype((aLoadState->LoadFlags() & INTERNAL_LOAD_FLAGS_LOADURI_SETUP_FLAGS
) == 0)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!((aLoadState->LoadFlags() & INTERNAL_LOAD_FLAGS_LOADURI_SETUP_FLAGS
) == 0))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("(aLoadState->LoadFlags() & INTERNAL_LOAD_FLAGS_LOADURI_SETUP_FLAGS) == 0"
" (" "Should not have these flags set" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 694); AnnotateMozCrashReason("MOZ_ASSERT" "(" "(aLoadState->LoadFlags() & INTERNAL_LOAD_FLAGS_LOADURI_SETUP_FLAGS) == 0"
") (" "Should not have these flags set" ")"); do { *((volatile
int*)__null) = 694; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
693 (aLoadState->LoadFlags() & INTERNAL_LOAD_FLAGS_LOADURI_SETUP_FLAGS) == 0,do { static_assert( mozilla::detail::AssertionConditionType<
decltype((aLoadState->LoadFlags() & INTERNAL_LOAD_FLAGS_LOADURI_SETUP_FLAGS
) == 0)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!((aLoadState->LoadFlags() & INTERNAL_LOAD_FLAGS_LOADURI_SETUP_FLAGS
) == 0))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("(aLoadState->LoadFlags() & INTERNAL_LOAD_FLAGS_LOADURI_SETUP_FLAGS) == 0"
" (" "Should not have these flags set" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 694); AnnotateMozCrashReason("MOZ_ASSERT" "(" "(aLoadState->LoadFlags() & INTERNAL_LOAD_FLAGS_LOADURI_SETUP_FLAGS) == 0"
") (" "Should not have these flags set" ")"); do { *((volatile
int*)__null) = 694; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
694 "Should not have these flags set")do { static_assert( mozilla::detail::AssertionConditionType<
decltype((aLoadState->LoadFlags() & INTERNAL_LOAD_FLAGS_LOADURI_SETUP_FLAGS
) == 0)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!((aLoadState->LoadFlags() & INTERNAL_LOAD_FLAGS_LOADURI_SETUP_FLAGS
) == 0))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("(aLoadState->LoadFlags() & INTERNAL_LOAD_FLAGS_LOADURI_SETUP_FLAGS) == 0"
" (" "Should not have these flags set" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 694); AnnotateMozCrashReason("MOZ_ASSERT" "(" "(aLoadState->LoadFlags() & INTERNAL_LOAD_FLAGS_LOADURI_SETUP_FLAGS) == 0"
") (" "Should not have these flags set" ")"); do { *((volatile
int*)__null) = 694; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
695 MOZ_ASSERT(aLoadState->TargetBrowsingContext().IsNull(),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aLoadState->TargetBrowsingContext().IsNull())>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(aLoadState->TargetBrowsingContext().IsNull()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("aLoadState->TargetBrowsingContext().IsNull()"
" (" "Targeting doesn't occur until InternalLoad" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 696); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->TargetBrowsingContext().IsNull()"
") (" "Targeting doesn't occur until InternalLoad" ")"); do {
*((volatile int*)__null) = 696; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
696 "Targeting doesn't occur until InternalLoad")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aLoadState->TargetBrowsingContext().IsNull())>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(aLoadState->TargetBrowsingContext().IsNull()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("aLoadState->TargetBrowsingContext().IsNull()"
" (" "Targeting doesn't occur until InternalLoad" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 696); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->TargetBrowsingContext().IsNull()"
") (" "Targeting doesn't occur until InternalLoad" ")"); do {
*((volatile int*)__null) = 696; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
;
697
698 if (!aLoadState->TriggeringPrincipal()) {
699 MOZ_ASSERT(false, "LoadURI must have a triggering principal")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "LoadURI must have a triggering principal"
")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 699); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"LoadURI must have a triggering principal" ")"); do { *((volatile
int*)__null) = 699; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
700 return NS_ERROR_FAILURE;
701 }
702
703 MOZ_TRY(CheckDisallowedJavascriptLoad(aLoadState))do { auto mozTryTempResult_ = ::mozilla::ToResult(CheckDisallowedJavascriptLoad
(aLoadState)); if ((__builtin_expect(!!(mozTryTempResult_.isErr
()), 0))) { return mozTryTempResult_.propagateErr(); } } while
(0)
;
704
705 bool oldIsNavigating = mIsNavigating;
706 auto cleanupIsNavigating =
707 MakeScopeExit([&]() { mIsNavigating = oldIsNavigating; });
708 if (aSetNavigating) {
709 mIsNavigating = true;
710 }
711
712 PopupBlocker::PopupControlState popupState = PopupBlocker::openOverridden;
713 if (aLoadState->HasLoadFlags(LOAD_FLAGS_ALLOW_POPUPS)) {
714 popupState = PopupBlocker::openAllowed;
715 // If we allow popups as part of the navigation, ensure we fake a user
716 // interaction, so that popups can, in fact, be allowed to open.
717 if (WindowContext* wc = mBrowsingContext->GetCurrentWindowContext()) {
718 wc->NotifyUserGestureActivation();
719 }
720 }
721
722 AutoPopupStatePusherAutoPopupStatePusherInternal statePusher(popupState);
723
724 if (aLoadState->GetCancelContentJSEpoch().isSome()) {
725 SetCancelContentJSEpoch(*aLoadState->GetCancelContentJSEpoch());
726 }
727
728 // Note: we allow loads to get through here even if mFiredUnloadEvent is
729 // true; that case will get handled in LoadInternal or LoadHistoryEntry,
730 // so we pass false as the second parameter to IsNavigationAllowed.
731 // However, we don't allow the page to change location *in the middle of*
732 // firing beforeunload, so we do need to check if *beforeunload* is currently
733 // firing, so we call IsNavigationAllowed rather than just IsPrintingOrPP.
734 if (!IsNavigationAllowed(true, false)) {
735 return NS_OK; // JS may not handle returning of an error code
736 }
737
738 nsLoadFlags defaultLoadFlags = mBrowsingContext->GetDefaultLoadFlags();
739 if (aLoadState->HasLoadFlags(LOAD_FLAGS_FORCE_TRR)) {
740 defaultLoadFlags |= nsIRequest::LOAD_TRR_ONLY_MODE;
741 } else if (aLoadState->HasLoadFlags(LOAD_FLAGS_DISABLE_TRR)) {
742 defaultLoadFlags |= nsIRequest::LOAD_TRR_DISABLED_MODE;
743 }
744
745 MOZ_ALWAYS_SUCCEEDS(mBrowsingContext->SetDefaultLoadFlags(defaultLoadFlags))do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(mBrowsingContext->SetDefaultLoadFlags(defaultLoadFlags)))
, 1)))), 1))) { } else { do { static_assert( mozilla::detail::
AssertionConditionType<decltype(false)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("false" " (" "NS_SUCCEEDED(mBrowsingContext->SetDefaultLoadFlags(defaultLoadFlags))"
")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 745); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "false"
") (" "NS_SUCCEEDED(mBrowsingContext->SetDefaultLoadFlags(defaultLoadFlags))"
")"); do { *((volatile int*)__null) = 745; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
746
747 if (!StartupTimeline::HasRecord(StartupTimeline::FIRST_LOAD_URI) &&
748 mItemType == typeContent && !NS_IsAboutBlank(aLoadState->URI())) {
749 StartupTimeline::RecordOnce(StartupTimeline::FIRST_LOAD_URI);
750 }
751
752 // LoadType used to be set to a default value here, if no LoadInfo/LoadState
753 // object was passed in. That functionality has been removed as of bug
754 // 1492648. LoadType should now be set up by the caller at the time they
755 // create their nsDocShellLoadState object to pass into LoadURI.
756
757 MOZ_LOG(do { const ::mozilla::LogModule* moz_real_module = gDocShellLeakLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "nsDocShell[%p]: loading %s with flags 0x%08x"
, this, aLoadState->URI()->GetSpecOrDefault().get(), aLoadState
->LoadFlags()); } } while (0)
758 gDocShellLeakLog, LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = gDocShellLeakLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "nsDocShell[%p]: loading %s with flags 0x%08x"
, this, aLoadState->URI()->GetSpecOrDefault().get(), aLoadState
->LoadFlags()); } } while (0)
759 ("nsDocShell[%p]: loading %s with flags 0x%08x", this,do { const ::mozilla::LogModule* moz_real_module = gDocShellLeakLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "nsDocShell[%p]: loading %s with flags 0x%08x"
, this, aLoadState->URI()->GetSpecOrDefault().get(), aLoadState
->LoadFlags()); } } while (0)
760 aLoadState->URI()->GetSpecOrDefault().get(), aLoadState->LoadFlags()))do { const ::mozilla::LogModule* moz_real_module = gDocShellLeakLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "nsDocShell[%p]: loading %s with flags 0x%08x"
, this, aLoadState->URI()->GetSpecOrDefault().get(), aLoadState
->LoadFlags()); } } while (0)
;
761
762 if ((!aLoadState->LoadIsFromSessionHistory() &&
763 !LOAD_TYPE_HAS_FLAGS(aLoadState->LoadType(),((aLoadState->LoadType()) & ((LOAD_FLAGS_REPLACE_HISTORY
) << 16))
764 LOAD_FLAGS_REPLACE_HISTORY)((aLoadState->LoadType()) & ((LOAD_FLAGS_REPLACE_HISTORY
) << 16))
) ||
765 aContinueHandlingSubframeHistory) {
766 // This is possibly a subframe, so handle it accordingly.
767 //
768 // If history exists, it will be loaded into the aLoadState object, and the
769 // LoadType will be changed.
770 if (MaybeHandleSubframeHistory(aLoadState,
771 aContinueHandlingSubframeHistory)) {
772 // MaybeHandleSubframeHistory returns true if we need to continue loading
773 // asynchronously.
774 return NS_OK;
775 }
776 }
777
778 if (aLoadState->LoadIsFromSessionHistory()) {
779 MOZ_LOG(gSHLog, LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = gSHLog; if
((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "nsDocShell[%p]: loading from session history"
, this); } } while (0)
780 ("nsDocShell[%p]: loading from session history", this))do { const ::mozilla::LogModule* moz_real_module = gSHLog; if
((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "nsDocShell[%p]: loading from session history"
, this); } } while (0)
;
781
782 if (!mozilla::SessionHistoryInParent()) {
783 nsCOMPtr<nsISHEntry> entry = aLoadState->SHEntry();
784 return LoadHistoryEntry(entry, aLoadState->LoadType(),
785 aLoadState->HasValidUserGestureActivation());
786 }
787
788 // FIXME Null check aLoadState->GetLoadingSessionHistoryInfo()?
789 return LoadHistoryEntry(*aLoadState->GetLoadingSessionHistoryInfo(),
790 aLoadState->LoadType(),
791 aLoadState->HasValidUserGestureActivation());
792 }
793
794 // On history navigation via Back/Forward buttons, don't execute
795 // automatic JavaScript redirection such as |location.href = ...| or
796 // |window.open()|
797 //
798 // LOAD_NORMAL: window.open(...) etc.
799 // LOAD_STOP_CONTENT: location.href = ..., location.assign(...)
800 if ((aLoadState->LoadType() == LOAD_NORMAL ||
801 aLoadState->LoadType() == LOAD_STOP_CONTENT) &&
802 ShouldBlockLoadingForBackButton()) {
803 return NS_OK;
804 }
805
806 BrowsingContext::Type bcType = mBrowsingContext->GetType();
807
808 // Set up the inheriting principal in LoadState.
809 nsresult rv = aLoadState->SetupInheritingPrincipal(
810 bcType, mBrowsingContext->OriginAttributesRef());
811 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/docshell/base/nsDocShell.cpp"
, 811); return rv; } } while (false)
;
812
813 rv = aLoadState->SetupTriggeringPrincipal(
814 mBrowsingContext->OriginAttributesRef());
815 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/docshell/base/nsDocShell.cpp"
, 815); return rv; } } while (false)
;
816
817 aLoadState->CalculateLoadURIFlags();
818
819 MOZ_ASSERT(aLoadState->TypeHint().IsVoid(),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aLoadState->TypeHint().IsVoid())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aLoadState->TypeHint().IsVoid
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("aLoadState->TypeHint().IsVoid()" " (" "Typehint should be null when calling InternalLoad from LoadURI"
")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 820); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->TypeHint().IsVoid()"
") (" "Typehint should be null when calling InternalLoad from LoadURI"
")"); do { *((volatile int*)__null) = 820; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
820 "Typehint should be null when calling InternalLoad from LoadURI")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aLoadState->TypeHint().IsVoid())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aLoadState->TypeHint().IsVoid
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("aLoadState->TypeHint().IsVoid()" " (" "Typehint should be null when calling InternalLoad from LoadURI"
")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 820); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->TypeHint().IsVoid()"
") (" "Typehint should be null when calling InternalLoad from LoadURI"
")"); do { *((volatile int*)__null) = 820; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
821 MOZ_ASSERT(aLoadState->FileName().IsVoid(),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aLoadState->FileName().IsVoid())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aLoadState->FileName().IsVoid
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("aLoadState->FileName().IsVoid()" " (" "FileName should be null when calling InternalLoad from LoadURI"
")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 822); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->FileName().IsVoid()"
") (" "FileName should be null when calling InternalLoad from LoadURI"
")"); do { *((volatile int*)__null) = 822; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
822 "FileName should be null when calling InternalLoad from LoadURI")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aLoadState->FileName().IsVoid())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aLoadState->FileName().IsVoid
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("aLoadState->FileName().IsVoid()" " (" "FileName should be null when calling InternalLoad from LoadURI"
")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 822); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->FileName().IsVoid()"
") (" "FileName should be null when calling InternalLoad from LoadURI"
")"); do { *((volatile int*)__null) = 822; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
823 MOZ_ASSERT(!aLoadState->LoadIsFromSessionHistory(),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aLoadState->LoadIsFromSessionHistory())>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(!aLoadState->LoadIsFromSessionHistory()))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("!aLoadState->LoadIsFromSessionHistory()"
" (" "Shouldn't be loading from an entry when calling InternalLoad "
"from LoadURI" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 825); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aLoadState->LoadIsFromSessionHistory()"
") (" "Shouldn't be loading from an entry when calling InternalLoad "
"from LoadURI" ")"); do { *((volatile int*)__null) = 825; __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
824 "Shouldn't be loading from an entry when calling InternalLoad "do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aLoadState->LoadIsFromSessionHistory())>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(!aLoadState->LoadIsFromSessionHistory()))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("!aLoadState->LoadIsFromSessionHistory()"
" (" "Shouldn't be loading from an entry when calling InternalLoad "
"from LoadURI" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 825); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aLoadState->LoadIsFromSessionHistory()"
") (" "Shouldn't be loading from an entry when calling InternalLoad "
"from LoadURI" ")"); do { *((volatile int*)__null) = 825; __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
825 "from LoadURI")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aLoadState->LoadIsFromSessionHistory())>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(!aLoadState->LoadIsFromSessionHistory()))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("!aLoadState->LoadIsFromSessionHistory()"
" (" "Shouldn't be loading from an entry when calling InternalLoad "
"from LoadURI" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 825); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aLoadState->LoadIsFromSessionHistory()"
") (" "Shouldn't be loading from an entry when calling InternalLoad "
"from LoadURI" ")"); do { *((volatile int*)__null) = 825; __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
;
826
827 // If we have a system triggering principal, we can assume that this load was
828 // triggered by some UI in the browser chrome, such as the URL bar or
829 // bookmark bar. This should count as a user interaction for the current sh
830 // entry, so that the user may navigate back to the current entry, from the
831 // entry that is going to be added as part of this load.
832 nsCOMPtr<nsIPrincipal> triggeringPrincipal =
833 aLoadState->TriggeringPrincipal();
834 if (triggeringPrincipal && triggeringPrincipal->IsSystemPrincipal()) {
835 if (mozilla::SessionHistoryInParent()) {
836 WindowContext* topWc = mBrowsingContext->GetTopWindowContext();
837 if (topWc && !topWc->IsDiscarded()) {
838 MOZ_ALWAYS_SUCCEEDS(topWc->SetSHEntryHasUserInteraction(true))do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(topWc->SetSHEntryHasUserInteraction(true))), 1)))), 1))) {
} else { do { static_assert( mozilla::detail::AssertionConditionType
<decltype(false)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("false" " (" "NS_SUCCEEDED(topWc->SetSHEntryHasUserInteraction(true))"
")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 838); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "false"
") (" "NS_SUCCEEDED(topWc->SetSHEntryHasUserInteraction(true))"
")"); do { *((volatile int*)__null) = 838; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
839 }
840 } else {
841 bool oshe = false;
842 nsCOMPtr<nsISHEntry> currentSHEntry;
843 GetCurrentSHEntry(getter_AddRefs(currentSHEntry), &oshe);
844 if (currentSHEntry) {
845 currentSHEntry->SetHasUserInteraction(true);
846 }
847 }
848 }
849
850 rv = InternalLoad(aLoadState);
851 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/docshell/base/nsDocShell.cpp"
, 851); return rv; } } while (false)
;
852
853 if (aLoadState->GetOriginalURIString().isSome()) {
854 // Save URI string in case it's needed later when
855 // sending to search engine service in EndPageLoad()
856 mOriginalUriString = *aLoadState->GetOriginalURIString();
857 }
858
859 return NS_OK;
860}
861
862bool nsDocShell::IsLoadingFromSessionHistory() {
863 return mActiveEntryIsLoadingFromSessionHistory;
864}
865
866// StopDetector is modeled similarly to OnloadBlocker; it is a rather
867// dummy nsIRequest implementation which can be added to an nsILoadGroup to
868// detect Cancel calls.
869class StopDetector final : public nsIRequest {
870 public:
871 StopDetector() = default;
872
873 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:
874 NS_DECL_NSIREQUESTvirtual nsresult GetName(nsACString& aName) override; virtual
nsresult IsPending(bool *_retval) override; virtual nsresult
GetStatus(nsresult *aStatus) override; virtual nsresult Cancel
(nsresult aStatus) override; virtual nsresult Suspend(void) override
; virtual nsresult Resume(void) override; virtual nsresult GetLoadGroup
(nsILoadGroup **aLoadGroup) override; virtual nsresult SetLoadGroup
(nsILoadGroup *aLoadGroup) override; virtual nsresult GetLoadFlags
(nsLoadFlags *aLoadFlags) override; virtual nsresult SetLoadFlags
(nsLoadFlags aLoadFlags) override; virtual nsresult GetTRRMode
(nsIRequest::TRRMode *_retval) override; virtual nsresult SetTRRMode
(nsIRequest::TRRMode mode) override; virtual nsresult CancelWithReason
(nsresult aStatus, const nsACString& aReason) override; virtual
nsresult GetCanceledReason(nsACString& aCanceledReason) override
; virtual nsresult SetCanceledReason(const nsACString& aCanceledReason
) override;
875
876 bool Canceled() { return mCanceled; }
877
878 private:
879 ~StopDetector() = default;
880
881 bool mCanceled = false;
882};
883
884NS_IMPL_ISUPPORTS(StopDetector, nsIRequest)MozExternalRefCountType StopDetector::AddRef(void) { static_assert
(!std::is_destructible_v<StopDetector>, "Reference-counted class "
"StopDetector" " 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/docshell/base/nsDocShell.cpp"
, 884); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { *((volatile int*)__null) =
884; __attribute__((nomerge)) ::abort(); } while (false); } }
while (false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("StopDetector" != nullptr)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!("StopDetector" != nullptr)))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("\"StopDetector\" != nullptr"
" (" "Must specify a name" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 884); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"StopDetector\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 884; __attribute__((nomerge)) ::abort(); } while (false);
} } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread
.AssertOwnership("StopDetector" " not thread-safe"); nsrefcnt
count = ++mRefCnt; NS_LogAddRef((this), (count), ("StopDetector"
), (uint32_t)(sizeof(*this))); return count; } MozExternalRefCountType
StopDetector::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/docshell/base/nsDocShell.cpp"
, 884); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { *((volatile int*)__null) = 884
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("StopDetector" != nullptr)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!("StopDetector" != nullptr)))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("\"StopDetector\" != nullptr"
" (" "Must specify a name" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 884); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"StopDetector\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 884; __attribute__((nomerge)) ::abort(); } while (false);
} } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread
.AssertOwnership("StopDetector" " not thread-safe"); const char
* const nametmp = "StopDetector"; nsrefcnt count = --mRefCnt;
NS_LogRelease((this), (count), (nametmp)); if (count == 0) {
mRefCnt = 1; delete (this); return 0; } return count; } nsresult
StopDetector::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/docshell/base/nsDocShell.cpp"
, 884); 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<StopDetector, nsIRequest>, int32_t( reinterpret_cast
<char*>(static_cast<nsIRequest*>((StopDetector*)0x1000
)) - reinterpret_cast<char*>((StopDetector*)0x1000))}, {
&mozilla::detail::kImplementedIID<StopDetector, nsISupports
>, int32_t(reinterpret_cast<char*>(static_cast<nsISupports
*>( static_cast<nsIRequest*>((StopDetector*)0x1000))
) - reinterpret_cast<char*>((StopDetector*)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; }
885
886NS_IMETHODIMPnsresult
887StopDetector::GetName(nsACString& aResult) {
888 aResult.AssignLiteral("about:stop-detector");
889 return NS_OK;
890}
891
892NS_IMETHODIMPnsresult
893StopDetector::IsPending(bool* aRetVal) {
894 *aRetVal = true;
895 return NS_OK;
896}
897
898NS_IMETHODIMPnsresult
899StopDetector::GetStatus(nsresult* aStatus) {
900 *aStatus = NS_OK;
901 return NS_OK;
902}
903
904NS_IMETHODIMPnsresult StopDetector::SetCanceledReason(const nsACString& aReason) {
905 return SetCanceledReasonImpl(aReason);
906}
907
908NS_IMETHODIMPnsresult StopDetector::GetCanceledReason(nsACString& aReason) {
909 return GetCanceledReasonImpl(aReason);
910}
911
912NS_IMETHODIMPnsresult StopDetector::CancelWithReason(nsresult aStatus,
913 const nsACString& aReason) {
914 return CancelWithReasonImpl(aStatus, aReason);
915}
916
917NS_IMETHODIMPnsresult
918StopDetector::Cancel(nsresult aStatus) {
919 mCanceled = true;
920 return NS_OK;
921}
922
923NS_IMETHODIMPnsresult
924StopDetector::Suspend(void) { return NS_OK; }
925NS_IMETHODIMPnsresult
926StopDetector::Resume(void) { return NS_OK; }
927
928NS_IMETHODIMPnsresult
929StopDetector::GetLoadGroup(nsILoadGroup** aLoadGroup) {
930 *aLoadGroup = nullptr;
931 return NS_OK;
932}
933
934NS_IMETHODIMPnsresult
935StopDetector::SetLoadGroup(nsILoadGroup* aLoadGroup) { return NS_OK; }
936
937NS_IMETHODIMPnsresult
938StopDetector::GetLoadFlags(nsLoadFlags* aLoadFlags) {
939 *aLoadFlags = nsIRequest::LOAD_NORMAL;
940 return NS_OK;
941}
942
943NS_IMETHODIMPnsresult
944StopDetector::GetTRRMode(nsIRequest::TRRMode* aTRRMode) {
945 return GetTRRModeImpl(aTRRMode);
946}
947
948NS_IMETHODIMPnsresult
949StopDetector::SetTRRMode(nsIRequest::TRRMode aTRRMode) {
950 return SetTRRModeImpl(aTRRMode);
951}
952
953NS_IMETHODIMPnsresult
954StopDetector::SetLoadFlags(nsLoadFlags aLoadFlags) { return NS_OK; }
955
956bool nsDocShell::MaybeHandleSubframeHistory(
957 nsDocShellLoadState* aLoadState, bool aContinueHandlingSubframeHistory) {
958 // First, verify if this is a subframe.
959 // Note, it is ok to rely on docshell here and not browsing context since when
960 // an iframe is created, it has first in-process docshell.
961 nsCOMPtr<nsIDocShellTreeItem> parentAsItem;
962 GetInProcessSameTypeParent(getter_AddRefs(parentAsItem));
963 nsCOMPtr<nsIDocShell> parentDS(do_QueryInterface(parentAsItem));
964
965 if (!parentDS || parentDS == static_cast<nsIDocShell*>(this)) {
966 if (mBrowsingContext && mBrowsingContext->IsTop()) {
967 // This is the root docshell. If we got here while
968 // executing an onLoad Handler,this load will not go
969 // into session history.
970 // XXX Why is this code in a method which deals with iframes!
971 if (aLoadState->IsFormSubmission()) {
972#ifdef DEBUG1
973 if (!mEODForCurrentDocument) {
974 const MaybeDiscarded<BrowsingContext>& targetBC =
975 aLoadState->TargetBrowsingContext();
976 MOZ_ASSERT_IF(GetBrowsingContext() == targetBC.get(),do { if (GetBrowsingContext() == targetBC.get()) { do { static_assert
( mozilla::detail::AssertionConditionType<decltype(aLoadState
->LoadType() == LOAD_NORMAL_REPLACE)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aLoadState->LoadType() ==
LOAD_NORMAL_REPLACE))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("aLoadState->LoadType() == LOAD_NORMAL_REPLACE", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 977); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->LoadType() == LOAD_NORMAL_REPLACE"
")"); do { *((volatile int*)__null) = 977; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
977 aLoadState->LoadType() == LOAD_NORMAL_REPLACE)do { if (GetBrowsingContext() == targetBC.get()) { do { static_assert
( mozilla::detail::AssertionConditionType<decltype(aLoadState
->LoadType() == LOAD_NORMAL_REPLACE)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aLoadState->LoadType() ==
LOAD_NORMAL_REPLACE))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("aLoadState->LoadType() == LOAD_NORMAL_REPLACE", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 977); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->LoadType() == LOAD_NORMAL_REPLACE"
")"); do { *((volatile int*)__null) = 977; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
978 }
979#endif
980 } else {
981 bool inOnLoadHandler = false;
982 GetIsExecutingOnLoadHandler(&inOnLoadHandler);
983 if (inOnLoadHandler) {
984 aLoadState->SetLoadType(LOAD_NORMAL_REPLACE);
985 }
986 }
987 }
988 return false;
989 }
990
991 /* OK. It is a subframe. Checkout the parent's loadtype. If the parent was
992 * loaded through a history mechanism, then get the SH entry for the child
993 * from the parent. This is done to restore frameset navigation while going
994 * back/forward. If the parent was loaded through any other loadType, set the
995 * child's loadType too accordingly, so that session history does not get
996 * confused.
997 */
998
999 // Get the parent's load type
1000 uint32_t parentLoadType;
1001 parentDS->GetLoadType(&parentLoadType);
1002
1003 if (!aContinueHandlingSubframeHistory) {
1004 if (mozilla::SessionHistoryInParent()) {
1005 if (nsDocShell::Cast(parentDS.get())->IsLoadingFromSessionHistory() &&
1006 !GetCreatedDynamically()) {
1007 if (XRE_IsContentProcess()) {
1008 dom::ContentChild* contentChild = dom::ContentChild::GetSingleton();
1009 nsCOMPtr<nsILoadGroup> loadGroup;
1010 GetLoadGroup(getter_AddRefs(loadGroup));
1011 if (contentChild && loadGroup && !mCheckingSessionHistory) {
1012 RefPtr<Document> parentDoc = parentDS->GetDocument();
1013 parentDoc->BlockOnload();
1014 RefPtr<BrowsingContext> browsingContext = mBrowsingContext;
1015 Maybe<uint64_t> currentLoadIdentifier =
1016 mBrowsingContext->GetCurrentLoadIdentifier();
1017 RefPtr<nsDocShellLoadState> loadState = aLoadState;
1018 bool isNavigating = mIsNavigating;
1019 RefPtr<StopDetector> stopDetector = new StopDetector();
1020 loadGroup->AddRequest(stopDetector, nullptr);
1021 // Need to set mCheckingSessionHistory so that
1022 // GetIsAttemptingToNavigate() returns true.
1023 mCheckingSessionHistory = true;
1024
1025 auto resolve =
1026 [currentLoadIdentifier, browsingContext, parentDoc, loadState,
1027 isNavigating, loadGroup, stopDetector](
1028 mozilla::Maybe<LoadingSessionHistoryInfo>&& aResult) {
1029 RefPtr<nsDocShell> docShell =
1030 static_cast<nsDocShell*>(browsingContext->GetDocShell());
1031 auto unblockParent = MakeScopeExit(
1032 [loadGroup, stopDetector, parentDoc, docShell]() {
1033 if (docShell) {
1034 docShell->mCheckingSessionHistory = false;
1035 }
1036 loadGroup->RemoveRequest(stopDetector, nullptr, NS_OK);
1037 parentDoc->UnblockOnload(false);
1038 });
1039
1040 if (!docShell || !docShell->mCheckingSessionHistory) {
1041 return;
1042 }
1043
1044 if (stopDetector->Canceled()) {
1045 return;
1046 }
1047 if (currentLoadIdentifier ==
1048 browsingContext->GetCurrentLoadIdentifier() &&
1049 aResult.isSome()) {
1050 loadState->SetLoadingSessionHistoryInfo(aResult.value());
1051 // This is an initial subframe load from the session
1052 // history, index doesn't need to be updated.
1053 loadState->SetLoadIsFromSessionHistory(0, false);
1054 }
1055
1056 // We got the results back from the parent process, call
1057 // LoadURI again with the possibly updated data.
1058 docShell->LoadURI(loadState, isNavigating, true);
1059 };
1060 auto reject = [loadGroup, stopDetector, browsingContext,
1061 parentDoc](mozilla::ipc::ResponseRejectReason) {
1062 RefPtr<nsDocShell> docShell =
1063 static_cast<nsDocShell*>(browsingContext->GetDocShell());
1064 if (docShell) {
1065 docShell->mCheckingSessionHistory = false;
1066 }
1067 // In practise reject shouldn't be called ever.
1068 loadGroup->RemoveRequest(stopDetector, nullptr, NS_OK);
1069 parentDoc->UnblockOnload(false);
1070 };
1071 contentChild->SendGetLoadingSessionHistoryInfoFromParent(
1072 mBrowsingContext, std::move(resolve), std::move(reject));
1073 return true;
1074 }
1075 } else {
1076 Maybe<LoadingSessionHistoryInfo> info;
1077 mBrowsingContext->Canonical()->GetLoadingSessionHistoryInfoFromParent(
1078 info);
1079 if (info.isSome()) {
1080 aLoadState->SetLoadingSessionHistoryInfo(info.value());
1081 // This is an initial subframe load from the session
1082 // history, index doesn't need to be updated.
1083 aLoadState->SetLoadIsFromSessionHistory(0, false);
1084 }
1085 }
1086 }
1087 } else {
1088 // Get the ShEntry for the child from the parent
1089 nsCOMPtr<nsISHEntry> currentSH;
1090 bool oshe = false;
1091 parentDS->GetCurrentSHEntry(getter_AddRefs(currentSH), &oshe);
1092 bool dynamicallyAddedChild = GetCreatedDynamically();
1093
1094 if (!dynamicallyAddedChild && !oshe && currentSH) {
1095 // Only use the old SHEntry, if we're sure enough that
1096 // it wasn't originally for some other frame.
1097 nsCOMPtr<nsISHEntry> shEntry;
1098 currentSH->GetChildSHEntryIfHasNoDynamicallyAddedChild(
1099 mBrowsingContext->ChildOffset(), getter_AddRefs(shEntry));
1100 if (shEntry) {
1101 aLoadState->SetSHEntry(shEntry);
1102 }
1103 }
1104 }
1105 }
1106
1107 // Make some decisions on the child frame's loadType based on the
1108 // parent's loadType, if the subframe hasn't loaded anything into it.
1109 //
1110 // In some cases privileged scripts may try to get the DOMWindow
1111 // reference of this docshell before the loading starts, causing the
1112 // initial about:blank content viewer being created and mCurrentURI being
1113 // set. To handle this case we check if mCurrentURI is about:blank and
1114 // currentSHEntry is null.
1115 bool oshe = false;
1116 nsCOMPtr<nsISHEntry> currentChildEntry;
1117 GetCurrentSHEntry(getter_AddRefs(currentChildEntry), &oshe);
1118
1119 if (mCurrentURI && (!NS_IsAboutBlank(mCurrentURI) || currentChildEntry ||
1120 mLoadingEntry || mActiveEntry)) {
1121 // This is a pre-existing subframe. If
1122 // 1. The load of this frame was not originally initiated by session
1123 // history directly (i.e. (!shEntry) condition succeeded, but it can
1124 // still be a history load on parent which causes this frame being
1125 // loaded), which we checked with the above assert, and
1126 // 2. mCurrentURI is not null, nor the initial about:blank,
1127 // it is possible that a parent's onLoadHandler or even self's
1128 // onLoadHandler is loading a new page in this child. Check parent's and
1129 // self's busy flag and if it is set, we don't want this onLoadHandler
1130 // load to get in to session history.
1131 BusyFlags parentBusy = parentDS->GetBusyFlags();
1132 BusyFlags selfBusy = GetBusyFlags();
1133
1134 if (parentBusy & BUSY_FLAGS_BUSY || selfBusy & BUSY_FLAGS_BUSY) {
1135 aLoadState->SetLoadType(LOAD_NORMAL_REPLACE);
1136 aLoadState->ClearLoadIsFromSessionHistory();
1137 }
1138 return false;
1139 }
1140
1141 // This is a newly created frame. Check for exception cases first.
1142 // By default the subframe will inherit the parent's loadType.
1143 if (aLoadState->LoadIsFromSessionHistory() &&
1144 (parentLoadType == LOAD_NORMAL || parentLoadType == LOAD_LINK)) {
1145 // The parent was loaded normally. In this case, this *brand new*
1146 // child really shouldn't have a SHEntry. If it does, it could be
1147 // because the parent is replacing an existing frame with a new frame,
1148 // in the onLoadHandler. We don't want this url to get into session
1149 // history. Clear off shEntry, and set load type to
1150 // LOAD_BYPASS_HISTORY.
1151 bool inOnLoadHandler = false;
1152 parentDS->GetIsExecutingOnLoadHandler(&inOnLoadHandler);
1153 if (inOnLoadHandler) {
1154 aLoadState->SetLoadType(LOAD_NORMAL_REPLACE);
1155 aLoadState->ClearLoadIsFromSessionHistory();
1156 }
1157 } else if (parentLoadType == LOAD_REFRESH) {
1158 // Clear shEntry. For refresh loads, we have to load
1159 // what comes through the pipe, not what's in history.
1160 aLoadState->ClearLoadIsFromSessionHistory();
1161 } else if ((parentLoadType == LOAD_BYPASS_HISTORY) ||
1162 (aLoadState->LoadIsFromSessionHistory() &&
1163 ((parentLoadType & LOAD_CMD_HISTORY) ||
1164 (parentLoadType == LOAD_RELOAD_NORMAL) ||
1165 (parentLoadType == LOAD_RELOAD_CHARSET_CHANGE) ||
1166 (parentLoadType == LOAD_RELOAD_CHARSET_CHANGE_BYPASS_CACHE) ||
1167 (parentLoadType ==
1168 LOAD_RELOAD_CHARSET_CHANGE_BYPASS_PROXY_AND_CACHE)))) {
1169 // If the parent url, bypassed history or was loaded from
1170 // history, pass on the parent's loadType to the new child
1171 // frame too, so that the child frame will also
1172 // avoid getting into history.
1173 aLoadState->SetLoadType(parentLoadType);
1174 } else if (parentLoadType == LOAD_ERROR_PAGE) {
1175 // If the parent document is an error page, we don't
1176 // want to update global/session history. However,
1177 // this child frame is not an error page.
1178 aLoadState->SetLoadType(LOAD_BYPASS_HISTORY);
1179 } else if ((parentLoadType == LOAD_RELOAD_BYPASS_CACHE) ||
1180 (parentLoadType == LOAD_RELOAD_BYPASS_PROXY) ||
1181 (parentLoadType == LOAD_RELOAD_BYPASS_PROXY_AND_CACHE)) {
1182 // the new frame should inherit the parent's load type so that it also
1183 // bypasses the cache and/or proxy
1184 aLoadState->SetLoadType(parentLoadType);
1185 }
1186
1187 return false;
1188}
1189
1190/*
1191 * Reset state to a new content model within the current document and the
1192 * document viewer. Called by the document before initiating an out of band
1193 * document.write().
1194 */
1195NS_IMETHODIMPnsresult
1196nsDocShell::PrepareForNewContentModel() {
1197 // Clear out our form control state, because the state of controls
1198 // in the pre-open() document should not affect the state of
1199 // controls that are now going to be written.
1200 SetLayoutHistoryState(nullptr);
1201 mEODForCurrentDocument = false;
1202 return NS_OK;
1203}
1204
1205NS_IMETHODIMPnsresult
1206nsDocShell::FirePageHideNotification(bool aIsUnload) {
1207 FirePageHideNotificationInternal(aIsUnload, false);
1208 return NS_OK;
1209}
1210
1211void nsDocShell::FirePageHideNotificationInternal(
1212 bool aIsUnload, bool aSkipCheckingDynEntries) {
1213 if (mDocumentViewer && !mFiredUnloadEvent) {
1214 // Keep an explicit reference since calling PageHide could release
1215 // mDocumentViewer
1216 nsCOMPtr<nsIDocumentViewer> viewer(mDocumentViewer);
1217 mFiredUnloadEvent = true;
1218
1219 if (mTiming) {
1220 mTiming->NotifyUnloadEventStart();
1221 }
1222
1223 viewer->PageHide(aIsUnload);
1224
1225 if (mTiming) {
1226 mTiming->NotifyUnloadEventEnd();
1227 }
1228
1229 AutoTArray<nsCOMPtr<nsIDocShell>, 8> kids;
1230 uint32_t n = mChildList.Length();
1231 kids.SetCapacity(n);
1232 for (uint32_t i = 0; i < n; i++) {
1233 kids.AppendElement(do_QueryInterface(ChildAt(i)));
1234 }
1235
1236 n = kids.Length();
1237 for (uint32_t i = 0; i < n; ++i) {
1238 RefPtr<nsDocShell> child = static_cast<nsDocShell*>(kids[i].get());
1239 if (child) {
1240 // Skip checking dynamic subframe entries in our children.
1241 child->FirePageHideNotificationInternal(aIsUnload, true);
1242 }
1243 }
1244
1245 // If the document is unloading, remove all dynamic subframe entries.
1246 if (aIsUnload && !aSkipCheckingDynEntries) {
1247 RefPtr<ChildSHistory> rootSH = GetRootSessionHistory();
1248 if (rootSH) {
1249 MOZ_LOG(do { const ::mozilla::LogModule* moz_real_module = gSHLog; if
((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "nsDocShell %p unloading, remove dynamic subframe entries"
, this); } } while (0)
1250 gSHLog, LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = gSHLog; if
((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "nsDocShell %p unloading, remove dynamic subframe entries"
, this); } } while (0)
1251 ("nsDocShell %p unloading, remove dynamic subframe entries", this))do { const ::mozilla::LogModule* moz_real_module = gSHLog; if
((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "nsDocShell %p unloading, remove dynamic subframe entries"
, this); } } while (0)
;
1252 if (mozilla::SessionHistoryInParent()) {
1253 if (mActiveEntry) {
1254 mBrowsingContext->RemoveDynEntriesFromActiveSessionHistoryEntry();
1255 }
1256 MOZ_LOG(gSHLog, LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = gSHLog; if
((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "nsDocShell %p unloading, no active entries"
, this); } } while (0)
1257 ("nsDocShell %p unloading, no active entries", this))do { const ::mozilla::LogModule* moz_real_module = gSHLog; if
((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "nsDocShell %p unloading, no active entries"
, this); } } while (0)
;
1258 } else if (mOSHE) {
1259 int32_t index = rootSH->Index();
1260 rootSH->LegacySHistory()->RemoveDynEntries(index, mOSHE);
1261 }
1262 }
1263 }
1264
1265 // Now make sure our editor, if any, is detached before we go
1266 // any farther.
1267 DetachEditorFromWindow();
1268 }
1269}
1270
1271void nsDocShell::ThawFreezeNonRecursive(bool aThaw) {
1272 MOZ_ASSERT(mozilla::BFCacheInParent())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mozilla::BFCacheInParent())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mozilla::BFCacheInParent()))
), 0))) { do { } while (false); MOZ_ReportAssertionFailure("mozilla::BFCacheInParent()"
, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 1272); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mozilla::BFCacheInParent()"
")"); do { *((volatile int*)__null) = 1272; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1273
1274 if (!mScriptGlobal) {
1275 return;
1276 }
1277
1278 if (RefPtr<nsGlobalWindowInner> inner =
1279 nsGlobalWindowInner::Cast(mScriptGlobal->GetCurrentInnerWindow())) {
1280 if (aThaw) {
1281 inner->Thaw(false);
1282 } else {
1283 inner->Freeze(false);
1284 }
1285 }
1286}
1287
1288void nsDocShell::FirePageHideShowNonRecursive(bool aShow) {
1289 MOZ_ASSERT(mozilla::BFCacheInParent())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mozilla::BFCacheInParent())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mozilla::BFCacheInParent()))
), 0))) { do { } while (false); MOZ_ReportAssertionFailure("mozilla::BFCacheInParent()"
, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 1289); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mozilla::BFCacheInParent()"
")"); do { *((volatile int*)__null) = 1289; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1290
1291 if (!mDocumentViewer) {
1292 return;
1293 }
1294
1295 // Emulate what non-SHIP BFCache does too. In pageshow case
1296 // add and remove a request and before that call SetCurrentURI to get
1297 // the location change notification.
1298 // For pagehide, set mFiredUnloadEvent to true, so that unload doesn't fire.
1299 nsCOMPtr<nsIDocumentViewer> viewer(mDocumentViewer);
1300 if (aShow) {
1301 viewer->SetIsHidden(false);
1302 mRefreshURIList = std::move(mBFCachedRefreshURIList);
1303 RefreshURIFromQueue();
1304 mFiredUnloadEvent = false;
1305 RefPtr<Document> doc = viewer->GetDocument();
1306 if (doc) {
1307 doc->NotifyActivityChanged();
1308 nsCOMPtr<nsPIDOMWindowInner> inner =
1309 mScriptGlobal ? mScriptGlobal->GetCurrentInnerWindow() : nullptr;
1310 if (mBrowsingContext->IsTop()) {
1311 doc->NotifyPossibleTitleChange(false);
1312 doc->SetLoadingOrRestoredFromBFCacheTimeStampToNow();
1313 if (inner) {
1314 // Now that we have found the inner window of the page restored
1315 // from the history, we have to make sure that
1316 // performance.navigation.type is 2.
1317 // Traditionally this type change has been done to the top level page
1318 // only.
1319 Performance* performance = inner->GetPerformance();
1320 if (performance) {
1321 performance->GetDOMTiming()->NotifyRestoreStart();
1322 }
1323 }
1324 }
1325
1326 nsCOMPtr<nsIChannel> channel = doc->GetChannel();
1327 if (channel) {
1328 SetLoadType(LOAD_HISTORY);
1329 mEODForCurrentDocument = false;
1330 mIsRestoringDocument = true;
1331 mLoadGroup->AddRequest(channel, nullptr);
1332 nsCOMPtr<nsIURI> uri;
1333 if (doc->FragmentDirective()) {
1334 // If we have fragment directives, then we've mutated the document
1335 // uri. Set the current URI from session history instead.
1336 if (mozilla::SessionHistoryInParent()) {
1337 uri = mActiveEntry ? mActiveEntry->GetURI() : nullptr;
1338 } else if (mOSHE) {
1339 uri = mOSHE->GetURI();
1340 }
1341 }
1342 if (!uri) {
1343 uri = doc->GetDocumentURI();
1344 }
1345 SetCurrentURI(uri, channel,
1346 /* aFireOnLocationChange */ true,
1347 /* aIsInitialAboutBlank */ false,
1348 /* aLocationFlags */ 0);
1349 mLoadGroup->RemoveRequest(channel, nullptr, NS_OK);
1350 mIsRestoringDocument = false;
1351 }
1352 RefPtr<PresShell> presShell = GetPresShell();
1353 if (presShell) {
1354 presShell->Thaw(false);
1355 }
1356
1357 if (inner) {
1358 inner->FireDelayedDOMEvents(false);
1359 }
1360 }
1361 } else if (!mFiredUnloadEvent) {
1362 // XXXBFCache check again that the page can enter bfcache.
1363 // XXXBFCache should mTiming->NotifyUnloadEventStart()/End() be called here?
1364
1365 if (mRefreshURIList) {
1366 RefreshURIToQueue();
1367 mBFCachedRefreshURIList = std::move(mRefreshURIList);
1368 } else {
1369 // If Stop was called, the list was moved to mSavedRefreshURIList after
1370 // calling SuspendRefreshURIs, which calls RefreshURIToQueue.
1371 mBFCachedRefreshURIList = std::move(mSavedRefreshURIList);
1372 }
1373
1374 mFiredUnloadEvent = true;
1375 viewer->PageHide(false);
1376
1377 RefPtr<PresShell> presShell = GetPresShell();
1378 if (presShell) {
1379 presShell->Freeze(false);
1380 }
1381 }
1382}
1383
1384nsresult nsDocShell::Dispatch(already_AddRefed<nsIRunnable>&& aRunnable) {
1385 nsCOMPtr<nsIRunnable> runnable(aRunnable);
1386 if (NS_WARN_IF(!GetWindow())NS_warn_if_impl(!GetWindow(), "!GetWindow()", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 1386)
) {
1387 // Window should only be unavailable after destroyed.
1388 MOZ_ASSERT(mIsBeingDestroyed)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mIsBeingDestroyed)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mIsBeingDestroyed))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("mIsBeingDestroyed"
, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 1388); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mIsBeingDestroyed"
")"); do { *((volatile int*)__null) = 1388; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1389 return NS_ERROR_FAILURE;
1390 }
1391 return SchedulerGroup::Dispatch(runnable.forget());
1392}
1393
1394NS_IMETHODIMPnsresult
1395nsDocShell::DispatchLocationChangeEvent() {
1396 return Dispatch(NewRunnableMethod("nsDocShell::FireDummyOnLocationChange",
1397 this,
1398 &nsDocShell::FireDummyOnLocationChange));
1399}
1400
1401NS_IMETHODIMPnsresult
1402nsDocShell::StartDelayedAutoplayMediaComponents() {
1403 RefPtr<nsPIDOMWindowOuter> outerWindow = GetWindow();
1404 if (outerWindow) {
1405 outerWindow->ActivateMediaComponents();
1406 }
1407 return NS_OK;
1408}
1409
1410bool nsDocShell::MaybeInitTiming() {
1411 if (mTiming && !mBlankTiming) {
1412 return false;
1413 }
1414
1415 bool canBeReset = false;
1416
1417 if (mScriptGlobal && mBlankTiming) {
1418 nsPIDOMWindowInner* innerWin = mScriptGlobal->GetCurrentInnerWindow();
1419 if (innerWin && innerWin->GetPerformance()) {
1420 mTiming = innerWin->GetPerformance()->GetDOMTiming();
1421 mBlankTiming = false;
1422 }
1423 }
1424
1425 if (!mTiming) {
1426 mTiming = new nsDOMNavigationTiming(this);
1427 canBeReset = true;
1428 }
1429
1430 mTiming->NotifyNavigationStart(
1431 mBrowsingContext->IsActive()
1432 ? nsDOMNavigationTiming::DocShellState::eActive
1433 : nsDOMNavigationTiming::DocShellState::eInactive);
1434
1435 return canBeReset;
1436}
1437
1438void nsDocShell::MaybeResetInitTiming(bool aReset) {
1439 if (aReset) {
1440 mTiming = nullptr;
1441 }
1442}
1443
1444nsDOMNavigationTiming* nsDocShell::GetNavigationTiming() const {
1445 return mTiming;
1446}
1447
1448nsPresContext* nsDocShell::GetEldestPresContext() {
1449 nsIDocumentViewer* viewer = mDocumentViewer;
1450 while (viewer) {
1451 nsIDocumentViewer* prevViewer = viewer->GetPreviousViewer();
1452 if (!prevViewer) {
1453 return viewer->GetPresContext();
1454 }
1455 viewer = prevViewer;
1456 }
1457
1458 return nullptr;
1459}
1460
1461nsPresContext* nsDocShell::GetPresContext() {
1462 if (!mDocumentViewer) {
1463 return nullptr;
1464 }
1465
1466 return mDocumentViewer->GetPresContext();
1467}
1468
1469PresShell* nsDocShell::GetPresShell() {
1470 nsPresContext* presContext = GetPresContext();
1471 return presContext ? presContext->GetPresShell() : nullptr;
1472}
1473
1474PresShell* nsDocShell::GetEldestPresShell() {
1475 nsPresContext* presContext = GetEldestPresContext();
1476
1477 if (presContext) {
1478 return presContext->GetPresShell();
1479 }
1480
1481 return nullptr;
1482}
1483
1484NS_IMETHODIMPnsresult
1485nsDocShell::GetDocViewer(nsIDocumentViewer** aDocumentViewer) {
1486 NS_ENSURE_ARG_POINTER(aDocumentViewer)do { if ((__builtin_expect(!!(!(aDocumentViewer)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aDocumentViewer" ") failed"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 1486); return NS_ERROR_INVALID_POINTER; } } while (false)
;
1487
1488 *aDocumentViewer = mDocumentViewer;
1489 NS_IF_ADDREF(*aDocumentViewer)ns_if_addref(*aDocumentViewer);
1490 return NS_OK;
1491}
1492
1493NS_IMETHODIMPnsresult
1494nsDocShell::GetOuterWindowID(uint64_t* aWindowID) {
1495 *aWindowID = mContentWindowID;
1496 return NS_OK;
1497}
1498
1499NS_IMETHODIMPnsresult
1500nsDocShell::SetChromeEventHandler(EventTarget* aChromeEventHandler) {
1501 mChromeEventHandler = aChromeEventHandler;
1502
1503 if (mScriptGlobal) {
1504 mScriptGlobal->SetChromeEventHandler(mChromeEventHandler);
1505 }
1506
1507 return NS_OK;
1508}
1509
1510NS_IMETHODIMPnsresult
1511nsDocShell::GetChromeEventHandler(EventTarget** aChromeEventHandler) {
1512 NS_ENSURE_ARG_POINTER(aChromeEventHandler)do { if ((__builtin_expect(!!(!(aChromeEventHandler)), 0))) {
NS_DebugBreak(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aChromeEventHandler"
") failed", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 1512); return NS_ERROR_INVALID_POINTER; } } while (false)
;
1513 RefPtr<EventTarget> handler = mChromeEventHandler;
1514 handler.forget(aChromeEventHandler);
1515 return NS_OK;
1516}
1517
1518NS_IMETHODIMPnsresult
1519nsDocShell::SetCurrentURIForSessionStore(nsIURI* aURI) {
1520 // Note that securityUI will set STATE_IS_INSECURE, even if
1521 // the scheme of |aURI| is "https".
1522 SetCurrentURI(aURI, nullptr,
1523 /* aFireOnLocationChange */
1524 true,
1525 /* aIsInitialAboutBlank */
1526 false,
1527 /* aLocationFlags */
1528 nsIWebProgressListener::LOCATION_CHANGE_SESSION_STORE);
1529 return NS_OK;
1530}
1531
1532bool nsDocShell::SetCurrentURI(nsIURI* aURI, nsIRequest* aRequest,
1533 bool aFireOnLocationChange,
1534 bool aIsInitialAboutBlank,
1535 uint32_t aLocationFlags) {
1536 MOZ_ASSERT(!mIsBeingDestroyed)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mIsBeingDestroyed)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mIsBeingDestroyed))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("!mIsBeingDestroyed"
, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 1536); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mIsBeingDestroyed"
")"); do { *((volatile int*)__null) = 1536; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1537
1538 MOZ_LOG(gDocShellLeakLog, LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = gDocShellLeakLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "DOCSHELL %p SetCurrentURI %s\n", this, aURI
? aURI->GetSpecOrDefault().get() : ""); } } while (0)
1539 ("DOCSHELL %p SetCurrentURI %s\n", this,do { const ::mozilla::LogModule* moz_real_module = gDocShellLeakLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "DOCSHELL %p SetCurrentURI %s\n", this, aURI
? aURI->GetSpecOrDefault().get() : ""); } } while (0)
1540 aURI ? aURI->GetSpecOrDefault().get() : ""))do { const ::mozilla::LogModule* moz_real_module = gDocShellLeakLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "DOCSHELL %p SetCurrentURI %s\n", this, aURI
? aURI->GetSpecOrDefault().get() : ""); } } while (0)
;
1541
1542 // We don't want to send a location change when we're displaying an error
1543 // page, and we don't want to change our idea of "current URI" either
1544 if (mLoadType == LOAD_ERROR_PAGE) {
1545 return false;
1546 }
1547
1548 bool uriIsEqual = false;
1549 if (!mCurrentURI || !aURI ||
1550 NS_FAILED(mCurrentURI->Equals(aURI, &uriIsEqual))((bool)(__builtin_expect(!!(NS_FAILED_impl(mCurrentURI->Equals
(aURI, &uriIsEqual))), 0)))
|| !uriIsEqual) {
1551 mTitleValidForCurrentURI = false;
1552 }
1553
1554 SetCurrentURIInternal(aURI);
1555
1556#ifdef DEBUG1
1557 mLastOpenedURI = aURI;
1558#endif
1559
1560 if (!NS_IsAboutBlank(mCurrentURI)) {
1561 mHasLoadedNonBlankURI = true;
1562 }
1563
1564 // Don't fire onLocationChange when creating a subframe's initial about:blank
1565 // document, as this can happen when it's not safe for us to run script.
1566 if (aIsInitialAboutBlank && !mHasLoadedNonBlankURI &&
1567 !mBrowsingContext->IsTop()) {
1568 MOZ_ASSERT(!aRequest && aLocationFlags == 0)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aRequest && aLocationFlags == 0)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(!aRequest && aLocationFlags == 0))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("!aRequest && aLocationFlags == 0"
, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 1568); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aRequest && aLocationFlags == 0"
")"); do { *((volatile int*)__null) = 1568; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1569 return false;
1570 }
1571
1572 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()", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 1572); AnnotateMozCrashReason("MOZ_ASSERT" "(" "nsContentUtils::IsSafeToRunScript()"
")"); do { *((volatile int*)__null) = 1572; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1573
1574 if (aFireOnLocationChange) {
1575 FireOnLocationChange(this, aRequest, aURI, aLocationFlags);
1576 }
1577 return !aFireOnLocationChange;
1578}
1579
1580void nsDocShell::SetCurrentURIInternal(nsIURI* aURI) {
1581 mCurrentURI = aURI;
1582 if (mBrowsingContext) {
1583 mBrowsingContext->ClearCachedValuesOfLocations();
1584 }
1585}
1586
1587NS_IMETHODIMPnsresult
1588nsDocShell::GetCharset(nsACString& aCharset) {
1589 aCharset.Truncate();
1590
1591 PresShell* presShell = GetPresShell();
1592 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/docshell/base/nsDocShell.cpp"
, 1592); return NS_ERROR_FAILURE; } } while (false)
;
1593 Document* doc = presShell->GetDocument();
1594 NS_ENSURE_TRUE(doc, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(doc)), 0))) { NS_DebugBreak(NS_DEBUG_WARNING
, "NS_ENSURE_TRUE(" "doc" ") failed", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 1594); return NS_ERROR_FAILURE; } } while (false)
;
1595 doc->GetDocumentCharacterSet()->Name(aCharset);
1596 return NS_OK;
1597}
1598
1599NS_IMETHODIMPnsresult
1600nsDocShell::ForceEncodingDetection() {
1601 nsCOMPtr<nsIDocumentViewer> viewer;
1602 GetDocViewer(getter_AddRefs(viewer));
1603 if (!viewer) {
1604 return NS_OK;
1605 }
1606
1607 Document* doc = viewer->GetDocument();
1608 if (!doc || doc->WillIgnoreCharsetOverride()) {
1609 return NS_OK;
1610 }
1611
1612 mForcedAutodetection = true;
1613
1614 nsIURI* url = doc->GetOriginalURI();
1615 bool isFileURL = url && SchemeIsFile(url);
1616
1617 int32_t charsetSource = doc->GetDocumentCharacterSetSource();
1618 auto encoding = doc->GetDocumentCharacterSet();
1619 // AsHTMLDocument is valid, because we called
1620 // WillIgnoreCharsetOverride() above.
1621 if (doc->AsHTMLDocument()->IsPlainText()) {
1622 switch (charsetSource) {
1623 case kCharsetFromInitialAutoDetectionASCII:
1624 // Deliberately no final version
1625 LOGCHARSETMENU(("TEXT:UnlabeledAscii"))do { const ::mozilla::LogModule* moz_real_module = gCharsetMenuLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, "TEXT:UnlabeledAscii"
); } } while (0)
;
1626 break;
1627 case kCharsetFromInitialAutoDetectionWouldNotHaveBeenUTF8Generic:
1628 case kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8Generic:
1629 case kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8GenericInitialWasASCII:
1630 case kCharsetFromInitialAutoDetectionWouldNotHaveBeenUTF8Content:
1631 case kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8Content:
1632 case kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8ContentInitialWasASCII:
1633 LOGCHARSETMENU(("TEXT:UnlabeledNonUtf8"))do { const ::mozilla::LogModule* moz_real_module = gCharsetMenuLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, "TEXT:UnlabeledNonUtf8"
); } } while (0)
;
1634 break;
1635 case kCharsetFromInitialAutoDetectionWouldNotHaveBeenUTF8DependedOnTLD:
1636 case kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8DependedOnTLD:
1637 case kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8DependedOnTLDInitialWasASCII:
1638 LOGCHARSETMENU(("TEXT:UnlabeledNonUtf8TLD"))do { const ::mozilla::LogModule* moz_real_module = gCharsetMenuLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, "TEXT:UnlabeledNonUtf8TLD"
); } } while (0)
;
1639 break;
1640 case kCharsetFromInitialAutoDetectionWouldHaveBeenUTF8:
1641 case kCharsetFromFinalAutoDetectionWouldHaveBeenUTF8InitialWasASCII:
1642 LOGCHARSETMENU(("TEXT:UnlabeledUtf8"))do { const ::mozilla::LogModule* moz_real_module = gCharsetMenuLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, "TEXT:UnlabeledUtf8"
); } } while (0)
;
1643 break;
1644 case kCharsetFromChannel:
1645 if (encoding == UTF_8_ENCODING) {
1646 LOGCHARSETMENU(("TEXT:ChannelUtf8"))do { const ::mozilla::LogModule* moz_real_module = gCharsetMenuLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, "TEXT:ChannelUtf8"
); } } while (0)
;
1647 } else {
1648 LOGCHARSETMENU(("TEXT:ChannelNonUtf8"))do { const ::mozilla::LogModule* moz_real_module = gCharsetMenuLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, "TEXT:ChannelNonUtf8"
); } } while (0)
;
1649 }
1650 break;
1651 default:
1652 LOGCHARSETMENU(("TEXT:Bug"))do { const ::mozilla::LogModule* moz_real_module = gCharsetMenuLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, "TEXT:Bug"); } } while
(0)
;
1653 break;
1654 }
1655 } else {
1656 switch (charsetSource) {
1657 case kCharsetFromInitialAutoDetectionASCII:
1658 // Deliberately no final version
1659 LOGCHARSETMENU(("HTML:UnlabeledAscii"))do { const ::mozilla::LogModule* moz_real_module = gCharsetMenuLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, "HTML:UnlabeledAscii"
); } } while (0)
;
1660 break;
1661 case kCharsetFromInitialAutoDetectionWouldNotHaveBeenUTF8Generic:
1662 case kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8Generic:
1663 case kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8GenericInitialWasASCII:
1664 case kCharsetFromInitialAutoDetectionWouldNotHaveBeenUTF8Content:
1665 case kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8Content:
1666 case kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8ContentInitialWasASCII:
1667 LOGCHARSETMENU(("HTML:UnlabeledNonUtf8"))do { const ::mozilla::LogModule* moz_real_module = gCharsetMenuLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, "HTML:UnlabeledNonUtf8"
); } } while (0)
;
1668 break;
1669 case kCharsetFromInitialAutoDetectionWouldNotHaveBeenUTF8DependedOnTLD:
1670 case kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8DependedOnTLD:
1671 case kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8DependedOnTLDInitialWasASCII:
1672 LOGCHARSETMENU(("HTML:UnlabeledNonUtf8TLD"))do { const ::mozilla::LogModule* moz_real_module = gCharsetMenuLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, "HTML:UnlabeledNonUtf8TLD"
); } } while (0)
;
1673 break;
1674 case kCharsetFromInitialAutoDetectionWouldHaveBeenUTF8:
1675 case kCharsetFromFinalAutoDetectionWouldHaveBeenUTF8InitialWasASCII:
1676 LOGCHARSETMENU(("HTML:UnlabeledUtf8"))do { const ::mozilla::LogModule* moz_real_module = gCharsetMenuLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, "HTML:UnlabeledUtf8"
); } } while (0)
;
1677 break;
1678 case kCharsetFromChannel:
1679 if (encoding == UTF_8_ENCODING) {
1680 LOGCHARSETMENU(("HTML:ChannelUtf8"))do { const ::mozilla::LogModule* moz_real_module = gCharsetMenuLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, "HTML:ChannelUtf8"
); } } while (0)
;
1681 } else {
1682 LOGCHARSETMENU(("HTML:ChannelNonUtf8"))do { const ::mozilla::LogModule* moz_real_module = gCharsetMenuLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, "HTML:ChannelNonUtf8"
); } } while (0)
;
1683 }
1684 break;
1685 case kCharsetFromXmlDeclaration:
1686 case kCharsetFromMetaTag:
1687 if (isFileURL) {
1688 LOGCHARSETMENU(("HTML:LocalLabeled"))do { const ::mozilla::LogModule* moz_real_module = gCharsetMenuLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, "HTML:LocalLabeled"
); } } while (0)
;
1689 } else if (encoding == UTF_8_ENCODING) {
1690 LOGCHARSETMENU(("HTML:MetaUtf8"))do { const ::mozilla::LogModule* moz_real_module = gCharsetMenuLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, "HTML:MetaUtf8");
} } while (0)
;
1691 } else {
1692 LOGCHARSETMENU(("HTML:MetaNonUtf8"))do { const ::mozilla::LogModule* moz_real_module = gCharsetMenuLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, "HTML:MetaNonUtf8"
); } } while (0)
;
1693 }
1694 break;
1695 default:
1696 LOGCHARSETMENU(("HTML:Bug"))do { const ::mozilla::LogModule* moz_real_module = gCharsetMenuLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, "HTML:Bug"); } } while
(0)
;
1697 break;
1698 }
1699 }
1700 return NS_OK;
1701}
1702
1703void nsDocShell::SetParentCharset(const Encoding*& aCharset,
1704 int32_t aCharsetSource,
1705 nsIPrincipal* aPrincipal) {
1706 mParentCharset = aCharset;
1707 mParentCharsetSource = aCharsetSource;
1708 mParentCharsetPrincipal = aPrincipal;
1709}
1710
1711void nsDocShell::GetParentCharset(const Encoding*& aCharset,
1712 int32_t* aCharsetSource,
1713 nsIPrincipal** aPrincipal) {
1714 aCharset = mParentCharset;
1715 *aCharsetSource = mParentCharsetSource;
1716 NS_IF_ADDREF(*aPrincipal = mParentCharsetPrincipal)ns_if_addref(*aPrincipal = mParentCharsetPrincipal);
1717}
1718
1719NS_IMETHODIMPnsresult
1720nsDocShell::GetHasTrackingContentBlocked(Promise** aPromise) {
1721 MOZ_ASSERT(aPromise)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aPromise)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aPromise))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aPromise", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 1721); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPromise" ")"
); do { *((volatile int*)__null) = 1721; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1722
1723 ErrorResult rv;
1724 RefPtr<Document> doc(GetDocument());
1725 RefPtr<Promise> retPromise = Promise::Create(doc->GetOwnerGlobal(), rv);
1726 if (NS_WARN_IF(rv.Failed())NS_warn_if_impl(rv.Failed(), "rv.Failed()", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 1726)
) {
1727 return rv.StealNSResult();
1728 }
1729
1730 // Retrieve the document's content blocking events from the parent process.
1731 RefPtr<Document::GetContentBlockingEventsPromise> promise =
1732 doc->GetContentBlockingEvents();
1733 if (promise) {
1734 promise->Then(
1735 GetCurrentSerialEventTarget(), __func__,
1736 [retPromise](const Document::GetContentBlockingEventsPromise::
1737 ResolveOrRejectValue& aValue) {
1738 if (aValue.IsResolve()) {
1739 bool has = aValue.ResolveValue() &
1740 nsIWebProgressListener::STATE_BLOCKED_TRACKING_CONTENT;
1741 retPromise->MaybeResolve(has);
1742 } else {
1743 retPromise->MaybeResolve(false);
1744 }
1745 });
1746 } else {
1747 retPromise->MaybeResolve(false);
1748 }
1749
1750 retPromise.forget(aPromise);
1751 return NS_OK;
1752}
1753
1754NS_IMETHODIMPnsresult
1755nsDocShell::GetCssErrorReportingEnabled(bool* aEnabled) {
1756 MOZ_ASSERT(aEnabled)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aEnabled)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aEnabled))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aEnabled", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 1756); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aEnabled" ")"
); do { *((volatile int*)__null) = 1756; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1757 *aEnabled = mCSSErrorReportingEnabled;
1758 return NS_OK;
1759}
1760
1761NS_IMETHODIMPnsresult
1762nsDocShell::SetCssErrorReportingEnabled(bool aEnabled) {
1763 mCSSErrorReportingEnabled = aEnabled;
1764 return NS_OK;
1765}
1766
1767NS_IMETHODIMPnsresult
1768nsDocShell::GetUsePrivateBrowsing(bool* aUsePrivateBrowsing) {
1769 NS_ENSURE_ARG_POINTER(aUsePrivateBrowsing)do { if ((__builtin_expect(!!(!(aUsePrivateBrowsing)), 0))) {
NS_DebugBreak(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aUsePrivateBrowsing"
") failed", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 1769); return NS_ERROR_INVALID_POINTER; } } while (false)
;
1770 return mBrowsingContext->GetUsePrivateBrowsing(aUsePrivateBrowsing);
1771}
1772
1773void nsDocShell::NotifyPrivateBrowsingChanged() {
1774 MOZ_ASSERT(!mIsBeingDestroyed)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mIsBeingDestroyed)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mIsBeingDestroyed))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("!mIsBeingDestroyed"
, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 1774); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mIsBeingDestroyed"
")"); do { *((volatile int*)__null) = 1774; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1775
1776 nsTObserverArray<nsWeakPtr>::ForwardIterator iter(mPrivacyObservers);
1777 while (iter.HasMore()) {
1778 nsWeakPtr ref = iter.GetNext();
1779 nsCOMPtr<nsIPrivacyTransitionObserver> obs = do_QueryReferent(ref);
1780 if (!obs) {
1781 iter.Remove();
1782 } else {
1783 obs->PrivateModeChanged(UsePrivateBrowsing());
1784 }
1785 }
1786}
1787
1788NS_IMETHODIMPnsresult
1789nsDocShell::SetUsePrivateBrowsing(bool aUsePrivateBrowsing) {
1790 return mBrowsingContext->SetUsePrivateBrowsing(aUsePrivateBrowsing);
1791}
1792
1793NS_IMETHODIMPnsresult
1794nsDocShell::SetPrivateBrowsing(bool aUsePrivateBrowsing) {
1795 return mBrowsingContext->SetPrivateBrowsing(aUsePrivateBrowsing);
1796}
1797
1798NS_IMETHODIMPnsresult
1799nsDocShell::GetHasLoadedNonBlankURI(bool* aResult) {
1800 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/docshell/base/nsDocShell.cpp"
, 1800); return NS_ERROR_INVALID_POINTER; } } while (false)
;
1801
1802 *aResult = mHasLoadedNonBlankURI;
1803 return NS_OK;
1804}
1805
1806NS_IMETHODIMPnsresult
1807nsDocShell::GetUseRemoteTabs(bool* aUseRemoteTabs) {
1808 NS_ENSURE_ARG_POINTER(aUseRemoteTabs)do { if ((__builtin_expect(!!(!(aUseRemoteTabs)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aUseRemoteTabs" ") failed"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 1808); return NS_ERROR_INVALID_POINTER; } } while (false)
;
1809 return mBrowsingContext->GetUseRemoteTabs(aUseRemoteTabs);
1810}
1811
1812NS_IMETHODIMPnsresult
1813nsDocShell::SetRemoteTabs(bool aUseRemoteTabs) {
1814 return mBrowsingContext->SetRemoteTabs(aUseRemoteTabs);
1815}
1816
1817NS_IMETHODIMPnsresult
1818nsDocShell::GetUseRemoteSubframes(bool* aUseRemoteSubframes) {
1819 NS_ENSURE_ARG_POINTER(aUseRemoteSubframes)do { if ((__builtin_expect(!!(!(aUseRemoteSubframes)), 0))) {
NS_DebugBreak(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aUseRemoteSubframes"
") failed", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 1819); return NS_ERROR_INVALID_POINTER; } } while (false)
;
1820 return mBrowsingContext->GetUseRemoteSubframes(aUseRemoteSubframes);
1821}
1822
1823NS_IMETHODIMPnsresult
1824nsDocShell::SetRemoteSubframes(bool aUseRemoteSubframes) {
1825 return mBrowsingContext->SetRemoteSubframes(aUseRemoteSubframes);
1826}
1827
1828NS_IMETHODIMPnsresult
1829nsDocShell::AddWeakPrivacyTransitionObserver(
1830 nsIPrivacyTransitionObserver* aObserver) {
1831 nsWeakPtr weakObs = do_GetWeakReference(aObserver);
1832 if (!weakObs) {
1833 return NS_ERROR_NOT_AVAILABLE;
1834 }
1835 mPrivacyObservers.AppendElement(weakObs);
1836 return NS_OK;
1837}
1838
1839NS_IMETHODIMPnsresult
1840nsDocShell::AddWeakReflowObserver(nsIReflowObserver* aObserver) {
1841 nsWeakPtr weakObs = do_GetWeakReference(aObserver);
1842 if (!weakObs) {
1843 return NS_ERROR_FAILURE;
1844 }
1845 mReflowObservers.AppendElement(weakObs);
1846 return NS_OK;
1847}
1848
1849NS_IMETHODIMPnsresult
1850nsDocShell::RemoveWeakReflowObserver(nsIReflowObserver* aObserver) {
1851 nsWeakPtr obs = do_GetWeakReference(aObserver);
1852 return mReflowObservers.RemoveElement(obs) ? NS_OK : NS_ERROR_FAILURE;
1853}
1854
1855NS_IMETHODIMPnsresult
1856nsDocShell::NotifyReflowObservers(bool aInterruptible,
1857 DOMHighResTimeStamp aStart,
1858 DOMHighResTimeStamp aEnd) {
1859 nsTObserverArray<nsWeakPtr>::ForwardIterator iter(mReflowObservers);
1860 while (iter.HasMore()) {
1861 nsWeakPtr ref = iter.GetNext();
1862 nsCOMPtr<nsIReflowObserver> obs = do_QueryReferent(ref);
1863 if (!obs) {
1864 iter.Remove();
1865 } else if (aInterruptible) {
1866 obs->ReflowInterruptible(aStart, aEnd);
1867 } else {
1868 obs->Reflow(aStart, aEnd);
1869 }
1870 }
1871 return NS_OK;
1872}
1873
1874NS_IMETHODIMPnsresult
1875nsDocShell::GetAllowMetaRedirects(bool* aReturn) {
1876 NS_ENSURE_ARG_POINTER(aReturn)do { if ((__builtin_expect(!!(!(aReturn)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aReturn" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 1876); return NS_ERROR_INVALID_POINTER; } } while (false)
;
1877
1878 *aReturn = mAllowMetaRedirects;
1879 return NS_OK;
1880}
1881
1882NS_IMETHODIMPnsresult
1883nsDocShell::SetAllowMetaRedirects(bool aValue) {
1884 mAllowMetaRedirects = aValue;
1885 return NS_OK;
1886}
1887
1888NS_IMETHODIMPnsresult
1889nsDocShell::GetAllowSubframes(bool* aAllowSubframes) {
1890 NS_ENSURE_ARG_POINTER(aAllowSubframes)do { if ((__builtin_expect(!!(!(aAllowSubframes)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aAllowSubframes" ") failed"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 1890); return NS_ERROR_INVALID_POINTER; } } while (false)
;
1891
1892 *aAllowSubframes = mAllowSubframes;
1893 return NS_OK;
1894}
1895
1896NS_IMETHODIMPnsresult
1897nsDocShell::SetAllowSubframes(bool aAllowSubframes) {
1898 mAllowSubframes = aAllowSubframes;
1899 return NS_OK;
1900}
1901
1902NS_IMETHODIMPnsresult
1903nsDocShell::GetAllowImages(bool* aAllowImages) {
1904 NS_ENSURE_ARG_POINTER(aAllowImages)do { if ((__builtin_expect(!!(!(aAllowImages)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aAllowImages" ") failed"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 1904); return NS_ERROR_INVALID_POINTER; } } while (false)
;
1905
1906 *aAllowImages = mAllowImages;
1907 return NS_OK;
1908}
1909
1910NS_IMETHODIMPnsresult
1911nsDocShell::SetAllowImages(bool aAllowImages) {
1912 mAllowImages = aAllowImages;
1913 return NS_OK;
1914}
1915
1916NS_IMETHODIMPnsresult
1917nsDocShell::GetAllowMedia(bool* aAllowMedia) {
1918 *aAllowMedia = mAllowMedia;
1919 return NS_OK;
1920}
1921
1922NS_IMETHODIMPnsresult
1923nsDocShell::SetAllowMedia(bool aAllowMedia) {
1924 mAllowMedia = aAllowMedia;
1925
1926 // Mute or unmute audio contexts attached to the inner window.
1927 if (mScriptGlobal) {
1928 if (nsPIDOMWindowInner* innerWin = mScriptGlobal->GetCurrentInnerWindow()) {
1929 if (aAllowMedia) {
1930 innerWin->UnmuteAudioContexts();
1931 } else {
1932 innerWin->MuteAudioContexts();
1933 }
1934 }
1935 }
1936
1937 return NS_OK;
1938}
1939
1940NS_IMETHODIMPnsresult
1941nsDocShell::GetAllowDNSPrefetch(bool* aAllowDNSPrefetch) {
1942 *aAllowDNSPrefetch = mAllowDNSPrefetch;
1943 return NS_OK;
1944}
1945
1946NS_IMETHODIMPnsresult
1947nsDocShell::SetAllowDNSPrefetch(bool aAllowDNSPrefetch) {
1948 mAllowDNSPrefetch = aAllowDNSPrefetch;
1949 return NS_OK;
1950}
1951
1952NS_IMETHODIMPnsresult
1953nsDocShell::GetAllowWindowControl(bool* aAllowWindowControl) {
1954 *aAllowWindowControl = mAllowWindowControl;
1955 return NS_OK;
1956}
1957
1958NS_IMETHODIMPnsresult
1959nsDocShell::SetAllowWindowControl(bool aAllowWindowControl) {
1960 mAllowWindowControl = aAllowWindowControl;
1961 return NS_OK;
1962}
1963
1964NS_IMETHODIMPnsresult
1965nsDocShell::GetAllowContentRetargeting(bool* aAllowContentRetargeting) {
1966 *aAllowContentRetargeting = mBrowsingContext->GetAllowContentRetargeting();
1967 return NS_OK;
1968}
1969
1970NS_IMETHODIMPnsresult
1971nsDocShell::SetAllowContentRetargeting(bool aAllowContentRetargeting) {
1972 BrowsingContext::Transaction txn;
1973 txn.SetAllowContentRetargeting(aAllowContentRetargeting);
1974 txn.SetAllowContentRetargetingOnChildren(aAllowContentRetargeting);
1975 return txn.Commit(mBrowsingContext);
1976}
1977
1978NS_IMETHODIMPnsresult
1979nsDocShell::GetAllowContentRetargetingOnChildren(
1980 bool* aAllowContentRetargetingOnChildren) {
1981 *aAllowContentRetargetingOnChildren =
1982 mBrowsingContext->GetAllowContentRetargetingOnChildren();
1983 return NS_OK;
1984}
1985
1986NS_IMETHODIMPnsresult
1987nsDocShell::SetAllowContentRetargetingOnChildren(
1988 bool aAllowContentRetargetingOnChildren) {
1989 return mBrowsingContext->SetAllowContentRetargetingOnChildren(
1990 aAllowContentRetargetingOnChildren);
1991}
1992
1993NS_IMETHODIMPnsresult
1994nsDocShell::GetMayEnableCharacterEncodingMenu(
1995 bool* aMayEnableCharacterEncodingMenu) {
1996 *aMayEnableCharacterEncodingMenu = false;
1997 if (!mDocumentViewer) {
1998 return NS_OK;
1999 }
2000 Document* doc = mDocumentViewer->GetDocument();
2001 if (!doc) {
2002 return NS_OK;
2003 }
2004 if (doc->WillIgnoreCharsetOverride()) {
2005 return NS_OK;
2006 }
2007
2008 *aMayEnableCharacterEncodingMenu = true;
2009 return NS_OK;
2010}
2011
2012NS_IMETHODIMPnsresult
2013nsDocShell::GetAllDocShellsInSubtree(int32_t aItemType,
2014 DocShellEnumeratorDirection aDirection,
2015 nsTArray<RefPtr<nsIDocShell>>& aResult) {
2016 aResult.Clear();
2017
2018 nsDocShellEnumerator docShellEnum(
2019 (aDirection == ENUMERATE_FORWARDS)
2020 ? nsDocShellEnumerator::EnumerationDirection::Forwards
2021 : nsDocShellEnumerator::EnumerationDirection::Backwards,
2022 aItemType, *this);
2023
2024 nsresult rv = docShellEnum.BuildDocShellArray(aResult);
2025 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2026 return rv;
2027 }
2028
2029 return NS_OK;
2030}
2031
2032NS_IMETHODIMPnsresult
2033nsDocShell::GetAppType(AppType* aAppType) {
2034 *aAppType = mAppType;
2035 return NS_OK;
2036}
2037
2038NS_IMETHODIMPnsresult
2039nsDocShell::SetAppType(AppType aAppType) {
2040 mAppType = aAppType;
2041 return NS_OK;
2042}
2043
2044NS_IMETHODIMPnsresult
2045nsDocShell::GetAllowAuth(bool* aAllowAuth) {
2046 *aAllowAuth = mAllowAuth;
2047 return NS_OK;
2048}
2049
2050NS_IMETHODIMPnsresult
2051nsDocShell::SetAllowAuth(bool aAllowAuth) {
2052 mAllowAuth = aAllowAuth;
2053 return NS_OK;
2054}
2055
2056NS_IMETHODIMPnsresult
2057nsDocShell::GetZoom(float* aZoom) {
2058 NS_ENSURE_ARG_POINTER(aZoom)do { if ((__builtin_expect(!!(!(aZoom)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aZoom" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 2058); return NS_ERROR_INVALID_POINTER; } } while (false)
;
2059 *aZoom = 1.0f;
2060 return NS_OK;
2061}
2062
2063NS_IMETHODIMPnsresult
2064nsDocShell::SetZoom(float aZoom) { return NS_ERROR_NOT_IMPLEMENTED; }
2065
2066NS_IMETHODIMPnsresult
2067nsDocShell::GetBusyFlags(BusyFlags* aBusyFlags) {
2068 NS_ENSURE_ARG_POINTER(aBusyFlags)do { if ((__builtin_expect(!!(!(aBusyFlags)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aBusyFlags" ") failed",
nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 2068); return NS_ERROR_INVALID_POINTER; } } while (false)
;
2069
2070 *aBusyFlags = mBusyFlags;
2071 return NS_OK;
2072}
2073
2074NS_IMETHODIMPnsresult
2075nsDocShell::GetLoadURIDelegate(nsILoadURIDelegate** aLoadURIDelegate) {
2076 nsCOMPtr<nsILoadURIDelegate> delegate = GetLoadURIDelegate();
2077 delegate.forget(aLoadURIDelegate);
2078 return NS_OK;
2079}
2080
2081already_AddRefed<nsILoadURIDelegate> nsDocShell::GetLoadURIDelegate() {
2082 if (nsCOMPtr<nsILoadURIDelegate> result =
2083 do_QueryActor("LoadURIDelegate", GetDocument())) {
2084 return result.forget();
2085 }
2086
2087 return nullptr;
2088}
2089
2090NS_IMETHODIMPnsresult
2091nsDocShell::GetUseErrorPages(bool* aUseErrorPages) {
2092 *aUseErrorPages = mBrowsingContext->GetUseErrorPages();
2093 return NS_OK;
2094}
2095
2096NS_IMETHODIMPnsresult
2097nsDocShell::SetUseErrorPages(bool aUseErrorPages) {
2098 return mBrowsingContext->SetUseErrorPages(aUseErrorPages);
2099}
2100
2101NS_IMETHODIMPnsresult
2102nsDocShell::GetPreviousEntryIndex(int32_t* aPreviousEntryIndex) {
2103 *aPreviousEntryIndex = mPreviousEntryIndex;
2104 return NS_OK;
2105}
2106
2107NS_IMETHODIMPnsresult
2108nsDocShell::GetLoadedEntryIndex(int32_t* aLoadedEntryIndex) {
2109 *aLoadedEntryIndex = mLoadedEntryIndex;
2110 return NS_OK;
2111}
2112
2113NS_IMETHODIMPnsresult
2114nsDocShell::HistoryPurged(int32_t aNumEntries) {
2115 // These indices are used for fastback cache eviction, to determine
2116 // which session history entries are candidates for content viewer
2117 // eviction. We need to adjust by the number of entries that we
2118 // just purged from history, so that we look at the right session history
2119 // entries during eviction.
2120 mPreviousEntryIndex = std::max(-1, mPreviousEntryIndex - aNumEntries);
2121 mLoadedEntryIndex = std::max(0, mLoadedEntryIndex - aNumEntries);
2122
2123 for (auto* child : mChildList.ForwardRange()) {
2124 nsCOMPtr<nsIDocShell> shell = do_QueryObject(child);
2125 if (shell) {
2126 shell->HistoryPurged(aNumEntries);
2127 }
2128 }
2129
2130 return NS_OK;
2131}
2132
2133nsresult nsDocShell::HistoryEntryRemoved(int32_t aIndex) {
2134 // These indices are used for fastback cache eviction, to determine
2135 // which session history entries are candidates for content viewer
2136 // eviction. We need to adjust by the number of entries that we
2137 // just purged from history, so that we look at the right session history
2138 // entries during eviction.
2139 if (aIndex == mPreviousEntryIndex) {
2140 mPreviousEntryIndex = -1;
2141 } else if (aIndex < mPreviousEntryIndex) {
2142 --mPreviousEntryIndex;
2143 }
2144 if (mLoadedEntryIndex == aIndex) {
2145 mLoadedEntryIndex = 0;
2146 } else if (aIndex < mLoadedEntryIndex) {
2147 --mLoadedEntryIndex;
2148 }
2149
2150 for (auto* child : mChildList.ForwardRange()) {
2151 nsCOMPtr<nsIDocShell> shell = do_QueryObject(child);
2152 if (shell) {
2153 static_cast<nsDocShell*>(shell.get())->HistoryEntryRemoved(aIndex);
2154 }
2155 }
2156
2157 return NS_OK;
2158}
2159
2160nsresult nsDocShell::Now(DOMHighResTimeStamp* aWhen) {
2161 *aWhen = (TimeStamp::Now() - TimeStamp::ProcessCreation()).ToMilliseconds();
2162 return NS_OK;
2163}
2164
2165NS_IMETHODIMPnsresult
2166nsDocShell::SetWindowDraggingAllowed(bool aValue) {
2167 RefPtr<nsDocShell> parent = GetInProcessParentDocshell();
2168 if (!aValue && mItemType == typeChrome && !parent) {
2169 // Window dragging is always allowed for top level
2170 // chrome docshells.
2171 return NS_ERROR_FAILURE;
2172 }
2173 mWindowDraggingAllowed = aValue;
2174 return NS_OK;
2175}
2176
2177NS_IMETHODIMPnsresult
2178nsDocShell::GetWindowDraggingAllowed(bool* aValue) {
2179 // window dragging regions in CSS (-moz-window-drag:drag)
2180 // can be slow. Default behavior is to only allow it for
2181 // chrome top level windows.
2182 RefPtr<nsDocShell> parent = GetInProcessParentDocshell();
2183 if (mItemType == typeChrome && !parent) {
2184 // Top level chrome window
2185 *aValue = true;
2186 } else {
2187 *aValue = mWindowDraggingAllowed;
2188 }
2189 return NS_OK;
2190}
2191
2192NS_IMETHODIMPnsresult
2193nsDocShell::GetCurrentDocumentChannel(nsIChannel** aResult) {
2194 NS_IF_ADDREF(*aResult = GetCurrentDocChannel())ns_if_addref(*aResult = GetCurrentDocChannel());
2195 return NS_OK;
2196}
2197
2198nsIChannel* nsDocShell::GetCurrentDocChannel() {
2199 if (mDocumentViewer) {
2200 Document* doc = mDocumentViewer->GetDocument();
2201 if (doc) {
2202 return doc->GetChannel();
2203 }
2204 }
2205 return nullptr;
2206}
2207
2208NS_IMETHODIMPnsresult
2209nsDocShell::AddWeakScrollObserver(nsIScrollObserver* aObserver) {
2210 nsWeakPtr weakObs = do_GetWeakReference(aObserver);
2211 if (!weakObs) {
2212 return NS_ERROR_FAILURE;
2213 }
2214 mScrollObservers.AppendElement(weakObs);
2215 return NS_OK;
2216}
2217
2218NS_IMETHODIMPnsresult
2219nsDocShell::RemoveWeakScrollObserver(nsIScrollObserver* aObserver) {
2220 nsWeakPtr obs = do_GetWeakReference(aObserver);
2221 return mScrollObservers.RemoveElement(obs) ? NS_OK : NS_ERROR_FAILURE;
2222}
2223
2224void nsDocShell::NotifyAsyncPanZoomStarted() {
2225 nsTObserverArray<nsWeakPtr>::ForwardIterator iter(mScrollObservers);
2226 while (iter.HasMore()) {
2227 nsWeakPtr ref = iter.GetNext();
2228 nsCOMPtr<nsIScrollObserver> obs = do_QueryReferent(ref);
2229 if (obs) {
2230 obs->AsyncPanZoomStarted();
2231 } else {
2232 iter.Remove();
2233 }
2234 }
2235}
2236
2237void nsDocShell::NotifyAsyncPanZoomStopped() {
2238 nsTObserverArray<nsWeakPtr>::ForwardIterator iter(mScrollObservers);
2239 while (iter.HasMore()) {
2240 nsWeakPtr ref = iter.GetNext();
2241 nsCOMPtr<nsIScrollObserver> obs = do_QueryReferent(ref);
2242 if (obs) {
2243 obs->AsyncPanZoomStopped();
2244 } else {
2245 iter.Remove();
2246 }
2247 }
2248}
2249
2250NS_IMETHODIMPnsresult
2251nsDocShell::NotifyScrollObservers() {
2252 nsTObserverArray<nsWeakPtr>::ForwardIterator iter(mScrollObservers);
2253 while (iter.HasMore()) {
2254 nsWeakPtr ref = iter.GetNext();
2255 nsCOMPtr<nsIScrollObserver> obs = do_QueryReferent(ref);
2256 if (obs) {
2257 obs->ScrollPositionChanged();
2258 } else {
2259 iter.Remove();
2260 }
2261 }
2262 return NS_OK;
2263}
2264
2265//*****************************************************************************
2266// nsDocShell::nsIDocShellTreeItem
2267//*****************************************************************************
2268
2269NS_IMETHODIMPnsresult
2270nsDocShell::GetName(nsAString& aName) {
2271 aName = mBrowsingContext->Name();
2272 return NS_OK;
2273}
2274
2275NS_IMETHODIMPnsresult
2276nsDocShell::SetName(const nsAString& aName) {
2277 return mBrowsingContext->SetName(aName);
2278}
2279
2280NS_IMETHODIMPnsresult
2281nsDocShell::NameEquals(const nsAString& aName, bool* aResult) {
2282 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/docshell/base/nsDocShell.cpp"
, 2282); return NS_ERROR_INVALID_POINTER; } } while (false)
;
2283 *aResult = mBrowsingContext->NameEquals(aName);
2284 return NS_OK;
2285}
2286
2287NS_IMETHODIMPnsresult
2288nsDocShell::GetCustomUserAgent(nsAString& aCustomUserAgent) {
2289 mBrowsingContext->GetCustomUserAgent(aCustomUserAgent);
2290 return NS_OK;
2291}
2292
2293NS_IMETHODIMPnsresult
2294nsDocShell::SetCustomUserAgent(const nsAString& aCustomUserAgent) {
2295 if (mWillChangeProcess) {
2296 NS_WARNING("SetCustomUserAgent: Process is changing. Ignoring set")NS_DebugBreak(NS_DEBUG_WARNING, "SetCustomUserAgent: Process is changing. Ignoring set"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 2296)
;
2297 return NS_ERROR_FAILURE;
2298 }
2299
2300 return mBrowsingContext->SetCustomUserAgent(aCustomUserAgent);
2301}
2302
2303NS_IMETHODIMPnsresult
2304nsDocShell::ClearCachedPlatform() {
2305 nsCOMPtr<nsPIDOMWindowInner> win =
2306 mScriptGlobal ? mScriptGlobal->GetCurrentInnerWindow() : nullptr;
2307 if (win) {
2308 Navigator* navigator = win->Navigator();
2309 if (navigator) {
2310 navigator->ClearPlatformCache();
2311 }
2312 }
2313
2314 return NS_OK;
2315}
2316
2317NS_IMETHODIMPnsresult
2318nsDocShell::ClearCachedUserAgent() {
2319 nsCOMPtr<nsPIDOMWindowInner> win =
2320 mScriptGlobal ? mScriptGlobal->GetCurrentInnerWindow() : nullptr;
2321 if (win) {
2322 Navigator* navigator = win->Navigator();
2323 if (navigator) {
2324 navigator->ClearUserAgentCache();
2325 }
2326 }
2327
2328 return NS_OK;
2329}
2330
2331/* virtual */
2332int32_t nsDocShell::ItemType() { return mItemType; }
2333
2334NS_IMETHODIMPnsresult
2335nsDocShell::GetItemType(int32_t* aItemType) {
2336 NS_ENSURE_ARG_POINTER(aItemType)do { if ((__builtin_expect(!!(!(aItemType)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aItemType" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 2336); return NS_ERROR_INVALID_POINTER; } } while (false)
;
2337
2338 MOZ_DIAGNOSTIC_ASSERT(do { static_assert( mozilla::detail::AssertionConditionType<
decltype((mBrowsingContext->IsContent() ? typeContent : typeChrome
) == mItemType)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!((mBrowsingContext->IsContent
() ? typeContent : typeChrome) == mItemType))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("(mBrowsingContext->IsContent() ? typeContent : typeChrome) == mItemType"
, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 2339); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "(mBrowsingContext->IsContent() ? typeContent : typeChrome) == mItemType"
")"); do { *((volatile int*)__null) = 2339; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2339 (mBrowsingContext->IsContent() ? typeContent : typeChrome) == mItemType)do { static_assert( mozilla::detail::AssertionConditionType<
decltype((mBrowsingContext->IsContent() ? typeContent : typeChrome
) == mItemType)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!((mBrowsingContext->IsContent
() ? typeContent : typeChrome) == mItemType))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("(mBrowsingContext->IsContent() ? typeContent : typeChrome) == mItemType"
, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 2339); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "(mBrowsingContext->IsContent() ? typeContent : typeChrome) == mItemType"
")"); do { *((volatile int*)__null) = 2339; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2340 *aItemType = mItemType;
2341 return NS_OK;
2342}
2343
2344NS_IMETHODIMPnsresult
2345nsDocShell::GetInProcessParent(nsIDocShellTreeItem** aParent) {
2346 if (!mParent) {
2347 *aParent = nullptr;
2348 } else {
2349 CallQueryInterface(mParent, aParent);
2350 }
2351 // Note that in the case when the parent is not an nsIDocShellTreeItem we
2352 // don't want to throw; we just want to return null.
2353 return NS_OK;
2354}
2355
2356// With Fission, related nsDocShell objects may exist in a different process. In
2357// that case, this method will return `nullptr`, despite a parent nsDocShell
2358// object existing.
2359//
2360// Prefer using `BrowsingContext::Parent()`, which will succeed even if the
2361// parent entry is not in the current process, and handle the case where the
2362// parent nsDocShell is inaccessible.
2363already_AddRefed<nsDocShell> nsDocShell::GetInProcessParentDocshell() {
2364 nsCOMPtr<nsIDocShell> docshell = do_QueryInterface(GetAsSupports(mParent));
2365 return docshell.forget().downcast<nsDocShell>();
2366}
2367
2368void nsDocShell::MaybeCreateInitialClientSource(nsIPrincipal* aPrincipal) {
2369 MOZ_ASSERT(!mIsBeingDestroyed)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mIsBeingDestroyed)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mIsBeingDestroyed))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("!mIsBeingDestroyed"
, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 2369); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mIsBeingDestroyed"
")"); do { *((volatile int*)__null) = 2369; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2370
2371 // If there is an existing document then there is no need to create
2372 // a client for a future initial about:blank document.
2373 if (mScriptGlobal && mScriptGlobal->GetCurrentInnerWindow() &&
2374 mScriptGlobal->GetCurrentInnerWindow()->GetExtantDoc()) {
2375 MOZ_DIAGNOSTIC_ASSERT(do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mScriptGlobal->GetCurrentInnerWindow()->GetClientInfo
().isSome())>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(mScriptGlobal->GetCurrentInnerWindow
()->GetClientInfo().isSome()))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("mScriptGlobal->GetCurrentInnerWindow()->GetClientInfo().isSome()"
, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 2376); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "mScriptGlobal->GetCurrentInnerWindow()->GetClientInfo().isSome()"
")"); do { *((volatile int*)__null) = 2376; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2376 mScriptGlobal->GetCurrentInnerWindow()->GetClientInfo().isSome())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mScriptGlobal->GetCurrentInnerWindow()->GetClientInfo
().isSome())>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(mScriptGlobal->GetCurrentInnerWindow
()->GetClientInfo().isSome()))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("mScriptGlobal->GetCurrentInnerWindow()->GetClientInfo().isSome()"
, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 2376); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "mScriptGlobal->GetCurrentInnerWindow()->GetClientInfo().isSome()"
")"); do { *((volatile int*)__null) = 2376; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2377 MOZ_DIAGNOSTIC_ASSERT(!mInitialClientSource)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mInitialClientSource)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mInitialClientSource))), 0)
)) { do { } while (false); MOZ_ReportAssertionFailure("!mInitialClientSource"
, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 2377); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "!mInitialClientSource"
")"); do { *((volatile int*)__null) = 2377; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2378 return;
2379 }
2380
2381 // Don't recreate the initial client source. We call this multiple times
2382 // when DoChannelLoad() is called before CreateAboutBlankDocumentViewer.
2383 if (mInitialClientSource) {
2384 return;
2385 }
2386
2387 // Don't pre-allocate the client when we are sandboxed. The inherited
2388 // principal does not take sandboxing into account.
2389 // TODO: Refactor sandboxing principal code out so we can use it here.
2390 if (!aPrincipal && mBrowsingContext->GetSandboxFlags()) {
2391 return;
2392 }
2393
2394 // We cannot get inherited foreign partitioned principal here. Instead, we
2395 // directly check which principal we want to inherit for the service worker.
2396 nsIPrincipal* principal =
2397 aPrincipal
2398 ? aPrincipal
2399 : GetInheritedPrincipal(
2400 false, StoragePrincipalHelper::
2401 ShouldUsePartitionPrincipalForServiceWorker(this));
2402
2403 // Sometimes there is no principal available when we are called from
2404 // CreateAboutBlankDocumentViewer. For example, sometimes the principal
2405 // is only extracted from the load context after the document is created
2406 // in Document::ResetToURI(). Ideally we would do something similar
2407 // here, but for now lets just avoid the issue by not preallocating the
2408 // client.
2409 if (!principal) {
2410 return;
2411 }
2412
2413 nsCOMPtr<nsPIDOMWindowOuter> win = GetWindow();
2414 if (!win) {
2415 return;
2416 }
2417
2418 mInitialClientSource = ClientManager::CreateSource(
2419 ClientType::Window, GetMainThreadSerialEventTarget(), principal);
2420 MOZ_DIAGNOSTIC_ASSERT(mInitialClientSource)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mInitialClientSource)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mInitialClientSource))), 0))
) { do { } while (false); MOZ_ReportAssertionFailure("mInitialClientSource"
, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 2420); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "mInitialClientSource"
")"); do { *((volatile int*)__null) = 2420; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2421
2422 // Mark the initial client as execution ready, but owned by the docshell.
2423 // If the client is actually used this will cause ClientSource to force
2424 // the creation of the initial about:blank by calling
2425 // nsDocShell::GetDocument().
2426 mInitialClientSource->DocShellExecutionReady(this);
2427
2428 // Next, check to see if the parent is controlled.
2429 nsCOMPtr<nsIDocShell> parent = GetInProcessParentDocshell();
2430 nsPIDOMWindowOuter* parentOuter = parent ? parent->GetWindow() : nullptr;
2431 nsPIDOMWindowInner* parentInner =
2432 parentOuter ? parentOuter->GetCurrentInnerWindow() : nullptr;
2433 if (!parentInner) {
2434 return;
2435 }
2436
2437 nsCOMPtr<nsIURI> uri;
2438 MOZ_ALWAYS_SUCCEEDS(NS_NewURI(getter_AddRefs(uri), "about:blank"_ns))do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(NS_NewURI(getter_AddRefs(uri), "about:blank"_ns))), 1)))), 1
))) { } else { do { static_assert( mozilla::detail::AssertionConditionType
<decltype(false)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("false" " (" "NS_SUCCEEDED(NS_NewURI(getter_AddRefs(uri), \"about:blank\"_ns))"
")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 2438); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "false"
") (" "NS_SUCCEEDED(NS_NewURI(getter_AddRefs(uri), \"about:blank\"_ns))"
")"); do { *((volatile int*)__null) = 2438; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
2439
2440 // We're done if there is no parent controller or if this docshell
2441 // is not permitted to control for some reason.
2442 Maybe<ServiceWorkerDescriptor> controller(parentInner->GetController());
2443 if (controller.isNothing() ||
2444 !ServiceWorkerAllowedToControlWindow(principal, uri)) {
2445 return;
2446 }
2447
2448 mInitialClientSource->InheritController(controller.ref());
2449}
2450
2451Maybe<ClientInfo> nsDocShell::GetInitialClientInfo() const {
2452 if (mInitialClientSource) {
2453 Maybe<ClientInfo> result;
2454 result.emplace(mInitialClientSource->Info());
2455 return result;
2456 }
2457
2458 nsPIDOMWindowInner* innerWindow =
2459 mScriptGlobal ? mScriptGlobal->GetCurrentInnerWindow() : nullptr;
2460 Document* doc = innerWindow ? innerWindow->GetExtantDoc() : nullptr;
2461
2462 if (!doc || !doc->IsInitialDocument()) {
2463 return Maybe<ClientInfo>();
2464 }
2465
2466 return innerWindow->GetClientInfo();
2467}
2468
2469nsresult nsDocShell::SetDocLoaderParent(nsDocLoader* aParent) {
2470 bool wasFrame = IsSubframe();
2471
2472 nsresult rv = nsDocLoader::SetDocLoaderParent(aParent);
2473 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/docshell/base/nsDocShell.cpp"
, 2473); return rv; } } while (false)
;
2474
2475 nsCOMPtr<nsISupportsPriority> priorityGroup = do_QueryInterface(mLoadGroup);
2476 if (wasFrame != IsSubframe() && priorityGroup) {
2477 priorityGroup->AdjustPriority(wasFrame ? -1 : 1);
2478 }
2479
2480 // Curse ambiguous nsISupports inheritance!
2481 nsISupports* parent = GetAsSupports(aParent);
2482
2483 // If parent is another docshell, we inherit all their flags for
2484 // allowing plugins, scripting etc.
2485 bool value;
2486 nsCOMPtr<nsIDocShell> parentAsDocShell(do_QueryInterface(parent));
2487
2488 if (parentAsDocShell) {
2489 if (mAllowMetaRedirects &&
2490 NS_SUCCEEDED(parentAsDocShell->GetAllowMetaRedirects(&value))((bool)(__builtin_expect(!!(!NS_FAILED_impl(parentAsDocShell->
GetAllowMetaRedirects(&value))), 1)))
) {
2491 SetAllowMetaRedirects(value);
2492 }
2493 if (mAllowSubframes &&
2494 NS_SUCCEEDED(parentAsDocShell->GetAllowSubframes(&value))((bool)(__builtin_expect(!!(!NS_FAILED_impl(parentAsDocShell->
GetAllowSubframes(&value))), 1)))
) {
2495 SetAllowSubframes(value);
2496 }
2497 if (mAllowImages &&
2498 NS_SUCCEEDED(parentAsDocShell->GetAllowImages(&value))((bool)(__builtin_expect(!!(!NS_FAILED_impl(parentAsDocShell->
GetAllowImages(&value))), 1)))
) {
2499 SetAllowImages(value);
2500 }
2501 SetAllowMedia(parentAsDocShell->GetAllowMedia() && mAllowMedia);
2502 if (mAllowWindowControl &&
2503 NS_SUCCEEDED(parentAsDocShell->GetAllowWindowControl(&value))((bool)(__builtin_expect(!!(!NS_FAILED_impl(parentAsDocShell->
GetAllowWindowControl(&value))), 1)))
) {
2504 SetAllowWindowControl(value);
2505 }
2506 if (NS_FAILED(parentAsDocShell->GetAllowDNSPrefetch(&value))((bool)(__builtin_expect(!!(NS_FAILED_impl(parentAsDocShell->
GetAllowDNSPrefetch(&value))), 0)))
) {
2507 value = false;
2508 }
2509 SetAllowDNSPrefetch(mAllowDNSPrefetch && value);
2510 }
2511
2512 nsCOMPtr<nsIURIContentListener> parentURIListener(do_GetInterface(parent));
2513 if (parentURIListener) {
2514 mContentListener->SetParentContentListener(parentURIListener);
2515 }
2516
2517 return NS_OK;
2518}
2519
2520void nsDocShell::MaybeRestoreWindowName() {
2521 if (!StaticPrefs::privacy_window_name_update_enabled()) {
2522 return;
2523 }
2524
2525 // We only restore window.name for the top-level content.
2526 if (!mBrowsingContext->IsTopContent()) {
2527 return;
2528 }
2529
2530 nsAutoString name;
2531
2532 // Following implements https://html.spec.whatwg.org/#history-traversal:
2533 // Step 4.4. Check if the loading entry has a name.
2534
2535 if (mLSHE) {
2536 mLSHE->GetName(name);
2537 }
2538
2539 if (mLoadingEntry) {
2540 name = mLoadingEntry->mInfo.GetName();
2541 }
2542
2543 if (name.IsEmpty()) {
2544 return;
2545 }
2546
2547 // Step 4.4.1. Set the name to the browsing context.
2548 Unused << mBrowsingContext->SetName(name);
2549
2550 // Step 4.4.2. Clear the name of all entries that are contiguous and
2551 // same-origin with the loading entry.
2552 if (mLSHE) {
2553 nsSHistory::WalkContiguousEntries(
2554 mLSHE, [](nsISHEntry* aEntry) { aEntry->SetName(EmptyString()); });
2555 }
2556
2557 if (mLoadingEntry) {
2558 // Clear the name of the session entry in the child side. For parent side,
2559 // the clearing will be done when we commit the history to the parent.
2560 mLoadingEntry->mInfo.SetName(EmptyString());
2561 }
2562}
2563
2564void nsDocShell::StoreWindowNameToSHEntries() {
2565 MOZ_ASSERT(mBrowsingContext->IsTopContent())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mBrowsingContext->IsTopContent())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mBrowsingContext->IsTopContent
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("mBrowsingContext->IsTopContent()", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 2565); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mBrowsingContext->IsTopContent()"
")"); do { *((volatile int*)__null) = 2565; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2566
2567 nsAutoString name;
2568 mBrowsingContext->GetName(name);
2569
2570 if (mOSHE) {
2571 nsSHistory::WalkContiguousEntries(
2572 mOSHE, [&](nsISHEntry* aEntry) { aEntry->SetName(name); });
2573 }
2574
2575 if (mozilla::SessionHistoryInParent()) {
2576 if (XRE_IsParentProcess()) {
2577 SessionHistoryEntry* entry =
2578 mBrowsingContext->Canonical()->GetActiveSessionHistoryEntry();
2579 if (entry) {
2580 nsSHistory::WalkContiguousEntries(
2581 entry, [&](nsISHEntry* aEntry) { aEntry->SetName(name); });
2582 }
2583 } else {
2584 // Ask parent process to store the name in entries.
2585 mozilla::Unused
2586 << ContentChild::GetSingleton()
2587 ->SendSessionHistoryEntryStoreWindowNameInContiguousEntries(
2588 mBrowsingContext, name);
2589 }
2590 }
2591}
2592
2593NS_IMETHODIMPnsresult
2594nsDocShell::GetInProcessSameTypeParent(nsIDocShellTreeItem** aParent) {
2595 if (BrowsingContext* parentBC = mBrowsingContext->GetParent()) {
2596 *aParent = do_AddRef(parentBC->GetDocShell()).take();
2597 }
2598 return NS_OK;
2599}
2600
2601NS_IMETHODIMPnsresult
2602nsDocShell::GetInProcessRootTreeItem(nsIDocShellTreeItem** aRootTreeItem) {
2603 NS_ENSURE_ARG_POINTER(aRootTreeItem)do { if ((__builtin_expect(!!(!(aRootTreeItem)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aRootTreeItem" ") failed"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 2603); return NS_ERROR_INVALID_POINTER; } } while (false)
;
2604
2605 RefPtr<nsDocShell> root = this;
2606 RefPtr<nsDocShell> parent = root->GetInProcessParentDocshell();
2607 while (parent) {
2608 root = parent;
2609 parent = root->GetInProcessParentDocshell();
2610 }
2611
2612 root.forget(aRootTreeItem);
2613 return NS_OK;
2614}
2615
2616NS_IMETHODIMPnsresult
2617nsDocShell::GetInProcessSameTypeRootTreeItem(
2618 nsIDocShellTreeItem** aRootTreeItem) {
2619 NS_ENSURE_ARG_POINTER(aRootTreeItem)do { if ((__builtin_expect(!!(!(aRootTreeItem)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aRootTreeItem" ") failed"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 2619); return NS_ERROR_INVALID_POINTER; } } while (false)
;
2620 *aRootTreeItem = static_cast<nsIDocShellTreeItem*>(this);
2621
2622 nsCOMPtr<nsIDocShellTreeItem> parent;
2623 NS_ENSURE_SUCCESS(GetInProcessSameTypeParent(getter_AddRefs(parent)),do { nsresult __rv = GetInProcessSameTypeParent(getter_AddRefs
(parent)); 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", "GetInProcessSameTypeParent(getter_AddRefs(parent))"
, "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/docshell/base/nsDocShell.cpp"
, 2624); return NS_ERROR_FAILURE; } } while (false)
2624 NS_ERROR_FAILURE)do { nsresult __rv = GetInProcessSameTypeParent(getter_AddRefs
(parent)); 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", "GetInProcessSameTypeParent(getter_AddRefs(parent))"
, "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/docshell/base/nsDocShell.cpp"
, 2624); return NS_ERROR_FAILURE; } } while (false)
;
2625 while (parent) {
2626 *aRootTreeItem = parent;
2627 NS_ENSURE_SUCCESS(do { nsresult __rv = (*aRootTreeItem)->GetInProcessSameTypeParent
(getter_AddRefs(parent)); 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", "(*aRootTreeItem)->GetInProcessSameTypeParent(getter_AddRefs(parent))"
, "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/docshell/base/nsDocShell.cpp"
, 2629); return NS_ERROR_FAILURE; } } while (false)
2628 (*aRootTreeItem)->GetInProcessSameTypeParent(getter_AddRefs(parent)),do { nsresult __rv = (*aRootTreeItem)->GetInProcessSameTypeParent
(getter_AddRefs(parent)); 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", "(*aRootTreeItem)->GetInProcessSameTypeParent(getter_AddRefs(parent))"
, "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/docshell/base/nsDocShell.cpp"
, 2629); return NS_ERROR_FAILURE; } } while (false)
2629 NS_ERROR_FAILURE)do { nsresult __rv = (*aRootTreeItem)->GetInProcessSameTypeParent
(getter_AddRefs(parent)); 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", "(*aRootTreeItem)->GetInProcessSameTypeParent(getter_AddRefs(parent))"
, "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/docshell/base/nsDocShell.cpp"
, 2629); return NS_ERROR_FAILURE; } } while (false)
;
2630 }
2631 NS_ADDREF(*aRootTreeItem)(*aRootTreeItem)->AddRef();
2632 return NS_OK;
2633}
2634
2635NS_IMETHODIMPnsresult
2636nsDocShell::GetTreeOwner(nsIDocShellTreeOwner** aTreeOwner) {
2637 NS_ENSURE_ARG_POINTER(aTreeOwner)do { if ((__builtin_expect(!!(!(aTreeOwner)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aTreeOwner" ") failed",
nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 2637); return NS_ERROR_INVALID_POINTER; } } while (false)
;
2638
2639 *aTreeOwner = mTreeOwner;
2640 NS_IF_ADDREF(*aTreeOwner)ns_if_addref(*aTreeOwner);
2641 return NS_OK;
2642}
2643
2644NS_IMETHODIMPnsresult
2645nsDocShell::SetTreeOwner(nsIDocShellTreeOwner* aTreeOwner) {
2646 if (mIsBeingDestroyed && aTreeOwner) {
2647 return NS_ERROR_FAILURE;
2648 }
2649
2650 // Don't automatically set the progress based on the tree owner for frames
2651 if (!IsSubframe()) {
2652 nsCOMPtr<nsIWebProgress> webProgress =
2653 do_QueryInterface(GetAsSupports(this));
2654
2655 if (webProgress) {
2656 nsCOMPtr<nsIWebProgressListener> oldListener =
2657 do_QueryInterface(mTreeOwner);
2658 nsCOMPtr<nsIWebProgressListener> newListener =
2659 do_QueryInterface(aTreeOwner);
2660
2661 if (oldListener) {
2662 webProgress->RemoveProgressListener(oldListener);
2663 }
2664
2665 if (newListener) {
2666 webProgress->AddProgressListener(newListener,
2667 nsIWebProgress::NOTIFY_ALL);
2668 }
2669 }
2670 }
2671
2672 mTreeOwner = aTreeOwner; // Weak reference per API
2673
2674 for (auto* childDocLoader : mChildList.ForwardRange()) {
2675 nsCOMPtr<nsIDocShellTreeItem> child = do_QueryObject(childDocLoader);
2676 NS_ENSURE_TRUE(child, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(child)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "child" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 2676); return NS_ERROR_FAILURE; } } while (false)
;
2677
2678 if (child->ItemType() == mItemType) {
2679 child->SetTreeOwner(aTreeOwner);
2680 }
2681 }
2682
2683 // If we're in the content process and have had a TreeOwner set on us, extract
2684 // our BrowserChild actor. If we've already had our BrowserChild set, assert
2685 // that it hasn't changed.
2686 if (mTreeOwner && XRE_IsContentProcess()) {
2687 nsCOMPtr<nsIBrowserChild> newBrowserChild = do_GetInterface(mTreeOwner);
2688 MOZ_ASSERT(newBrowserChild,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(newBrowserChild)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(newBrowserChild))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("newBrowserChild"
" (" "No BrowserChild actor for tree owner in Content!" ")",
"/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 2689); AnnotateMozCrashReason("MOZ_ASSERT" "(" "newBrowserChild"
") (" "No BrowserChild actor for tree owner in Content!" ")"
); do { *((volatile int*)__null) = 2689; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2689 "No BrowserChild actor for tree owner in Content!")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(newBrowserChild)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(newBrowserChild))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("newBrowserChild"
" (" "No BrowserChild actor for tree owner in Content!" ")",
"/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 2689); AnnotateMozCrashReason("MOZ_ASSERT" "(" "newBrowserChild"
") (" "No BrowserChild actor for tree owner in Content!" ")"
); do { *((volatile int*)__null) = 2689; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2690
2691 if (mBrowserChild) {
2692 nsCOMPtr<nsIBrowserChild> oldBrowserChild =
2693 do_QueryReferent(mBrowserChild);
2694 MOZ_RELEASE_ASSERT(do { static_assert( mozilla::detail::AssertionConditionType<
decltype(oldBrowserChild == newBrowserChild)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(oldBrowserChild == newBrowserChild
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"oldBrowserChild == newBrowserChild" " (" "Cannot change BrowserChild during nsDocShell lifetime!"
")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 2696); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "oldBrowserChild == newBrowserChild"
") (" "Cannot change BrowserChild during nsDocShell lifetime!"
")"); do { *((volatile int*)__null) = 2696; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2695 oldBrowserChild == newBrowserChild,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(oldBrowserChild == newBrowserChild)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(oldBrowserChild == newBrowserChild
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"oldBrowserChild == newBrowserChild" " (" "Cannot change BrowserChild during nsDocShell lifetime!"
")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 2696); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "oldBrowserChild == newBrowserChild"
") (" "Cannot change BrowserChild during nsDocShell lifetime!"
")"); do { *((volatile int*)__null) = 2696; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2696 "Cannot change BrowserChild during nsDocShell lifetime!")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(oldBrowserChild == newBrowserChild)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(oldBrowserChild == newBrowserChild
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"oldBrowserChild == newBrowserChild" " (" "Cannot change BrowserChild during nsDocShell lifetime!"
")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 2696); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "oldBrowserChild == newBrowserChild"
") (" "Cannot change BrowserChild during nsDocShell lifetime!"
")"); do { *((volatile int*)__null) = 2696; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2697 } else {
2698 mBrowserChild = do_GetWeakReference(newBrowserChild);
2699 }
2700 }
2701
2702 return NS_OK;
2703}
2704
2705NS_IMETHODIMPnsresult
2706nsDocShell::GetHistoryID(nsID& aID) {
2707 aID = mBrowsingContext->GetHistoryID();
2708 return NS_OK;
2709}
2710
2711const nsID& nsDocShell::HistoryID() { return mBrowsingContext->GetHistoryID(); }
2712
2713NS_IMETHODIMPnsresult
2714nsDocShell::GetIsInUnload(bool* aIsInUnload) {
2715 *aIsInUnload = mFiredUnloadEvent;
2716 return NS_OK;
2717}
2718
2719NS_IMETHODIMPnsresult
2720nsDocShell::GetInProcessChildCount(int32_t* aChildCount) {
2721 NS_ENSURE_ARG_POINTER(aChildCount)do { if ((__builtin_expect(!!(!(aChildCount)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aChildCount" ") failed"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 2721); return NS_ERROR_INVALID_POINTER; } } while (false)
;
2722 *aChildCount = mChildList.Length();
2723 return NS_OK;
2724}
2725
2726NS_IMETHODIMPnsresult
2727nsDocShell::AddChild(nsIDocShellTreeItem* aChild) {
2728 NS_ENSURE_ARG_POINTER(aChild)do { if ((__builtin_expect(!!(!(aChild)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aChild" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 2728); return NS_ERROR_INVALID_POINTER; } } while (false)
;
2729
2730 RefPtr<nsDocLoader> childAsDocLoader = GetAsDocLoader(aChild);
2731 NS_ENSURE_TRUE(childAsDocLoader, NS_ERROR_UNEXPECTED)do { if ((__builtin_expect(!!(!(childAsDocLoader)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "childAsDocLoader" ") failed"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 2731); return NS_ERROR_UNEXPECTED; } } while (false)
;
2732
2733 // Make sure we're not creating a loop in the docshell tree
2734 nsDocLoader* ancestor = this;
2735 do {
2736 if (childAsDocLoader == ancestor) {
2737 return NS_ERROR_ILLEGAL_VALUE;
2738 }
2739 ancestor = ancestor->GetParent();
2740 } while (ancestor);
2741
2742 // Make sure to remove the child from its current parent.
2743 nsDocLoader* childsParent = childAsDocLoader->GetParent();
2744 if (childsParent) {
2745 nsresult rv = childsParent->RemoveChildLoader(childAsDocLoader);
2746 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/docshell/base/nsDocShell.cpp"
, 2746); return rv; } } while (false)
;
2747 }
2748
2749 // Make sure to clear the treeowner in case this child is a different type
2750 // from us.
2751 aChild->SetTreeOwner(nullptr);
2752
2753 nsresult res = AddChildLoader(childAsDocLoader);
2754 NS_ENSURE_SUCCESS(res, res)do { nsresult __rv = res; 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", "res", "res", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 2754); return res; } } while (false)
;
2755 NS_ASSERTION(!mChildList.IsEmpty(),do { if (!(!mChildList.IsEmpty())) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "child list must not be empty after a successful add", "!mChildList.IsEmpty()"
, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 2756); MOZ_PretendNoReturn(); } } while (0)
2756 "child list must not be empty after a successful add")do { if (!(!mChildList.IsEmpty())) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "child list must not be empty after a successful add", "!mChildList.IsEmpty()"
, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 2756); MOZ_PretendNoReturn(); } } while (0)
;
2757
2758 /* Set the child's global history if the parent has one */
2759 if (mBrowsingContext->GetUseGlobalHistory()) {
2760 // childDocShell->SetUseGlobalHistory(true);
2761 // this should be set through BC inherit
2762 MOZ_ASSERT(aChild->GetBrowsingContext()->GetUseGlobalHistory())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aChild->GetBrowsingContext()->GetUseGlobalHistory
())>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(aChild->GetBrowsingContext()->GetUseGlobalHistory
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("aChild->GetBrowsingContext()->GetUseGlobalHistory()",
"/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 2762); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aChild->GetBrowsingContext()->GetUseGlobalHistory()"
")"); do { *((volatile int*)__null) = 2762; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2763 }
2764
2765 if (aChild->ItemType() != mItemType) {
2766 return NS_OK;
2767 }
2768
2769 aChild->SetTreeOwner(mTreeOwner);
2770
2771 nsCOMPtr<nsIDocShell> childAsDocShell(do_QueryInterface(aChild));
2772 if (!childAsDocShell) {
2773 return NS_OK;
2774 }
2775
2776 // charset, style-disabling, and zoom will be inherited in SetupNewViewer()
2777
2778 // Now take this document's charset and set the child's parentCharset field
2779 // to it. We'll later use that field, in the loading process, for the
2780 // charset choosing algorithm.
2781 // If we fail, at any point, we just return NS_OK.
2782 // This code has some performance impact. But this will be reduced when
2783 // the current charset will finally be stored as an Atom, avoiding the
2784 // alias resolution extra look-up.
2785
2786 // we are NOT going to propagate the charset is this Chrome's docshell
2787 if (mItemType == nsIDocShellTreeItem::typeChrome) {
2788 return NS_OK;
2789 }
2790
2791 // get the parent's current charset
2792 if (!mDocumentViewer) {
2793 return NS_OK;
2794 }
2795 Document* doc = mDocumentViewer->GetDocument();
2796 if (!doc) {
2797 return NS_OK;
2798 }
2799
2800 const Encoding* parentCS = doc->GetDocumentCharacterSet();
2801 int32_t charsetSource = doc->GetDocumentCharacterSetSource();
2802 // set the child's parentCharset
2803 childAsDocShell->SetParentCharset(parentCS, charsetSource,
2804 doc->NodePrincipal());
2805
2806 // printf("### 1 >>> Adding child. Parent CS = %s. ItemType = %d.\n",
2807 // NS_LossyConvertUTF16toASCII(parentCS).get(), mItemType);
2808
2809 return NS_OK;
2810}
2811
2812NS_IMETHODIMPnsresult
2813nsDocShell::RemoveChild(nsIDocShellTreeItem* aChild) {
2814 NS_ENSURE_ARG_POINTER(aChild)do { if ((__builtin_expect(!!(!(aChild)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aChild" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 2814); return NS_ERROR_INVALID_POINTER; } } while (false)
;
2815
2816 RefPtr<nsDocLoader> childAsDocLoader = GetAsDocLoader(aChild);
2817 NS_ENSURE_TRUE(childAsDocLoader, NS_ERROR_UNEXPECTED)do { if ((__builtin_expect(!!(!(childAsDocLoader)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "childAsDocLoader" ") failed"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 2817); return NS_ERROR_UNEXPECTED; } } while (false)
;
2818
2819 nsresult rv = RemoveChildLoader(childAsDocLoader);
2820 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/docshell/base/nsDocShell.cpp"
, 2820); return rv; } } while (false)
;
2821
2822 aChild->SetTreeOwner(nullptr);
2823
2824 return nsDocLoader::AddDocLoaderAsChildOfRoot(childAsDocLoader);
2825}
2826
2827NS_IMETHODIMPnsresult
2828nsDocShell::GetInProcessChildAt(int32_t aIndex, nsIDocShellTreeItem** aChild) {
2829 NS_ENSURE_ARG_POINTER(aChild)do { if ((__builtin_expect(!!(!(aChild)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aChild" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 2829); return NS_ERROR_INVALID_POINTER; } } while (false)
;
2830
2831 RefPtr<nsDocShell> child = GetInProcessChildAt(aIndex);
2832 NS_ENSURE_TRUE(child, NS_ERROR_UNEXPECTED)do { if ((__builtin_expect(!!(!(child)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "child" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 2832); return NS_ERROR_UNEXPECTED; } } while (false)
;
2833
2834 child.forget(aChild);
2835
2836 return NS_OK;
2837}
2838
2839nsDocShell* nsDocShell::GetInProcessChildAt(int32_t aIndex) {
2840#ifdef DEBUG1
2841 if (aIndex < 0) {
2842 NS_WARNING("Negative index passed to GetChildAt")NS_DebugBreak(NS_DEBUG_WARNING, "Negative index passed to GetChildAt"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 2842)
;
2843 } else if (static_cast<uint32_t>(aIndex) >= mChildList.Length()) {
2844 NS_WARNING("Too large an index passed to GetChildAt")NS_DebugBreak(NS_DEBUG_WARNING, "Too large an index passed to GetChildAt"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 2844)
;
2845 }
2846#endif
2847
2848 nsIDocumentLoader* child = ChildAt(aIndex);
2849
2850 // child may be nullptr here.
2851 return static_cast<nsDocShell*>(child);
2852}
2853
2854nsresult nsDocShell::AddChildSHEntry(nsISHEntry* aCloneRef,
2855 nsISHEntry* aNewEntry,
2856 int32_t aChildOffset, uint32_t aLoadType,
2857 bool aCloneChildren) {
2858 MOZ_ASSERT(!mozilla::SessionHistoryInParent())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mozilla::SessionHistoryInParent())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mozilla::SessionHistoryInParent
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!mozilla::SessionHistoryInParent()", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 2858); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mozilla::SessionHistoryInParent()"
")"); do { *((volatile int*)__null) = 2858; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2859 nsresult rv = NS_OK;
2860
2861 if (mLSHE && aLoadType != LOAD_PUSHSTATE) {
2862 /* You get here if you are currently building a
2863 * hierarchy ie.,you just visited a frameset page
2864 */
2865 if (NS_FAILED(mLSHE->ReplaceChild(aNewEntry))((bool)(__builtin_expect(!!(NS_FAILED_impl(mLSHE->ReplaceChild
(aNewEntry))), 0)))
) {
2866 rv = mLSHE->AddChild(aNewEntry, aChildOffset);
2867 }
2868 } else if (!aCloneRef) {
2869 /* This is an initial load in some subframe. Just append it if we can */
2870 if (mOSHE) {
2871 rv = mOSHE->AddChild(aNewEntry, aChildOffset, UseRemoteSubframes());
2872 }
2873 } else {
2874 RefPtr<ChildSHistory> shistory = GetRootSessionHistory();
2875 if (shistory) {
2876 rv = shistory->LegacySHistory()->AddChildSHEntryHelper(
2877 aCloneRef, aNewEntry, mBrowsingContext->Top(), aCloneChildren);
2878 }
2879 }
2880 return rv;
2881}
2882
2883nsresult nsDocShell::AddChildSHEntryToParent(nsISHEntry* aNewEntry,
2884 int32_t aChildOffset,
2885 bool aCloneChildren) {
2886 MOZ_ASSERT(!mozilla::SessionHistoryInParent())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mozilla::SessionHistoryInParent())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mozilla::SessionHistoryInParent
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!mozilla::SessionHistoryInParent()", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 2886); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mozilla::SessionHistoryInParent()"
")"); do { *((volatile int*)__null) = 2886; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2887 /* You will get here when you are in a subframe and
2888 * a new url has been loaded on you.
2889 * The mOSHE in this subframe will be the previous url's
2890 * mOSHE. This mOSHE will be used as the identification
2891 * for this subframe in the CloneAndReplace function.
2892 */
2893
2894 // In this case, we will end up calling AddEntry, which increases the
2895 // current index by 1
2896 RefPtr<ChildSHistory> rootSH = GetRootSessionHistory();
2897 if (rootSH) {
2898 mPreviousEntryIndex = rootSH->Index();
2899 }
2900
2901 nsresult rv;
2902 // XXX(farre): this is not Fission safe, expect errors. This never
2903 // get's executed once session history in the parent is enabled.
2904 nsCOMPtr<nsIDocShell> parent = do_QueryInterface(GetAsSupports(mParent), &rv);
2905 NS_WARNING_ASSERTION(do { if (!(parent || !UseRemoteSubframes())) { NS_DebugBreak(
NS_DEBUG_WARNING, "Failed to add child session history entry! This will be resolved once "
"session history in the parent is enabled.", "parent || !UseRemoteSubframes()"
, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 2908); } } while (false)
2906 parent || !UseRemoteSubframes(),do { if (!(parent || !UseRemoteSubframes())) { NS_DebugBreak(
NS_DEBUG_WARNING, "Failed to add child session history entry! This will be resolved once "
"session history in the parent is enabled.", "parent || !UseRemoteSubframes()"
, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 2908); } } while (false)
2907 "Failed to add child session history entry! This will be resolved once "do { if (!(parent || !UseRemoteSubframes())) { NS_DebugBreak(
NS_DEBUG_WARNING, "Failed to add child session history entry! This will be resolved once "
"session history in the parent is enabled.", "parent || !UseRemoteSubframes()"
, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 2908); } } while (false)
2908 "session history in the parent is enabled.")do { if (!(parent || !UseRemoteSubframes())) { NS_DebugBreak(
NS_DEBUG_WARNING, "Failed to add child session history entry! This will be resolved once "
"session history in the parent is enabled.", "parent || !UseRemoteSubframes()"
, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 2908); } } while (false)
;
2909 if (parent) {
2910 rv = nsDocShell::Cast(parent)->AddChildSHEntry(
2911 mOSHE, aNewEntry, aChildOffset, mLoadType, aCloneChildren);
2912 }
2913
2914 if (rootSH) {
2915 mLoadedEntryIndex = rootSH->Index();
2916
2917 if (MOZ_UNLIKELY(MOZ_LOG_TEST(gPageCacheLog, LogLevel::Verbose))(__builtin_expect(!!((__builtin_expect(!!(mozilla::detail::log_test
(gPageCacheLog, LogLevel::Verbose)), 0))), 0))
) {
2918 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, "Previous index: %d, Loaded index: %d", mPreviousEntryIndex
, mLoadedEntryIndex); } } while (0)
2919 ("Previous index: %d, Loaded index: %d", mPreviousEntryIndex,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, "Previous index: %d, Loaded index: %d", mPreviousEntryIndex
, mLoadedEntryIndex); } } while (0)
2920 mLoadedEntryIndex))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, "Previous index: %d, Loaded index: %d", mPreviousEntryIndex
, mLoadedEntryIndex); } } while (0)
;
2921 }
2922 }
2923
2924 return rv;
2925}
2926
2927NS_IMETHODIMPnsresult
2928nsDocShell::GetCurrentSHEntry(nsISHEntry** aEntry, bool* aOSHE) {
2929 *aOSHE = false;
2930 *aEntry = nullptr;
2931 if (mLSHE) {
2932 NS_ADDREF(*aEntry = mLSHE)(*aEntry = mLSHE)->AddRef();
2933 } else if (mOSHE) {
2934 NS_ADDREF(*aEntry = mOSHE)(*aEntry = mOSHE)->AddRef();
2935 *aOSHE = true;
2936 }
2937 return NS_OK;
2938}
2939
2940NS_IMETHODIMPnsresult nsDocShell::SynchronizeLayoutHistoryState() {
2941 if (mActiveEntry && mActiveEntry->GetLayoutHistoryState() &&
2942 mBrowsingContext) {
2943 if (XRE_IsContentProcess()) {
2944 dom::ContentChild* contentChild = dom::ContentChild::GetSingleton();
2945 if (contentChild) {
2946 contentChild->SendSynchronizeLayoutHistoryState(
2947 mBrowsingContext, mActiveEntry->GetLayoutHistoryState());
2948 }
2949 } else {
2950 SessionHistoryEntry* entry =
2951 mBrowsingContext->Canonical()->GetActiveSessionHistoryEntry();
2952 if (entry) {
2953 entry->SetLayoutHistoryState(mActiveEntry->GetLayoutHistoryState());
2954 }
2955 }
2956 if (mLoadingEntry &&
2957 mLoadingEntry->mInfo.SharedId() == mActiveEntry->SharedId()) {
2958 mLoadingEntry->mInfo.SetLayoutHistoryState(
2959 mActiveEntry->GetLayoutHistoryState());
2960 }
2961 }
2962
2963 return NS_OK;
2964}
2965
2966void nsDocShell::SetLoadGroupDefaultLoadFlags(nsLoadFlags aLoadFlags) {
2967 if (mLoadGroup) {
2968 mLoadGroup->SetDefaultLoadFlags(aLoadFlags);
2969 } else {
2970 NS_WARNING(NS_DebugBreak(NS_DEBUG_WARNING, "nsDocShell::SetLoadGroupDefaultLoadFlags has no loadGroup to "
"propagate the mode to", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 2972)
2971 "nsDocShell::SetLoadGroupDefaultLoadFlags has no loadGroup to "NS_DebugBreak(NS_DEBUG_WARNING, "nsDocShell::SetLoadGroupDefaultLoadFlags has no loadGroup to "
"propagate the mode to", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 2972)
2972 "propagate the mode to")NS_DebugBreak(NS_DEBUG_WARNING, "nsDocShell::SetLoadGroupDefaultLoadFlags has no loadGroup to "
"propagate the mode to", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 2972)
;
2973 }
2974}
2975
2976nsIScriptGlobalObject* nsDocShell::GetScriptGlobalObject() {
2977 NS_ENSURE_SUCCESS(EnsureScriptEnvironment(), nullptr)do { nsresult __rv = EnsureScriptEnvironment(); 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", "EnsureScriptEnvironment()", "nullptr", static_cast
<uint32_t>(__rv), name ? " (" : "", name ? name : "", name
? ")" : ""); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 2977); return nullptr; } } while (false)
;
2978 return mScriptGlobal;
2979}
2980
2981Document* nsDocShell::GetDocument() {
2982 NS_ENSURE_SUCCESS(EnsureDocumentViewer(), nullptr)do { nsresult __rv = EnsureDocumentViewer(); 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", "EnsureDocumentViewer()", "nullptr", static_cast
<uint32_t>(__rv), name ? " (" : "", name ? name : "", name
? ")" : ""); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 2982); return nullptr; } } while (false)
;
2983 return mDocumentViewer->GetDocument();
2984}
2985
2986Document* nsDocShell::GetExtantDocument() {
2987 return mDocumentViewer ? mDocumentViewer->GetDocument() : nullptr;
2988}
2989
2990nsPIDOMWindowOuter* nsDocShell::GetWindow() {
2991 if (NS_FAILED(EnsureScriptEnvironment())((bool)(__builtin_expect(!!(NS_FAILED_impl(EnsureScriptEnvironment
())), 0)))
) {
2992 return nullptr;
2993 }
2994 return mScriptGlobal;
2995}
2996
2997NS_IMETHODIMPnsresult
2998nsDocShell::GetDomWindow(mozIDOMWindowProxy** aWindow) {
2999 NS_ENSURE_ARG_POINTER(aWindow)do { if ((__builtin_expect(!!(!(aWindow)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aWindow" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 2999); return NS_ERROR_INVALID_POINTER; } } while (false)
;
3000
3001 nsresult rv = EnsureScriptEnvironment();
3002 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/docshell/base/nsDocShell.cpp"
, 3002); return rv; } } while (false)
;
3003
3004 RefPtr<nsGlobalWindowOuter> window = mScriptGlobal;
3005 window.forget(aWindow);
3006 return NS_OK;
3007}
3008
3009NS_IMETHODIMPnsresult
3010nsDocShell::GetMessageManager(ContentFrameMessageManager** aMessageManager) {
3011 RefPtr<ContentFrameMessageManager> mm;
3012 if (RefPtr<BrowserChild> browserChild = BrowserChild::GetFrom(this)) {
3013 mm = browserChild->GetMessageManager();
3014 } else if (nsPIDOMWindowOuter* win = GetWindow()) {
3015 mm = win->GetMessageManager();
3016 }
3017 mm.forget(aMessageManager);
3018 return NS_OK;
3019}
3020
3021NS_IMETHODIMPnsresult
3022nsDocShell::GetIsNavigating(bool* aOut) {
3023 *aOut = mIsNavigating;
3024 return NS_OK;
3025}
3026
3027void nsDocShell::ClearFrameHistory(nsISHEntry* aEntry) {
3028 MOZ_ASSERT(!mozilla::SessionHistoryInParent())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mozilla::SessionHistoryInParent())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mozilla::SessionHistoryInParent
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!mozilla::SessionHistoryInParent()", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 3028); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mozilla::SessionHistoryInParent()"
")"); do { *((volatile int*)__null) = 3028; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3029 RefPtr<ChildSHistory> rootSH = GetRootSessionHistory();
3030 if (!rootSH || !aEntry) {
3031 return;
3032 }
3033
3034 rootSH->LegacySHistory()->RemoveFrameEntries(aEntry);
3035}
3036
3037//-------------------------------------
3038//-- Helper Method for Print discovery
3039//-------------------------------------
3040bool nsDocShell::NavigationBlockedByPrinting(bool aDisplayErrorDialog) {
3041 if (!mBrowsingContext->Top()->GetIsPrinting()) {
3042 return false;
3043 }
3044 if (aDisplayErrorDialog) {
3045 DisplayLoadError(NS_ERROR_DOCUMENT_IS_PRINTMODE, nullptr, nullptr, nullptr);
3046 }
3047 return true;
3048}
3049
3050bool nsDocShell::IsNavigationAllowed(bool aDisplayPrintErrorDialog,
3051 bool aCheckIfUnloadFired) {
3052 bool isAllowed = !NavigationBlockedByPrinting(aDisplayPrintErrorDialog) &&
3053 (!aCheckIfUnloadFired || !mFiredUnloadEvent);
3054 if (!isAllowed) {
3055 return false;
3056 }
3057 if (!mDocumentViewer) {
3058 return true;
3059 }
3060 bool firingBeforeUnload;
3061 mDocumentViewer->GetBeforeUnloadFiring(&firingBeforeUnload);
3062 return !firingBeforeUnload;
3063}
3064
3065//*****************************************************************************
3066// nsDocShell::nsIWebNavigation
3067//*****************************************************************************
3068
3069NS_IMETHODIMPnsresult
3070nsDocShell::GetCanGoBack(bool* aCanGoBack) {
3071 *aCanGoBack = false;
3072 if (!IsNavigationAllowed(false)) {
3073 return NS_OK; // JS may not handle returning of an error code
3074 }
3075 RefPtr<ChildSHistory> rootSH = GetRootSessionHistory();
3076 if (rootSH) {
3077 *aCanGoBack = rootSH->CanGo(-1);
3078 MOZ_LOG(gSHLog, LogLevel::Verbose,do { const ::mozilla::LogModule* moz_real_module = gSHLog; if
((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Verbose)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Verbose, "nsDocShell %p CanGoBack()->%d", this
, *aCanGoBack); } } while (0)
3079 ("nsDocShell %p CanGoBack()->%d", this, *aCanGoBack))do { const ::mozilla::LogModule* moz_real_module = gSHLog; if
((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Verbose)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Verbose, "nsDocShell %p CanGoBack()->%d", this
, *aCanGoBack); } } while (0)
;
3080
3081 return NS_OK;
3082 }
3083 return NS_ERROR_FAILURE;
3084}
3085
3086NS_IMETHODIMPnsresult
3087nsDocShell::GetCanGoForward(bool* aCanGoForward) {
3088 *aCanGoForward = false;
3089 if (!IsNavigationAllowed(false)) {
3090 return NS_OK; // JS may not handle returning of an error code
3091 }
3092 RefPtr<ChildSHistory> rootSH = GetRootSessionHistory();
3093 if (rootSH) {
3094 *aCanGoForward = rootSH->CanGo(1);
3095 MOZ_LOG(gSHLog, LogLevel::Verbose,do { const ::mozilla::LogModule* moz_real_module = gSHLog; if
((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Verbose)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Verbose, "nsDocShell %p CanGoForward()->%d", this
, *aCanGoForward); } } while (0)
3096 ("nsDocShell %p CanGoForward()->%d", this, *aCanGoForward))do { const ::mozilla::LogModule* moz_real_module = gSHLog; if
((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Verbose)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Verbose, "nsDocShell %p CanGoForward()->%d", this
, *aCanGoForward); } } while (0)
;
3097 return NS_OK;
3098 }
3099 return NS_ERROR_FAILURE;
3100}
3101
3102NS_IMETHODIMPnsresult
3103nsDocShell::GoBack(bool aRequireUserInteraction, bool aUserActivation) {
3104 if (!IsNavigationAllowed()) {
3105 return NS_OK; // JS may not handle returning of an error code
3106 }
3107
3108 auto cleanupIsNavigating = MakeScopeExit([&]() { mIsNavigating = false; });
3109 mIsNavigating = true;
3110
3111 RefPtr<ChildSHistory> rootSH = GetRootSessionHistory();
3112 NS_ENSURE_TRUE(rootSH, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(rootSH)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "rootSH" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 3112); return NS_ERROR_FAILURE; } } while (false)
;
3113 ErrorResult rv;
3114 rootSH->Go(-1, aRequireUserInteraction, aUserActivation, rv);
3115 return rv.StealNSResult();
3116}
3117
3118NS_IMETHODIMPnsresult
3119nsDocShell::GoForward(bool aRequireUserInteraction, bool aUserActivation) {
3120 if (!IsNavigationAllowed()) {
3121 return NS_OK; // JS may not handle returning of an error code
3122 }
3123
3124 auto cleanupIsNavigating = MakeScopeExit([&]() { mIsNavigating = false; });
3125 mIsNavigating = true;
3126
3127 RefPtr<ChildSHistory> rootSH = GetRootSessionHistory();
3128 NS_ENSURE_TRUE(rootSH, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(rootSH)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "rootSH" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 3128); return NS_ERROR_FAILURE; } } while (false)
;
3129 ErrorResult rv;
3130 rootSH->Go(1, aRequireUserInteraction, aUserActivation, rv);
3131 return rv.StealNSResult();
3132}
3133
3134// XXX(nika): We may want to stop exposing this API in the child process? Going
3135// to a specific index from multiple different processes could definitely race.
3136NS_IMETHODIMPnsresult
3137nsDocShell::GotoIndex(int32_t aIndex, bool aUserActivation) {
3138 if (!IsNavigationAllowed()) {
3139 return NS_OK; // JS may not handle returning of an error code
3140 }
3141
3142 auto cleanupIsNavigating = MakeScopeExit([&]() { mIsNavigating = false; });
3143 mIsNavigating = true;
3144
3145 RefPtr<ChildSHistory> rootSH = GetRootSessionHistory();
3146 NS_ENSURE_TRUE(rootSH, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(rootSH)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "rootSH" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 3146); return NS_ERROR_FAILURE; } } while (false)
;
3147
3148 ErrorResult rv;
3149 rootSH->GotoIndex(aIndex, aIndex - rootSH->Index(), false, aUserActivation,
3150 rv);
3151 return rv.StealNSResult();
3152}
3153
3154nsresult nsDocShell::LoadURI(nsIURI* aURI,
3155 const LoadURIOptions& aLoadURIOptions) {
3156 if (!IsNavigationAllowed()) {
3157 return NS_OK; // JS may not handle returning of an error code
3158 }
3159 RefPtr<nsDocShellLoadState> loadState;
3160 nsresult rv = nsDocShellLoadState::CreateFromLoadURIOptions(
3161 mBrowsingContext, aURI, aLoadURIOptions, getter_AddRefs(loadState));
3162 MOZ_ASSERT(rv != NS_ERROR_MALFORMED_URI)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(rv != NS_ERROR_MALFORMED_URI)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(rv != NS_ERROR_MALFORMED_URI
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"rv != NS_ERROR_MALFORMED_URI", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 3162); AnnotateMozCrashReason("MOZ_ASSERT" "(" "rv != NS_ERROR_MALFORMED_URI"
")"); do { *((volatile int*)__null) = 3162; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3163 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) || !loadState) {
3164 return NS_ERROR_FAILURE;
3165 }
3166
3167 return LoadURI(loadState, true);
3168}
3169
3170NS_IMETHODIMPnsresult
3171nsDocShell::LoadURIFromScript(nsIURI* aURI,
3172 JS::Handle<JS::Value> aLoadURIOptions,
3173 JSContext* aCx) {
3174 // generate dictionary for aLoadURIOptions and forward call
3175 LoadURIOptions loadURIOptions;
3176 if (!loadURIOptions.Init(aCx, aLoadURIOptions)) {
3177 return NS_ERROR_INVALID_ARG;
3178 }
3179 return LoadURI(aURI, loadURIOptions);
3180}
3181
3182nsresult nsDocShell::FixupAndLoadURIString(
3183 const nsAString& aURIString, const LoadURIOptions& aLoadURIOptions) {
3184 if (!IsNavigationAllowed()) {
3185 return NS_OK; // JS may not handle returning of an error code
3186 }
3187
3188 RefPtr<nsDocShellLoadState> loadState;
3189 nsresult rv = nsDocShellLoadState::CreateFromLoadURIOptions(
3190 mBrowsingContext, aURIString, aLoadURIOptions, getter_AddRefs(loadState));
3191
3192 uint32_t loadFlags = aLoadURIOptions.mLoadFlags;
3193 if (NS_ERROR_MALFORMED_URI == rv) {
3194 MOZ_LOG(gSHLog, LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = gSHLog; if
((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "Creating an active entry on nsDocShell %p to %s (because "
"we're showing an error page)", this, NS_ConvertUTF16toUTF8(
aURIString).get()); } } while (0)
3195 ("Creating an active entry on nsDocShell %p to %s (because "do { const ::mozilla::LogModule* moz_real_module = gSHLog; if
((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "Creating an active entry on nsDocShell %p to %s (because "
"we're showing an error page)", this, NS_ConvertUTF16toUTF8(
aURIString).get()); } } while (0)
3196 "we're showing an error page)",do { const ::mozilla::LogModule* moz_real_module = gSHLog; if
((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "Creating an active entry on nsDocShell %p to %s (because "
"we're showing an error page)", this, NS_ConvertUTF16toUTF8(
aURIString).get()); } } while (0)
3197 this, NS_ConvertUTF16toUTF8(aURIString).get()))do { const ::mozilla::LogModule* moz_real_module = gSHLog; if
((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "Creating an active entry on nsDocShell %p to %s (because "
"we're showing an error page)", this, NS_ConvertUTF16toUTF8(
aURIString).get()); } } while (0)
;
3198
3199 // We need to store a session history entry. We don't have a valid URI, so
3200 // we use about:blank instead.
3201 nsCOMPtr<nsIURI> uri;
3202 MOZ_ALWAYS_SUCCEEDS(NS_NewURI(getter_AddRefs(uri), "about:blank"_ns))do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(NS_NewURI(getter_AddRefs(uri), "about:blank"_ns))), 1)))), 1
))) { } else { do { static_assert( mozilla::detail::AssertionConditionType
<decltype(false)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("false" " (" "NS_SUCCEEDED(NS_NewURI(getter_AddRefs(uri), \"about:blank\"_ns))"
")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 3202); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "false"
") (" "NS_SUCCEEDED(NS_NewURI(getter_AddRefs(uri), \"about:blank\"_ns))"
")"); do { *((volatile int*)__null) = 3202; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
3203 nsCOMPtr<nsIPrincipal> triggeringPrincipal;
3204 if (aLoadURIOptions.mTriggeringPrincipal) {
3205 triggeringPrincipal = aLoadURIOptions.mTriggeringPrincipal;
3206 } else {
3207 triggeringPrincipal = nsContentUtils::GetSystemPrincipal();
3208 }
3209 if (mozilla::SessionHistoryInParent()) {
3210 mActiveEntry = MakeUnique<SessionHistoryInfo>(
3211 uri, triggeringPrincipal, nullptr, nullptr, nullptr,
3212 nsLiteralCString("text/html"));
3213 mBrowsingContext->SetActiveSessionHistoryEntry(
3214 Nothing(), mActiveEntry.get(), MAKE_LOAD_TYPE(LOAD_NORMAL, loadFlags)((LOAD_NORMAL) | ((loadFlags) << 16)),
3215 /* aUpdatedCacheKey = */ 0);
3216 }
3217 if (DisplayLoadError(rv, nullptr, PromiseFlatStringTPromiseFlatString<char16_t>(aURIString).get(),
3218 nullptr) &&
3219 (loadFlags & LOAD_FLAGS_ERROR_LOAD_CHANGES_RV) != 0) {
3220 return NS_ERROR_LOAD_SHOWED_ERRORPAGE;
3221 }
3222 }
3223
3224 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) || !loadState) {
3225 return NS_ERROR_FAILURE;
3226 }
3227
3228 return LoadURI(loadState, true);
3229}
3230
3231NS_IMETHODIMPnsresult
3232nsDocShell::FixupAndLoadURIStringFromScript(
3233 const nsAString& aURIString, JS::Handle<JS::Value> aLoadURIOptions,
3234 JSContext* aCx) {
3235 // generate dictionary for aLoadURIOptions and forward call
3236 LoadURIOptions loadURIOptions;
3237 if (!loadURIOptions.Init(aCx, aLoadURIOptions)) {
3238 return NS_ERROR_INVALID_ARG;
3239 }
3240 return FixupAndLoadURIString(aURIString, loadURIOptions);
3241}
3242
3243void nsDocShell::UnblockEmbedderLoadEventForFailure(bool aFireFrameErrorEvent) {
3244 // If we're not in a content frame, or are at a BrowsingContext tree boundary,
3245 // such as the content-chrome boundary, don't fire the error event.
3246 if (mBrowsingContext->IsTopContent() || mBrowsingContext->IsChrome()) {
3247 return;
3248 }
3249
3250 // If embedder is same-process, then unblocking the load event is already
3251 // handled by nsDocLoader. Fire the error event on our embedder element if
3252 // requested.
3253 //
3254 // XXX: Bug 1440212 is looking into potentially changing this behaviour to act
3255 // more like the remote case when in-process.
3256 RefPtr<Element> element = mBrowsingContext->GetEmbedderElement();
3257 if (element) {
3258 if (aFireFrameErrorEvent) {
3259 if (RefPtr<nsFrameLoaderOwner> flo = do_QueryObject(element)) {
3260 if (RefPtr<nsFrameLoader> fl = flo->GetFrameLoader()) {
3261 fl->FireErrorEvent();
3262 }
3263 }
3264 }
3265 return;
3266 }
3267
3268 // If we have a cross-process parent document, we must notify it that we no
3269 // longer block its load event. This is necessary for OOP sub-documents
3270 // because error documents do not result in a call to
3271 // SendMaybeFireEmbedderLoadEvents via any of the normal call paths.
3272 // (Obviously, we must do this before any of the returns below.)
3273 RefPtr<BrowserChild> browserChild = BrowserChild::GetFrom(this);
3274 if (browserChild &&
3275 !mBrowsingContext->GetParentWindowContext()->IsInProcess()) {
3276 mozilla::Unused << browserChild->SendMaybeFireEmbedderLoadEvents(
3277 aFireFrameErrorEvent ? EmbedderElementEventType::ErrorEvent
3278 : EmbedderElementEventType::NoEvent);
3279 }
3280}
3281
3282NS_IMETHODIMPnsresult
3283nsDocShell::DisplayLoadError(nsresult aError, nsIURI* aURI,
3284 const char16_t* aURL, nsIChannel* aFailedChannel,
3285 bool* aDisplayedErrorPage) {
3286 MOZ_LOG(gDocShellLeakLog, LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = gDocShellLeakLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "DOCSHELL %p DisplayLoadError %s\n", this,
aURI ? aURI->GetSpecOrDefault().get() : ""); } } while (0
)
3287 ("DOCSHELL %p DisplayLoadError %s\n", this,do { const ::mozilla::LogModule* moz_real_module = gDocShellLeakLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "DOCSHELL %p DisplayLoadError %s\n", this,
aURI ? aURI->GetSpecOrDefault().get() : ""); } } while (0
)
3288 aURI ? aURI->GetSpecOrDefault().get() : ""))do { const ::mozilla::LogModule* moz_real_module = gDocShellLeakLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "DOCSHELL %p DisplayLoadError %s\n", this,
aURI ? aURI->GetSpecOrDefault().get() : ""); } } while (0
)
;
3289
3290 *aDisplayedErrorPage = false;
3291 // Get prompt and string bundle services
3292 nsCOMPtr<nsIPrompt> prompter;
3293 nsCOMPtr<nsIStringBundle> stringBundle;
3294 GetPromptAndStringBundle(getter_AddRefs(prompter),
3295 getter_AddRefs(stringBundle));
3296
3297 NS_ENSURE_TRUE(stringBundle, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(stringBundle)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "stringBundle" ") failed"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 3297); return NS_ERROR_FAILURE; } } while (false)
;
3298 NS_ENSURE_TRUE(prompter, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(prompter)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "prompter" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 3298); return NS_ERROR_FAILURE; } } while (false)
;
3299
3300 const char* error = nullptr;
3301 // The key used to select the appropriate error message from the properties
3302 // file.
3303 const char* errorDescriptionID = nullptr;
3304 AutoTArray<nsString, 3> formatStrs;
3305 bool addHostPort = false;
3306 bool isBadStsCertError = false;
3307 nsresult rv = NS_OK;
3308 nsAutoString messageStr;
3309 nsAutoCString cssClass;
3310 nsAutoCString errorPage;
3311
3312 errorPage.AssignLiteral("neterror");
3313
3314 // Turn the error code into a human readable error message.
3315 if (NS_ERROR_UNKNOWN_PROTOCOL == aError) {
3316 NS_ENSURE_ARG_POINTER(aURI)do { if ((__builtin_expect(!!(!(aURI)), 0))) { NS_DebugBreak(
NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aURI" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 3316); return NS_ERROR_INVALID_POINTER; } } while (false)
;
3317
3318 // Extract the schemes into a comma delimited list.
3319 nsAutoCString scheme;
3320 aURI->GetScheme(scheme);
3321 CopyASCIItoUTF16(scheme, *formatStrs.AppendElement());
3322 nsCOMPtr<nsINestedURI> nestedURI = do_QueryInterface(aURI);
3323 while (nestedURI) {
3324 nsCOMPtr<nsIURI> tempURI;
3325 nsresult rv2;
3326 rv2 = nestedURI->GetInnerURI(getter_AddRefs(tempURI));
3327 if (NS_SUCCEEDED(rv2)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv2)), 1))) && tempURI) {
3328 tempURI->GetScheme(scheme);
3329 formatStrs[0].AppendLiteral(", ");
3330 AppendASCIItoUTF16(scheme, formatStrs[0]);
3331 }
3332 nestedURI = do_QueryInterface(tempURI);
3333 }
3334 error = "unknownProtocolFound";
3335 } else if (NS_ERROR_NET_ERROR_RESPONSE == aError) {
3336 NS_ENSURE_ARG_POINTER(aURI)do { if ((__builtin_expect(!!(!(aURI)), 0))) { NS_DebugBreak(
NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aURI" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 3336); return NS_ERROR_INVALID_POINTER; } } while (false)
;
3337 error = "serverError";
3338 } else if (NS_ERROR_FILE_NOT_FOUND == aError) {
3339 NS_ENSURE_ARG_POINTER(aURI)do { if ((__builtin_expect(!!(!(aURI)), 0))) { NS_DebugBreak(
NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aURI" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 3339); return NS_ERROR_INVALID_POINTER; } } while (false)
;
3340 error = "fileNotFound";
3341 } else if (NS_ERROR_FILE_ACCESS_DENIED == aError) {
3342 NS_ENSURE_ARG_POINTER(aURI)do { if ((__builtin_expect(!!(!(aURI)), 0))) { NS_DebugBreak(
NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aURI" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 3342); return NS_ERROR_INVALID_POINTER; } } while (false)
;
3343 error = "fileAccessDenied";
3344 } else if (NS_ERROR_UNKNOWN_HOST == aError) {
3345 NS_ENSURE_ARG_POINTER(aURI)do { if ((__builtin_expect(!!(!(aURI)), 0))) { NS_DebugBreak(
NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aURI" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 3345); return NS_ERROR_INVALID_POINTER; } } while (false)
;
3346 // Get the host
3347 nsAutoCString host;
3348 nsCOMPtr<nsIURI> innermostURI = NS_GetInnermostURI(aURI);
3349 innermostURI->GetHost(host);
3350 CopyUTF8toUTF16(host, *formatStrs.AppendElement());
3351 errorDescriptionID = "dnsNotFound2";
3352 error = "dnsNotFound";
3353 } else if (NS_ERROR_CONNECTION_REFUSED == aError ||
3354 NS_ERROR_PROXY_BAD_GATEWAY == aError) {
3355 NS_ENSURE_ARG_POINTER(aURI)do { if ((__builtin_expect(!!(!(aURI)), 0))) { NS_DebugBreak(
NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aURI" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 3355); return NS_ERROR_INVALID_POINTER; } } while (false)
;
3356 addHostPort = true;
3357 error = "connectionFailure";
3358 } else if (NS_ERROR_NET_INTERRUPT == aError) {
3359 NS_ENSURE_ARG_POINTER(aURI)do { if ((__builtin_expect(!!(!(aURI)), 0))) { NS_DebugBreak(
NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aURI" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 3359); return NS_ERROR_INVALID_POINTER; } } while (false)
;
3360 addHostPort = true;
3361 error = "netInterrupt";
3362 } else if (NS_ERROR_NET_TIMEOUT == aError ||
3363 NS_ERROR_PROXY_GATEWAY_TIMEOUT == aError ||
3364 NS_ERROR_NET_TIMEOUT_EXTERNAL == aError) {
3365 NS_ENSURE_ARG_POINTER(aURI)do { if ((__builtin_expect(!!(!(aURI)), 0))) { NS_DebugBreak(
NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aURI" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 3365); return NS_ERROR_INVALID_POINTER; } } while (false)
;
3366 // Get the host
3367 nsAutoCString host;
3368 aURI->GetHost(host);
3369 CopyUTF8toUTF16(host, *formatStrs.AppendElement());
3370 error = "netTimeout";
3371 } else if (NS_ERROR_CSP_FRAME_ANCESTOR_VIOLATION == aError ||
3372 NS_ERROR_CSP_FORM_ACTION_VIOLATION == aError) {
3373 // CSP error
3374 cssClass.AssignLiteral("neterror");
3375 error = "cspBlocked";
3376 } else if (NS_ERROR_XFO_VIOLATION == aError) {
3377 // XFO error
3378 cssClass.AssignLiteral("neterror");
3379 error = "xfoBlocked";
3380 } else if (NS_ERROR_GET_MODULE(aError) == NS_ERROR_MODULE_SECURITY21) {
3381 nsCOMPtr<nsINSSErrorsService> nsserr =
3382 do_GetService(NS_NSS_ERRORS_SERVICE_CONTRACTID"@mozilla.org/nss_errors_service;1");
3383
3384 uint32_t errorClass;
3385 if (!nsserr || NS_FAILED(nsserr->GetErrorClass(aError, &errorClass))((bool)(__builtin_expect(!!(NS_FAILED_impl(nsserr->GetErrorClass
(aError, &errorClass))), 0)))
) {
3386 errorClass = nsINSSErrorsService::ERROR_CLASS_SSL_PROTOCOL;
3387 }
3388
3389 nsCOMPtr<nsITransportSecurityInfo> tsi;
3390 if (aFailedChannel) {
3391 aFailedChannel->GetSecurityInfo(getter_AddRefs(tsi));
3392 }
3393 if (tsi) {
3394 uint32_t securityState;
3395 tsi->GetSecurityState(&securityState);
3396 if (securityState & nsIWebProgressListener::STATE_USES_SSL_3) {
3397 error = "sslv3Used";
3398 addHostPort = true;
3399 } else if (securityState &
3400 nsIWebProgressListener::STATE_USES_WEAK_CRYPTO) {
3401 error = "weakCryptoUsed";
Value stored to 'error' is never read
3402 addHostPort = true;
3403 }
3404 } else {
3405 // No channel, let's obtain the generic error message
3406 if (nsserr) {
3407 nsserr->GetErrorMessage(aError, messageStr);
3408 }
3409 }
3410 // We don't have a message string here anymore but DisplayLoadError
3411 // requires a non-empty messageStr.
3412 messageStr.Truncate();
3413 messageStr.AssignLiteral(u" ");
3414 if (errorClass == nsINSSErrorsService::ERROR_CLASS_BAD_CERT) {
3415 error = "nssBadCert";
3416
3417 // If this is an HTTP Strict Transport Security host or a pinned host
3418 // and the certificate is bad, don't allow overrides (RFC 6797 section
3419 // 12.1).
3420 bool isStsHost = false;
3421 bool isPinnedHost = false;
3422 OriginAttributes attrsForHSTS;
3423 if (aFailedChannel) {
3424 StoragePrincipalHelper::GetOriginAttributesForHSTS(aFailedChannel,
3425 attrsForHSTS);
3426 } else {
3427 attrsForHSTS = GetOriginAttributes();
3428 }
3429
3430 if (XRE_IsParentProcess()) {
3431 nsCOMPtr<nsISiteSecurityService> sss =
3432 do_GetService(NS_SSSERVICE_CONTRACTID"@mozilla.org/ssservice;1", &rv);
3433 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/docshell/base/nsDocShell.cpp"
, 3433); return rv; } } while (false)
;
3434 rv = sss->IsSecureURI(aURI, attrsForHSTS, &isStsHost);
3435 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/docshell/base/nsDocShell.cpp"
, 3435); return rv; } } while (false)
;
3436 } else {
3437 mozilla::dom::ContentChild* cc =
3438 mozilla::dom::ContentChild::GetSingleton();
3439 cc->SendIsSecureURI(aURI, attrsForHSTS, &isStsHost);
3440 }
3441 nsCOMPtr<nsIPublicKeyPinningService> pkps =
3442 do_GetService(NS_PKPSERVICE_CONTRACTID"@mozilla.org/security/publickeypinningservice;1", &rv);
3443 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/docshell/base/nsDocShell.cpp"
, 3443); return rv; } } while (false)
;
3444 rv = pkps->HostHasPins(aURI, &isPinnedHost);
3445
3446 if (Preferences::GetBool("browser.xul.error_pages.expert_bad_cert",
3447 false)) {
3448 cssClass.AssignLiteral("expertBadCert");
3449 }
3450
3451 // HSTS/pinning takes precedence over the expert bad cert pref. We
3452 // never want to show the "Add Exception" button for these sites.
3453 // In the future we should differentiate between an HSTS host and a
3454 // pinned host and display a more informative message to the user.
3455 if (isStsHost || isPinnedHost) {
3456 isBadStsCertError = true;
3457 cssClass.AssignLiteral("badStsCert");
3458 }
3459
3460 errorPage.Assign("certerror");
3461 } else {
3462 error = "nssFailure2";
3463 }
3464 } else if (NS_ERROR_PHISHING_URI == aError ||
3465 NS_ERROR_MALWARE_URI == aError ||
3466 NS_ERROR_UNWANTED_URI == aError ||
3467 NS_ERROR_HARMFUL_URI == aError) {
3468 nsAutoCString host;
3469 aURI->GetHost(host);
3470 CopyUTF8toUTF16(host, *formatStrs.AppendElement());
3471
3472 // Malware and phishing detectors may want to use an alternate error
3473 // page, but if the pref's not set, we'll fall back on the standard page
3474 nsAutoCString alternateErrorPage;
3475 nsresult rv = Preferences::GetCString("urlclassifier.alternate_error_page",
3476 alternateErrorPage);
3477 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
3478 errorPage.Assign(alternateErrorPage);
3479 }
3480
3481 if (NS_ERROR_PHISHING_URI == aError) {
3482 error = "deceptiveBlocked";
3483 } else if (NS_ERROR_MALWARE_URI == aError) {
3484 error = "malwareBlocked";
3485 } else if (NS_ERROR_UNWANTED_URI == aError) {
3486 error = "unwantedBlocked";
3487 } else if (NS_ERROR_HARMFUL_URI == aError) {
3488 error = "harmfulBlocked";
3489 }
3490
3491 cssClass.AssignLiteral("blacklist");
3492 } else if (NS_ERROR_CONTENT_CRASHED == aError) {
3493 errorPage.AssignLiteral("tabcrashed");
3494 error = "tabcrashed";
3495
3496 RefPtr<EventTarget> handler = mChromeEventHandler;
3497 if (handler) {
3498 nsCOMPtr<Element> element = do_QueryInterface(handler);
3499 element->GetAttribute(u"crashedPageTitle"_ns, messageStr);
3500 }
3501
3502 // DisplayLoadError requires a non-empty messageStr to proceed and call
3503 // LoadErrorPage. If the page doesn't have a title, we will use a blank
3504 // space which will be trimmed and thus treated as empty by the front-end.
3505 if (messageStr.IsEmpty()) {
3506 messageStr.AssignLiteral(u" ");
3507 }
3508 } else if (NS_ERROR_FRAME_CRASHED == aError) {
3509 errorPage.AssignLiteral("framecrashed");
3510 error = "framecrashed";
3511 messageStr.AssignLiteral(u" ");
3512 } else if (NS_ERROR_BUILDID_MISMATCH == aError) {
3513 errorPage.AssignLiteral("restartrequired");
3514 error = "restartrequired";
3515
3516 // DisplayLoadError requires a non-empty messageStr to proceed and call
3517 // LoadErrorPage. If the page doesn't have a title, we will use a blank
3518 // space which will be trimmed and thus treated as empty by the front-end.
3519 if (messageStr.IsEmpty()) {
3520 messageStr.AssignLiteral(u" ");
3521 }
3522 } else {
3523 // Errors requiring simple formatting
3524 switch (aError) {
3525 case NS_ERROR_MALFORMED_URI:
3526 // URI is malformed
3527 error = "malformedURI";
3528 errorDescriptionID = "malformedURI2";
3529 break;
3530 case NS_ERROR_REDIRECT_LOOP:
3531 // Doc failed to load because the server generated too many redirects
3532 error = "redirectLoop";
3533 break;
3534 case NS_ERROR_UNKNOWN_SOCKET_TYPE:
3535 // Doc failed to load because PSM is not installed
3536 error = "unknownSocketType";
3537 break;
3538 case NS_ERROR_NET_RESET:
3539 // Doc failed to load because the server kept reseting the connection
3540 // before we could read any data from it
3541 error = "netReset";
3542 break;
3543 case NS_ERROR_DOCUMENT_NOT_CACHED:
3544 // Doc failed to load because the cache does not contain a copy of
3545 // the document.
3546 error = "notCached";
3547 break;
3548 case NS_ERROR_OFFLINE:
3549 // Doc failed to load because we are offline.
3550 error = "netOffline";
3551 break;
3552 case NS_ERROR_DOCUMENT_IS_PRINTMODE:
3553 // Doc navigation attempted while Printing or Print Preview
3554 error = "isprinting";
3555 break;
3556 case NS_ERROR_PORT_ACCESS_NOT_ALLOWED:
3557 // Port blocked for security reasons
3558 addHostPort = true;
3559 error = "deniedPortAccess";
3560 break;
3561 case NS_ERROR_UNKNOWN_PROXY_HOST:
3562 // Proxy hostname could not be resolved.
3563 error = "proxyResolveFailure";
3564 break;
3565 case NS_ERROR_PROXY_CONNECTION_REFUSED:
3566 case NS_ERROR_PROXY_FORBIDDEN:
3567 case NS_ERROR_PROXY_NOT_IMPLEMENTED:
3568 case NS_ERROR_PROXY_AUTHENTICATION_FAILED:
3569 case NS_ERROR_PROXY_TOO_MANY_REQUESTS:
3570 // Proxy connection was refused.
3571 error = "proxyConnectFailure";
3572 break;
3573 case NS_ERROR_INVALID_CONTENT_ENCODING:
3574 // Bad Content Encoding.
3575 error = "contentEncodingError";
3576 break;
3577 case NS_ERROR_UNSAFE_CONTENT_TYPE:
3578 // Channel refused to load from an unrecognized content type.
3579 error = "unsafeContentType";
3580 break;
3581 case NS_ERROR_CORRUPTED_CONTENT:
3582 // Broken Content Detected. e.g. Content-MD5 check failure.
3583 error = "corruptedContentErrorv2";
3584 break;
3585 case NS_ERROR_INTERCEPTION_FAILED:
3586 // ServiceWorker intercepted request, but something went wrong.
3587 error = "corruptedContentErrorv2";
3588 break;
3589 case NS_ERROR_NET_INADEQUATE_SECURITY:
3590 // Server negotiated bad TLS for HTTP/2.
3591 error = "inadequateSecurityError";
3592 addHostPort = true;
3593 break;
3594 case NS_ERROR_BLOCKED_BY_POLICY:
3595 case NS_ERROR_DOM_COOP_FAILED:
3596 case NS_ERROR_DOM_COEP_FAILED:
3597 // Page blocked by policy
3598 error = "blockedByPolicy";
3599 break;
3600 case NS_ERROR_NET_HTTP2_SENT_GOAWAY:
3601 case NS_ERROR_NET_HTTP3_PROTOCOL_ERROR:
3602 // HTTP/2 or HTTP/3 stack detected a protocol error
3603 error = "networkProtocolError";
3604 break;
3605
3606 default:
3607 break;
3608 }
3609 }
3610
3611 nsresult delegateErrorCode = aError;
3612 // If the HTTPS-Only Mode upgraded this request and the upgrade might have
3613 // caused this error, we replace the error-page with about:httpsonlyerror
3614 if (nsHTTPSOnlyUtils::CouldBeHttpsOnlyError(aFailedChannel, aError)) {
3615 errorPage.AssignLiteral("httpsonlyerror");
3616 delegateErrorCode = NS_ERROR_HTTPS_ONLY;
3617 } else if (isBadStsCertError) {
3618 delegateErrorCode = NS_ERROR_BAD_HSTS_CERT;
3619 }
3620
3621 if (nsCOMPtr<nsILoadURIDelegate> loadURIDelegate = GetLoadURIDelegate()) {
3622 nsCOMPtr<nsIURI> errorPageURI;
3623 rv = loadURIDelegate->HandleLoadError(
3624 aURI, delegateErrorCode, NS_ERROR_GET_MODULE(delegateErrorCode),
3625 getter_AddRefs(errorPageURI));
3626 // If the docshell is going away there's no point in showing an error page.
3627 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) || mIsBeingDestroyed) {
3628 *aDisplayedErrorPage = false;
3629 return NS_OK;
3630 }
3631
3632 if (errorPageURI) {
3633 *aDisplayedErrorPage =
3634 NS_SUCCEEDED(LoadErrorPage(errorPageURI, aURI, aFailedChannel))((bool)(__builtin_expect(!!(!NS_FAILED_impl(LoadErrorPage(errorPageURI
, aURI, aFailedChannel))), 1)))
;
3635 return NS_OK;
3636 }
3637 }
3638
3639 // Test if the error should be displayed
3640 if (!error) {
3641 return NS_OK;
3642 }
3643
3644 if (!errorDescriptionID) {
3645 errorDescriptionID = error;
3646 }
3647
3648 Telemetry::AccumulateCategoricalKeyed(
3649 IsSubframe() ? "frame"_ns : "top"_ns,
3650 mozilla::dom::LoadErrorToTelemetryLabel(aError));
3651
3652 // Test if the error needs to be formatted
3653 if (!messageStr.IsEmpty()) {
3654 // already obtained message
3655 } else {
3656 if (addHostPort) {
3657 // Build up the host:port string.
3658 nsAutoCString hostport;
3659 if (aURI) {
3660 aURI->GetHostPort(hostport);
3661 } else {
3662 hostport.Assign('?');
3663 }
3664 CopyUTF8toUTF16(hostport, *formatStrs.AppendElement());
3665 }
3666
3667 nsAutoCString spec;
3668 rv = NS_ERROR_NOT_AVAILABLE;
3669 auto& nextFormatStr = *formatStrs.AppendElement();
3670 if (aURI) {
3671 // displaying "file://" is aesthetically unpleasing and could even be
3672 // confusing to the user
3673 if (SchemeIsFile(aURI)) {
3674 aURI->GetPathQueryRef(spec);
3675 } else {
3676 aURI->GetSpec(spec);
3677 }
3678
3679 nsCOMPtr<nsITextToSubURI> textToSubURI(
3680 do_GetService(NS_ITEXTTOSUBURI_CONTRACTID"@mozilla.org/intl/texttosuburi;1", &rv));
3681 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
3682 rv = textToSubURI->UnEscapeURIForUI(spec, nextFormatStr);
3683 }
3684 } else {
3685 spec.Assign('?');
3686 }
3687 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3688 CopyUTF8toUTF16(spec, nextFormatStr);
3689 }
3690 rv = NS_OK;
3691
3692 nsAutoString str;
3693 rv =
3694 stringBundle->FormatStringFromName(errorDescriptionID, formatStrs, str);
3695 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/docshell/base/nsDocShell.cpp"
, 3695); return rv; } } while (false)
;
3696 messageStr.Assign(str);
3697 }
3698
3699 // Display the error as a page or an alert prompt
3700 NS_ENSURE_FALSE(messageStr.IsEmpty(), NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(!(messageStr.IsEmpty()))), 0)
)) { NS_DebugBreak(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "!(messageStr.IsEmpty())"
") failed", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 3700); return NS_ERROR_FAILURE; } } while (false)
;
3701
3702 if ((NS_ERROR_NET_INTERRUPT == aError || NS_ERROR_NET_RESET == aError) &&
3703 SchemeIsHTTPS(aURI)) {
3704 // Maybe TLS intolerant. Treat this as an SSL error.
3705 error = "nssFailure2";
3706 }
3707
3708 if (mBrowsingContext->GetUseErrorPages()) {
3709 // Display an error page
3710 nsresult loadedPage =
3711 LoadErrorPage(aURI, aURL, errorPage.get(), error, messageStr.get(),
3712 cssClass.get(), aFailedChannel);
3713 *aDisplayedErrorPage = NS_SUCCEEDED(loadedPage)((bool)(__builtin_expect(!!(!NS_FAILED_impl(loadedPage)), 1))
)
;
3714 } else {
3715 // The prompter reqires that our private window has a document (or it
3716 // asserts). Satisfy that assertion now since GetDoc will force
3717 // creation of one if it hasn't already been created.
3718 if (mScriptGlobal) {
3719 Unused << mScriptGlobal->GetDoc();
3720 }
3721
3722 // Display a message box
3723 prompter->Alert(nullptr, messageStr.get());
3724 }
3725
3726 return NS_OK;
3727}
3728
3729#define PREF_SAFEBROWSING_ALLOWOVERRIDE"browser.safebrowsing.allowOverride" "browser.safebrowsing.allowOverride"
3730
3731nsresult nsDocShell::LoadErrorPage(nsIURI* aURI, const char16_t* aURL,
3732 const char* aErrorPage,
3733 const char* aErrorType,
3734 const char16_t* aDescription,
3735 const char* aCSSClass,
3736 nsIChannel* aFailedChannel) {
3737 if (mIsBeingDestroyed) {
3738 return NS_ERROR_NOT_AVAILABLE;
3739 }
3740
3741#if defined(DEBUG1)
3742 if (MOZ_LOG_TEST(gDocShellLog, LogLevel::Debug)(__builtin_expect(!!(mozilla::detail::log_test(gDocShellLog, LogLevel
::Debug)), 0))
) {
3743 nsAutoCString chanName;
3744 if (aFailedChannel) {
3745 aFailedChannel->GetName(chanName);
3746 } else {
3747 chanName.AssignLiteral("<no channel>");
3748 }
3749
3750 MOZ_LOG(gDocShellLog, LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = gDocShellLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "nsDocShell[%p]::LoadErrorPage(\"%s\", \"%s\", {...}, [%s])\n"
, this, aURI ? aURI->GetSpecOrDefault().get() : "", NS_ConvertUTF16toUTF8
(aURL).get(), chanName.get()); } } while (0)
3751 ("nsDocShell[%p]::LoadErrorPage(\"%s\", \"%s\", {...}, [%s])\n",do { const ::mozilla::LogModule* moz_real_module = gDocShellLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "nsDocShell[%p]::LoadErrorPage(\"%s\", \"%s\", {...}, [%s])\n"
, this, aURI ? aURI->GetSpecOrDefault().get() : "", NS_ConvertUTF16toUTF8
(aURL).get(), chanName.get()); } } while (0)
3752 this, aURI ? aURI->GetSpecOrDefault().get() : "",do { const ::mozilla::LogModule* moz_real_module = gDocShellLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "nsDocShell[%p]::LoadErrorPage(\"%s\", \"%s\", {...}, [%s])\n"
, this, aURI ? aURI->GetSpecOrDefault().get() : "", NS_ConvertUTF16toUTF8
(aURL).get(), chanName.get()); } } while (0)
3753 NS_ConvertUTF16toUTF8(aURL).get(), chanName.get()))do { const ::mozilla::LogModule* moz_real_module = gDocShellLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "nsDocShell[%p]::LoadErrorPage(\"%s\", \"%s\", {...}, [%s])\n"
, this, aURI ? aURI->GetSpecOrDefault().get() : "", NS_ConvertUTF16toUTF8
(aURL).get(), chanName.get()); } } while (0)
;
3754 }
3755#endif
3756
3757 nsAutoCString url;
3758 if (aURI) {
3759 nsresult rv = aURI->GetSpec(url);
3760 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/docshell/base/nsDocShell.cpp"
, 3760); return rv; } } while (false)
;
3761 } else if (aURL) {
3762 CopyUTF16toUTF8(MakeStringSpan(aURL), url);
3763 } else {
3764 return NS_ERROR_INVALID_POINTER;
3765 }
3766
3767 // Create a URL to pass all the error information through to the page.
3768
3769#undef SAFE_ESCAPE
3770#define SAFE_ESCAPE(output, input, params)if (NS_warn_if_impl(!NS_Escape(input, output, params), "!NS_Escape(input, output, params)"
, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 3770)) { return NS_ERROR_OUT_OF_MEMORY; }
\
3771 if (NS_WARN_IF(!NS_Escape(input, output, params))NS_warn_if_impl(!NS_Escape(input, output, params), "!NS_Escape(input, output, params)"
, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 3771)
) { \
3772 return NS_ERROR_OUT_OF_MEMORY; \
3773 }
3774
3775 nsCString escapedUrl, escapedError, escapedDescription, escapedCSSClass;
3776 SAFE_ESCAPE(escapedUrl, url, url_Path)if (NS_warn_if_impl(!NS_Escape(url, escapedUrl, url_Path), "!NS_Escape(url, escapedUrl, url_Path)"
, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 3776)) { return NS_ERROR_OUT_OF_MEMORY; }
;
3777 SAFE_ESCAPE(escapedError, nsDependentCString(aErrorType), url_Path)if (NS_warn_if_impl(!NS_Escape(nsDependentCString(aErrorType)
, escapedError, url_Path), "!NS_Escape(nsDependentCString(aErrorType), escapedError, url_Path)"
, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 3777)) { return NS_ERROR_OUT_OF_MEMORY; }
;
3778 SAFE_ESCAPE(escapedDescription, NS_ConvertUTF16toUTF8(aDescription),if (NS_warn_if_impl(!NS_Escape(NS_ConvertUTF16toUTF8(aDescription
), escapedDescription, url_Path), "!NS_Escape(NS_ConvertUTF16toUTF8(aDescription), escapedDescription, url_Path)"
, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 3779)) { return NS_ERROR_OUT_OF_MEMORY; }
3779 url_Path)if (NS_warn_if_impl(!NS_Escape(NS_ConvertUTF16toUTF8(aDescription
), escapedDescription, url_Path), "!NS_Escape(NS_ConvertUTF16toUTF8(aDescription), escapedDescription, url_Path)"
, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 3779)) { return NS_ERROR_OUT_OF_MEMORY; }
;
3780 if (aCSSClass) {
3781 nsCString cssClass(aCSSClass);
3782 SAFE_ESCAPE(escapedCSSClass, cssClass, url_Path)if (NS_warn_if_impl(!NS_Escape(cssClass, escapedCSSClass, url_Path
), "!NS_Escape(cssClass, escapedCSSClass, url_Path)", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 3782)) { return NS_ERROR_OUT_OF_MEMORY; }
;
3783 }
3784 nsCString errorPageUrl("about:");
3785 errorPageUrl.AppendASCII(aErrorPage);
3786 errorPageUrl.AppendLiteral("?e=");
3787
3788 errorPageUrl.AppendASCII(escapedError.get());
3789 errorPageUrl.AppendLiteral("&u=");
3790 errorPageUrl.AppendASCII(escapedUrl.get());
3791 if ((strcmp(aErrorPage, "blocked") == 0) &&
3792 Preferences::GetBool(PREF_SAFEBROWSING_ALLOWOVERRIDE"browser.safebrowsing.allowOverride", true)) {
3793 errorPageUrl.AppendLiteral("&o=1");
3794 }
3795 if (!escapedCSSClass.IsEmpty()) {
3796 errorPageUrl.AppendLiteral("&s=");
3797 errorPageUrl.AppendASCII(escapedCSSClass.get());
3798 }
3799 errorPageUrl.AppendLiteral("&c=UTF-8");
3800
3801 nsCOMPtr<nsICaptivePortalService> cps = do_GetService(NS_CAPTIVEPORTAL_CID{ 0xbdbe0555, 0xfc3d, 0x4f7b, { 0x92, 0x05, 0xc3, 0x09, 0xce,
0xb2, 0xd6, 0x41 } }
);
3802 int32_t cpsState;
3803 if (cps && NS_SUCCEEDED(cps->GetState(&cpsState))((bool)(__builtin_expect(!!(!NS_FAILED_impl(cps->GetState(
&cpsState))), 1)))
&&
3804 cpsState == nsICaptivePortalService::LOCKED_PORTAL) {
3805 errorPageUrl.AppendLiteral("&captive=true");
3806 }
3807
3808 errorPageUrl.AppendLiteral("&d=");
3809 errorPageUrl.AppendASCII(escapedDescription.get());
3810
3811 nsCOMPtr<nsIURI> errorPageURI;
3812 nsresult rv = NS_NewURI(getter_AddRefs(errorPageURI), errorPageUrl);
3813 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/docshell/base/nsDocShell.cpp"
, 3813); return rv; } } while (false)
;
3814
3815 return LoadErrorPage(errorPageURI, aURI, aFailedChannel);
3816}
3817
3818nsresult nsDocShell::LoadErrorPage(nsIURI* aErrorURI, nsIURI* aFailedURI,
3819 nsIChannel* aFailedChannel) {
3820 mFailedChannel = aFailedChannel;
3821 mFailedURI = aFailedURI;
3822 mFailedLoadType = mLoadType;
3823
3824 if (mLSHE) {
3825 // Abandon mLSHE's BFCache entry and create a new one. This way, if
3826 // we go back or forward to another SHEntry with the same doc
3827 // identifier, the error page won't persist.
3828 mLSHE->AbandonBFCacheEntry();
3829 }
3830
3831 RefPtr<nsDocShellLoadState> loadState = new nsDocShellLoadState(aErrorURI);
3832 loadState->SetTriggeringPrincipal(nsContentUtils::GetSystemPrincipal());
3833 if (mBrowsingContext) {
3834 loadState->SetTriggeringSandboxFlags(mBrowsingContext->GetSandboxFlags());
3835 loadState->SetTriggeringWindowId(
3836 mBrowsingContext->GetCurrentInnerWindowId());
3837 nsPIDOMWindowInner* innerWin = mScriptGlobal->GetCurrentInnerWindow();
3838 if (innerWin) {
3839 loadState->SetTriggeringStorageAccess(innerWin->UsingStorageAccess());
3840 }
3841 }
3842 loadState->SetLoadType(LOAD_ERROR_PAGE);
3843 loadState->SetFirstParty(true);
3844 loadState->SetSourceBrowsingContext(mBrowsingContext);
3845 if (mozilla::SessionHistoryInParent() && mLoadingEntry) {
3846 // We keep the loading entry for the load that failed here. If the user
3847 // reloads we want to try to reload the original load, not the error page.
3848 loadState->SetLoadingSessionHistoryInfo(
3849 MakeUnique<LoadingSessionHistoryInfo>(*mLoadingEntry));
3850 }
3851 return InternalLoad(loadState);
3852}
3853
3854NS_IMETHODIMPnsresult
3855nsDocShell::Reload(uint32_t aReloadFlags) {
3856 if (!IsNavigationAllowed()) {
3857 return NS_OK; // JS may not handle returning of an error code
3858 }
3859
3860 NS_ASSERTION(((aReloadFlags & INTERNAL_LOAD_FLAGS_LOADURI_SETUP_FLAGS) == 0),do { if (!(((aReloadFlags & INTERNAL_LOAD_FLAGS_LOADURI_SETUP_FLAGS
) == 0))) { NS_DebugBreak(NS_DEBUG_ASSERTION, "Reload command not updated to use load flags!"
, "((aReloadFlags & INTERNAL_LOAD_FLAGS_LOADURI_SETUP_FLAGS) == 0)"
, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 3861); MOZ_PretendNoReturn(); } } while (0)
3861 "Reload command not updated to use load flags!")do { if (!(((aReloadFlags & INTERNAL_LOAD_FLAGS_LOADURI_SETUP_FLAGS
) == 0))) { NS_DebugBreak(NS_DEBUG_ASSERTION, "Reload command not updated to use load flags!"
, "((aReloadFlags & INTERNAL_LOAD_FLAGS_LOADURI_SETUP_FLAGS) == 0)"
, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 3861); MOZ_PretendNoReturn(); } } while (0)
;
3862 NS_ASSERTION((aReloadFlags & EXTRA_LOAD_FLAGS) == 0,do { if (!((aReloadFlags & (nsIWebNavigation::LOAD_FLAGS_FROM_EXTERNAL
| nsIWebNavigation::LOAD_FLAGS_FIRST_LOAD | nsIWebNavigation
::LOAD_FLAGS_ALLOW_POPUPS | 0xffff0000)) == 0)) { NS_DebugBreak
(NS_DEBUG_ASSERTION, "Don't pass these flags to Reload", "(aReloadFlags & EXTRA_LOAD_FLAGS) == 0"
, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 3863); MOZ_PretendNoReturn(); } } while (0)
3863 "Don't pass these flags to Reload")do { if (!((aReloadFlags & (nsIWebNavigation::LOAD_FLAGS_FROM_EXTERNAL
| nsIWebNavigation::LOAD_FLAGS_FIRST_LOAD | nsIWebNavigation
::LOAD_FLAGS_ALLOW_POPUPS | 0xffff0000)) == 0)) { NS_DebugBreak
(NS_DEBUG_ASSERTION, "Don't pass these flags to Reload", "(aReloadFlags & EXTRA_LOAD_FLAGS) == 0"
, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 3863); MOZ_PretendNoReturn(); } } while (0)
;
3864
3865 uint32_t loadType = MAKE_LOAD_TYPE(LOAD_RELOAD_NORMAL, aReloadFlags)((LOAD_RELOAD_NORMAL) | ((aReloadFlags) << 16));
3866 NS_ENSURE_TRUE(IsValidLoadType(loadType), NS_ERROR_INVALID_ARG)do { if ((__builtin_expect(!!(!(IsValidLoadType(loadType))), 0
))) { NS_DebugBreak(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "IsValidLoadType(loadType)"
") failed", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 3866); return NS_ERROR_INVALID_ARG; } } while (false)
;
3867
3868 // Send notifications to the HistoryListener if any, about the impending
3869 // reload
3870 RefPtr<ChildSHistory> rootSH = GetRootSessionHistory();
3871 if (mozilla::SessionHistoryInParent()) {
3872 MOZ_LOG(gSHLog, LogLevel::Debug, ("nsDocShell %p Reload", this))do { const ::mozilla::LogModule* moz_real_module = gSHLog; if
((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "nsDocShell %p Reload", this); } } while (
0)
;
3873 bool forceReload = IsForceReloadType(loadType);
3874 if (!XRE_IsParentProcess()) {
3875 ++mPendingReloadCount;
3876 RefPtr<nsDocShell> docShell(this);
3877 nsCOMPtr<nsIDocumentViewer> viewer(mDocumentViewer);
3878 NS_ENSURE_STATE(viewer)do { if ((__builtin_expect(!!(!(viewer)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "viewer" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 3878); return NS_ERROR_UNEXPECTED; } } while (false)
;
3879
3880 bool okToUnload = true;
3881 MOZ_TRY(viewer->PermitUnload(&okToUnload))do { auto mozTryTempResult_ = ::mozilla::ToResult(viewer->
PermitUnload(&okToUnload)); if ((__builtin_expect(!!(mozTryTempResult_
.isErr()), 0))) { return mozTryTempResult_.propagateErr(); } }
while (0)
;
3882 if (!okToUnload) {
3883 return NS_OK;
3884 }
3885
3886 RefPtr<Document> doc(GetDocument());
3887 RefPtr<BrowsingContext> browsingContext(mBrowsingContext);
3888 nsCOMPtr<nsIURI> currentURI(mCurrentURI);
3889 nsCOMPtr<nsIReferrerInfo> referrerInfo(mReferrerInfo);
3890 RefPtr<StopDetector> stopDetector = new StopDetector();
3891 nsCOMPtr<nsILoadGroup> loadGroup;
3892 GetLoadGroup(getter_AddRefs(loadGroup));
3893 if (loadGroup) {
3894 // loadGroup may be null in theory. In that case stopDetector just
3895 // doesn't do anything.
3896 loadGroup->AddRequest(stopDetector, nullptr);
3897 }
3898
3899 ContentChild::GetSingleton()->SendNotifyOnHistoryReload(
3900 mBrowsingContext, forceReload,
3901 [docShell, doc, loadType, browsingContext, currentURI, referrerInfo,
3902 loadGroup, stopDetector](
3903 std::tuple<bool, Maybe<NotNull<RefPtr<nsDocShellLoadState>>>,
3904 Maybe<bool>>&& aResult) {
3905 auto scopeExit = MakeScopeExit([loadGroup, stopDetector]() {
3906 if (loadGroup) {
3907 loadGroup->RemoveRequest(stopDetector, nullptr, NS_OK);
3908 }
3909 });
3910
3911 // Decrease mPendingReloadCount before any other early returns!
3912 if (--(docShell->mPendingReloadCount) > 0) {
3913 return;
3914 }
3915
3916 if (stopDetector->Canceled()) {
3917 return;
3918 }
3919 bool canReload;
3920 Maybe<NotNull<RefPtr<nsDocShellLoadState>>> loadState;
3921 Maybe<bool> reloadingActiveEntry;
3922
3923 std::tie(canReload, loadState, reloadingActiveEntry) = aResult;
3924
3925 if (!canReload) {
3926 return;
3927 }
3928
3929 if (loadState.isSome()) {
3930 MOZ_LOG(do { const ::mozilla::LogModule* moz_real_module = gSHLog; if
((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "nsDocShell %p Reload - LoadHistoryEntry",
docShell.get()); } } while (0)
3931 gSHLog, LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = gSHLog; if
((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "nsDocShell %p Reload - LoadHistoryEntry",
docShell.get()); } } while (0)
3932 ("nsDocShell %p Reload - LoadHistoryEntry", docShell.get()))do { const ::mozilla::LogModule* moz_real_module = gSHLog; if
((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "nsDocShell %p Reload - LoadHistoryEntry",
docShell.get()); } } while (0)
;
3933 loadState.ref()->SetNotifiedBeforeUnloadListeners(true);
3934 docShell->LoadHistoryEntry(loadState.ref(), loadType,
3935 reloadingActiveEntry.ref());
3936 } else {
3937 MOZ_LOG(gSHLog, LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = gSHLog; if
((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "nsDocShell %p ReloadDocument", docShell.get
()); } } while (0)
3938 ("nsDocShell %p ReloadDocument", docShell.get()))do { const ::mozilla::LogModule* moz_real_module = gSHLog; if
((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "nsDocShell %p ReloadDocument", docShell.get
()); } } while (0)
;
3939 ReloadDocument(docShell, doc, loadType, browsingContext,
3940 currentURI, referrerInfo,
3941 /* aNotifiedBeforeUnloadListeners */ true);
3942 }
3943 },
3944 [](mozilla::ipc::ResponseRejectReason) {});
3945 } else {
3946 // Parent process
3947 bool canReload = false;
3948 Maybe<NotNull<RefPtr<nsDocShellLoadState>>> loadState;
3949 Maybe<bool> reloadingActiveEntry;
3950 if (!mBrowsingContext->IsDiscarded()) {
3951 mBrowsingContext->Canonical()->NotifyOnHistoryReload(
3952 forceReload, canReload, loadState, reloadingActiveEntry);
3953 }
3954 if (canReload) {
3955 if (loadState.isSome()) {
3956 MOZ_LOG(gSHLog, LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = gSHLog; if
((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "nsDocShell %p Reload - LoadHistoryEntry",
this); } } while (0)
3957 ("nsDocShell %p Reload - LoadHistoryEntry", this))do { const ::mozilla::LogModule* moz_real_module = gSHLog; if
((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "nsDocShell %p Reload - LoadHistoryEntry",
this); } } while (0)
;
3958 LoadHistoryEntry(loadState.ref(), loadType,
3959 reloadingActiveEntry.ref());
3960 } else {
3961 MOZ_LOG(gSHLog, LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = gSHLog; if
((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "nsDocShell %p ReloadDocument", this); } }
while (0)
3962 ("nsDocShell %p ReloadDocument", this))do { const ::mozilla::LogModule* moz_real_module = gSHLog; if
((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "nsDocShell %p ReloadDocument", this); } }
while (0)
;
3963 RefPtr<Document> doc = GetDocument();
3964 RefPtr<BrowsingContext> bc = mBrowsingContext;
3965 nsCOMPtr<nsIURI> currentURI = mCurrentURI;
3966 nsCOMPtr<nsIReferrerInfo> referrerInfo = mReferrerInfo;
3967 ReloadDocument(this, doc, loadType, bc, currentURI, referrerInfo);
3968 }
3969 }
3970 }
3971 return NS_OK;
3972 }
3973
3974 bool canReload = true;
3975 if (rootSH) {
3976 rootSH->LegacySHistory()->NotifyOnHistoryReload(&canReload);
3977 }
3978
3979 if (!canReload) {
3980 return NS_OK;
3981 }
3982
3983 /* If you change this part of code, make sure bug 45297 does not re-occur */
3984 if (mOSHE) {
3985 nsCOMPtr<nsISHEntry> oshe = mOSHE;
3986 return LoadHistoryEntry(
3987 oshe, loadType,
3988 aReloadFlags & nsIWebNavigation::LOAD_FLAGS_USER_ACTIVATION);
3989 }
3990
3991 if (mLSHE) { // In case a reload happened before the current load is done
3992 nsCOMPtr<nsISHEntry> lshe = mLSHE;
3993 return LoadHistoryEntry(
3994 lshe, loadType,
3995 aReloadFlags & nsIWebNavigation::LOAD_FLAGS_USER_ACTIVATION);
3996 }
3997
3998 RefPtr<Document> doc = GetDocument();
3999 RefPtr<BrowsingContext> bc = mBrowsingContext;
4000 nsCOMPtr<nsIURI> currentURI = mCurrentURI;
4001 nsCOMPtr<nsIReferrerInfo> referrerInfo = mReferrerInfo;
4002 return ReloadDocument(this, doc, loadType, bc, currentURI, referrerInfo);
4003}
4004
4005/* static */
4006nsresult nsDocShell::ReloadDocument(nsDocShell* aDocShell, Document* aDocument,
4007 uint32_t aLoadType,
4008 BrowsingContext* aBrowsingContext,
4009 nsIURI* aCurrentURI,
4010 nsIReferrerInfo* aReferrerInfo,
4011 bool aNotifiedBeforeUnloadListeners) {
4012 if (!aDocument) {
4013 return NS_OK;
4014 }
4015
4016 // Do not inherit owner from document
4017 uint32_t flags = INTERNAL_LOAD_FLAGS_NONE;
4018 nsAutoString srcdoc;
4019 nsIURI* baseURI = nullptr;
4020 nsCOMPtr<nsIURI> originalURI;
4021 nsCOMPtr<nsIURI> resultPrincipalURI;
4022 bool loadReplace = false;
4023
4024 nsIPrincipal* triggeringPrincipal = aDocument->NodePrincipal();
4025 nsCOMPtr<nsIContentSecurityPolicy> csp = aDocument->GetCsp();
4026 uint32_t triggeringSandboxFlags = aDocument->GetSandboxFlags();
4027 uint64_t triggeringWindowId = aDocument->InnerWindowID();
4028 bool triggeringStorageAccess = aDocument->UsingStorageAccess();
4029
4030 nsAutoString contentTypeHint;
4031 aDocument->GetContentType(contentTypeHint);
4032
4033 if (aDocument->IsSrcdocDocument()) {
4034 aDocument->GetSrcdocData(srcdoc);
4035 flags |= INTERNAL_LOAD_FLAGS_IS_SRCDOC;
4036 baseURI = aDocument->GetBaseURI();
4037 } else {
4038 srcdoc = VoidString();
4039 }
4040 nsCOMPtr<nsIChannel> chan = aDocument->GetChannel();
4041 if (chan) {
4042 uint32_t loadFlags;
4043 chan->GetLoadFlags(&loadFlags);
4044 loadReplace = loadFlags & nsIChannel::LOAD_REPLACE;
4045 nsCOMPtr<nsIHttpChannel> httpChan(do_QueryInterface(chan));
4046 if (httpChan) {
4047 httpChan->GetOriginalURI(getter_AddRefs(originalURI));
4048 }
4049
4050 nsCOMPtr<nsILoadInfo> loadInfo = chan->LoadInfo();
4051 loadInfo->GetResultPrincipalURI(getter_AddRefs(resultPrincipalURI));
4052 }
4053
4054 if (!triggeringPrincipal) {
4055 MOZ_ASSERT(false, "Reload needs a valid triggeringPrincipal")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "Reload needs a valid triggeringPrincipal"
")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 4055); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"Reload needs a valid triggeringPrincipal" ")"); do { *((volatile
int*)__null) = 4055; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
4056 return NS_ERROR_FAILURE;
4057 }
4058
4059 // Stack variables to ensure changes to the member variables don't affect to
4060 // the call.
4061 nsCOMPtr<nsIURI> currentURI = aCurrentURI;
4062
4063 // Reload always rewrites result principal URI.
4064 Maybe<nsCOMPtr<nsIURI>> emplacedResultPrincipalURI;
4065 emplacedResultPrincipalURI.emplace(std::move(resultPrincipalURI));
4066
4067 RefPtr<WindowContext> context = aBrowsingContext->GetCurrentWindowContext();
4068 RefPtr<nsDocShellLoadState> loadState = new nsDocShellLoadState(currentURI);
4069 loadState->SetReferrerInfo(aReferrerInfo);
4070 loadState->SetOriginalURI(originalURI);
4071 loadState->SetMaybeResultPrincipalURI(emplacedResultPrincipalURI);
4072 loadState->SetLoadReplace(loadReplace);
4073 loadState->SetTriggeringPrincipal(triggeringPrincipal);
4074 loadState->SetTriggeringSandboxFlags(triggeringSandboxFlags);
4075 loadState->SetTriggeringWindowId(triggeringWindowId);
4076 loadState->SetTriggeringStorageAccess(triggeringStorageAccess);
4077 loadState->SetPrincipalToInherit(triggeringPrincipal);
4078 loadState->SetCsp(csp);
4079 loadState->SetInternalLoadFlags(flags);
4080 loadState->SetTypeHint(NS_ConvertUTF16toUTF8(contentTypeHint));
4081 loadState->SetLoadType(aLoadType);
4082 loadState->SetFirstParty(true);
4083 loadState->SetSrcdocData(srcdoc);
4084 loadState->SetSourceBrowsingContext(aBrowsingContext);
4085 loadState->SetBaseURI(baseURI);
4086 loadState->SetHasValidUserGestureActivation(
4087 context && context->HasValidTransientUserGestureActivation());
4088
4089 loadState->SetTextDirectiveUserActivation(
4090 aDocument->ConsumeTextDirectiveUserActivation() ||
4091 loadState->HasValidUserGestureActivation());
4092
4093 loadState->SetNotifiedBeforeUnloadListeners(aNotifiedBeforeUnloadListeners);
4094 return aDocShell->InternalLoad(loadState);
4095}
4096
4097NS_IMETHODIMPnsresult
4098nsDocShell::Stop(uint32_t aStopFlags) {
4099 // Revoke any pending event related to content viewer restoration
4100 mRestorePresentationEvent.Revoke();
4101
4102 if (mLoadType == LOAD_ERROR_PAGE) {
4103 if (mLSHE) {
4104 // Since error page loads never unset mLSHE, do so now
4105 SetHistoryEntryAndUpdateBC(Some(nullptr), Some<nsISHEntry*>(mLSHE));
4106 }
4107 mActiveEntryIsLoadingFromSessionHistory = false;
4108
4109 mFailedChannel = nullptr;
4110 mFailedURI = nullptr;
4111 }
4112
4113 if (nsIWebNavigation::STOP_CONTENT & aStopFlags) {
4114 // Stop the document loading and animations
4115 if (mDocumentViewer) {
4116 nsCOMPtr<nsIDocumentViewer> viewer = mDocumentViewer;
4117 viewer->Stop();
4118 }
4119 } else if (nsIWebNavigation::STOP_NETWORK & aStopFlags) {
4120 // Stop the document loading only
4121 if (mDocumentViewer) {
4122 RefPtr<Document> doc = mDocumentViewer->GetDocument();
4123 if (doc) {
4124 doc->StopDocumentLoad();
4125 }
4126 }
4127 }
4128
4129 if (nsIWebNavigation::STOP_NETWORK & aStopFlags) {
4130 // Suspend any timers that were set for this loader. We'll clear
4131 // them out for good in CreateDocumentViewer.
4132 if (mRefreshURIList) {
4133 SuspendRefreshURIs();
4134 mSavedRefreshURIList.swap(mRefreshURIList);
4135 mRefreshURIList = nullptr;
4136 }
4137
4138 // XXXbz We could also pass |this| to nsIURILoader::Stop. That will
4139 // just call Stop() on us as an nsIDocumentLoader... We need fewer
4140 // redundant apis!
4141 Stop();
4142
4143 // Clear out mChannelToDisconnectOnPageHide. This page won't go in the
4144 // BFCache now, and the Stop above will have removed the DocumentChannel
4145 // from the loadgroup.
4146 mChannelToDisconnectOnPageHide = 0;
4147 }
4148
4149 for (auto* child : mChildList.ForwardRange()) {
4150 nsCOMPtr<nsIWebNavigation> shellAsNav(do_QueryObject(child));
4151 if (shellAsNav) {
4152 shellAsNav->Stop(aStopFlags);
4153 }
4154 }
4155
4156 return NS_OK;
4157}
4158
4159NS_IMETHODIMPnsresult
4160nsDocShell::GetDocument(Document** aDocument) {
4161 NS_ENSURE_ARG_POINTER(aDocument)do { if ((__builtin_expect(!!(!(aDocument)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aDocument" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 4161); return NS_ERROR_INVALID_POINTER; } } while (false)
;
4162 NS_ENSURE_SUCCESS(EnsureDocumentViewer(), NS_ERROR_FAILURE)do { nsresult __rv = EnsureDocumentViewer(); 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", "EnsureDocumentViewer()", "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/docshell/base/nsDocShell.cpp"
, 4162); return NS_ERROR_FAILURE; } } while (false)
;
4163
4164 RefPtr<Document> doc = mDocumentViewer->GetDocument();
4165 if (!doc) {
4166 return NS_ERROR_NOT_AVAILABLE;
4167 }
4168
4169 doc.forget(aDocument);
4170 return NS_OK;
4171}
4172
4173NS_IMETHODIMPnsresult
4174nsDocShell::GetCurrentURI(nsIURI** aURI) {
4175 NS_ENSURE_ARG_POINTER(aURI)do { if ((__builtin_expect(!!(!(aURI)), 0))) { NS_DebugBreak(
NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aURI" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 4175); return NS_ERROR_INVALID_POINTER; } } while (false)
;
4176
4177 nsCOMPtr<nsIURI> uri = mCurrentURI;
4178 uri.forget(aURI);
4179 return NS_OK;
4180}
4181
4182NS_IMETHODIMPnsresult
4183nsDocShell::GetSessionHistoryXPCOM(nsISupports** aSessionHistory) {
4184 NS_ENSURE_ARG_POINTER(aSessionHistory)do { if ((__builtin_expect(!!(!(aSessionHistory)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aSessionHistory" ") failed"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 4184); return NS_ERROR_INVALID_POINTER; } } while (false)
;
4185 RefPtr<ChildSHistory> shistory = GetSessionHistory();
4186 shistory.forget(aSessionHistory);
4187 return NS_OK;
4188}
4189
4190//*****************************************************************************
4191// nsDocShell::nsIWebPageDescriptor
4192//*****************************************************************************
4193
4194NS_IMETHODIMPnsresult
4195nsDocShell::LoadPageAsViewSource(nsIDocShell* aOtherDocShell,
4196 const nsAString& aURI) {
4197 if (!aOtherDocShell) {
4198 return NS_ERROR_INVALID_POINTER;
4199 }
4200 nsCOMPtr<nsIURI> newURI;
4201 nsresult rv = NS_NewURI(getter_AddRefs(newURI), aURI);
4202 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
4203 return rv;
4204 }
4205
4206 RefPtr<nsDocShellLoadState> loadState;
4207 uint32_t cacheKey;
4208 auto* otherDocShell = nsDocShell::Cast(aOtherDocShell);
4209 if (mozilla::SessionHistoryInParent()) {
4210 loadState = new nsDocShellLoadState(newURI);
4211 if (!otherDocShell->FillLoadStateFromCurrentEntry(*loadState)) {
4212 return NS_ERROR_INVALID_POINTER;
4213 }
4214 cacheKey = otherDocShell->GetCacheKeyFromCurrentEntry().valueOr(0);
4215 } else {
4216 nsCOMPtr<nsISHEntry> entry;
4217 bool isOriginalSHE;
4218 otherDocShell->GetCurrentSHEntry(getter_AddRefs(entry), &isOriginalSHE);
4219 if (!entry) {
4220 return NS_ERROR_INVALID_POINTER;
4221 }
4222 rv = entry->CreateLoadInfo(getter_AddRefs(loadState));
4223 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/docshell/base/nsDocShell.cpp"
, 4223); return rv; } } while (false)
;
4224 entry->GetCacheKey(&cacheKey);
4225 loadState->SetURI(newURI);
4226 loadState->SetSHEntry(nullptr);
4227 }
4228
4229 // We're doing a load of the page, via an API that
4230 // is only exposed to system code. The triggering principal for this load
4231 // should be the system principal.
4232 loadState->SetTriggeringPrincipal(nsContentUtils::GetSystemPrincipal());
4233 loadState->SetOriginalURI(nullptr);
4234 loadState->SetResultPrincipalURI(nullptr);
4235
4236 return InternalLoad(loadState, Some(cacheKey));
4237}
4238
4239NS_IMETHODIMPnsresult
4240nsDocShell::GetCurrentDescriptor(nsISupports** aPageDescriptor) {
4241 MOZ_ASSERT(aPageDescriptor, "Null out param?")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aPageDescriptor)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aPageDescriptor))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("aPageDescriptor"
" (" "Null out param?" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 4241); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPageDescriptor"
") (" "Null out param?" ")"); do { *((volatile int*)__null) =
4241; __attribute__((nomerge)) ::abort(); } while (false); }
} while (false)
;
4242
4243 *aPageDescriptor = nullptr;
4244
4245 nsISHEntry* src = mOSHE ? mOSHE : mLSHE;
4246 if (src) {
4247 nsCOMPtr<nsISHEntry> dest;
4248
4249 nsresult rv = src->Clone(getter_AddRefs(dest));
4250 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
4251 return rv;
4252 }
4253
4254 // null out inappropriate cloned attributes...
4255 dest->SetParent(nullptr);
4256 dest->SetIsSubFrame(false);
4257
4258 return CallQueryInterface(dest, aPageDescriptor);
4259 }
4260
4261 return NS_ERROR_NOT_AVAILABLE;
4262}
4263
4264already_AddRefed<nsIInputStream> nsDocShell::GetPostDataFromCurrentEntry()
4265 const {
4266 nsCOMPtr<nsIInputStream> postData;
4267 if (mozilla::SessionHistoryInParent()) {
4268 if (mActiveEntry) {
4269 postData = mActiveEntry->GetPostData();
4270 } else if (mLoadingEntry) {
4271 postData = mLoadingEntry->mInfo.GetPostData();
4272 }
4273 } else {
4274 if (mOSHE) {
4275 postData = mOSHE->GetPostData();
4276 } else if (mLSHE) {
4277 postData = mLSHE->GetPostData();
4278 }
4279 }
4280
4281 return postData.forget();
4282}
4283
4284Maybe<uint32_t> nsDocShell::GetCacheKeyFromCurrentEntry() const {
4285 if (mozilla::SessionHistoryInParent()) {
4286 if (mActiveEntry) {
4287 return Some(mActiveEntry->GetCacheKey());
4288 }
4289
4290 if (mLoadingEntry) {
4291 return Some(mLoadingEntry->mInfo.GetCacheKey());
4292 }
4293 } else {
4294 if (mOSHE) {
4295 return Some(mOSHE->GetCacheKey());
4296 }
4297
4298 if (mLSHE) {
4299 return Some(mLSHE->GetCacheKey());
4300 }
4301 }
4302
4303 return Nothing();
4304}
4305
4306bool nsDocShell::FillLoadStateFromCurrentEntry(
4307 nsDocShellLoadState& aLoadState) {
4308 if (mLoadingEntry) {
4309 mLoadingEntry->mInfo.FillLoadInfo(aLoadState);
4310 return true;
4311 }
4312 if (mActiveEntry) {
4313 mActiveEntry->FillLoadInfo(aLoadState);
4314 return true;
4315 }
4316 return false;
4317}
4318
4319//*****************************************************************************
4320// nsDocShell::nsIBaseWindow
4321//*****************************************************************************
4322
4323NS_IMETHODIMPnsresult
4324nsDocShell::InitWindow(nativeWindow aParentNativeWindow,
4325 nsIWidget* aParentWidget, int32_t aX, int32_t aY,
4326 int32_t aWidth, int32_t aHeight) {
4327 SetParentWidget(aParentWidget);
4328 SetPositionAndSize(aX, aY, aWidth, aHeight, 0);
4329 NS_ENSURE_TRUE(Initialize(), NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(Initialize())), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "Initialize()" ") failed"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 4329); return NS_ERROR_FAILURE; } } while (false)
;
4330
4331 return NS_OK;
4332}
4333
4334NS_IMETHODIMPnsresult
4335nsDocShell::Destroy() {
4336 // XXX: We allow this function to be called just once. If you are going to
4337 // reset new variables in this function, please make sure the variables will
4338 // never be re-initialized. Adding assertions to check |mIsBeingDestroyed|
4339 // in the setter functions for the variables would be enough.
4340 if (mIsBeingDestroyed) {
4341 return NS_ERROR_DOCSHELL_DYING;
4342 }
4343
4344 NS_ASSERTION(mItemType == typeContent || mItemType == typeChrome,do { if (!(mItemType == typeContent || mItemType == typeChrome
)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "Unexpected item type in docshell"
, "mItemType == typeContent || mItemType == typeChrome", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 4345); MOZ_PretendNoReturn(); } } while (0)
4345 "Unexpected item type in docshell")do { if (!(mItemType == typeContent || mItemType == typeChrome
)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "Unexpected item type in docshell"
, "mItemType == typeContent || mItemType == typeChrome", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 4345); MOZ_PretendNoReturn(); } } while (0)
;
4346
4347 nsCOMPtr<nsIObserverService> serv = services::GetObserverService();
4348 if (serv) {
4349 const char* msg = mItemType == typeContent
4350 ? NS_WEBNAVIGATION_DESTROY"webnavigation-destroy"
4351 : NS_CHROME_WEBNAVIGATION_DESTROY"chrome-webnavigation-destroy";
4352 serv->NotifyObservers(GetAsSupports(this), msg, nullptr);
4353 }
4354
4355 mIsBeingDestroyed = true;
4356
4357 // Brak the cycle with the initial client, if present.
4358 mInitialClientSource.reset();
4359
4360 // Make sure to blow away our mLoadingURI just in case. No loads
4361 // from inside this pagehide.
4362 mLoadingURI = nullptr;
4363
4364 // Fire unload event before we blow anything away.
4365 (void)FirePageHideNotification(true);
4366
4367 // Clear pointers to any detached nsEditorData that's lying
4368 // around in shistory entries. Breaks cycle. See bug 430921.
4369 if (mOSHE) {
4370 mOSHE->SetEditorData(nullptr);
4371 }
4372 if (mLSHE) {
4373 mLSHE->SetEditorData(nullptr);
4374 }
4375
4376 // Note: mContentListener can be null if Init() failed and we're being
4377 // called from the destructor.
4378 if (mContentListener) {
4379 mContentListener->DropDocShellReference();
4380 mContentListener->SetParentContentListener(nullptr);
4381 // Note that we do NOT set mContentListener to null here; that
4382 // way if someone tries to do a load in us after this point
4383 // the nsDSURIContentListener will block it. All of which
4384 // means that we should do this before calling Stop(), of
4385 // course.
4386 }
4387
4388 // Stop any URLs that are currently being loaded...
4389 Stop(nsIWebNavigation::STOP_ALL);
4390
4391 mEditorData = nullptr;
4392
4393 // Save the state of the current document, before destroying the window.
4394 // This is needed to capture the state of a frameset when the new document
4395 // causes the frameset to be destroyed...
4396 PersistLayoutHistoryState();
4397
4398 // Remove this docshell from its parent's child list
4399 nsCOMPtr<nsIDocShellTreeItem> docShellParentAsItem =
4400 do_QueryInterface(GetAsSupports(mParent));
4401 if (docShellParentAsItem) {
4402 docShellParentAsItem->RemoveChild(this);
4403 }
4404
4405 if (mDocumentViewer) {
4406 mDocumentViewer->Close(nullptr);
4407 mDocumentViewer->Destroy();
4408 mDocumentViewer = nullptr;
4409 }
4410
4411 nsDocLoader::Destroy();
4412
4413 mParentWidget = nullptr;
4414 SetCurrentURIInternal(nullptr);
4415
4416 if (mScriptGlobal) {
4417 mScriptGlobal->DetachFromDocShell(!mWillChangeProcess);
4418 mScriptGlobal = nullptr;
4419 }
4420
4421 if (GetSessionHistory()) {
4422 // We want to destroy these content viewers now rather than
4423 // letting their destruction wait for the session history
4424 // entries to get garbage collected. (Bug 488394)
4425 GetSessionHistory()->EvictLocalDocumentViewers();
4426 }
4427
4428 if (mWillChangeProcess && !mBrowsingContext->IsDiscarded()) {
4429 mBrowsingContext->PrepareForProcessChange();
4430 }
4431
4432 SetTreeOwner(nullptr);
4433
4434 mBrowserChild = nullptr;
4435
4436 mChromeEventHandler = nullptr;
4437
4438 // Cancel any timers that were set for this docshell; this is needed
4439 // to break the cycle between us and the timers.
4440 CancelRefreshURITimers();
4441
4442 return NS_OK;
4443}
4444
4445double nsDocShell::GetWidgetCSSToDeviceScale() {
4446 if (mParentWidget) {
4447 return mParentWidget->GetDefaultScale().scale;
4448 }
4449 if (nsCOMPtr<nsIBaseWindow> ownerWindow = do_QueryInterface(mTreeOwner)) {
4450 return ownerWindow->GetWidgetCSSToDeviceScale();
4451 }
4452 return 1.0;
4453}
4454
4455NS_IMETHODIMPnsresult
4456nsDocShell::GetDevicePixelsPerDesktopPixel(double* aScale) {
4457 if (mParentWidget) {
4458 *aScale = mParentWidget->GetDesktopToDeviceScale().scale;
4459 return NS_OK;
4460 }
4461
4462 nsCOMPtr<nsIBaseWindow> ownerWindow(do_QueryInterface(mTreeOwner));
4463 if (ownerWindow) {
4464 return ownerWindow->GetDevicePixelsPerDesktopPixel(aScale);
4465 }
4466
4467 *aScale = 1.0;
4468 return NS_OK;
4469}
4470
4471NS_IMETHODIMPnsresult
4472nsDocShell::SetPosition(int32_t aX, int32_t aY) {
4473 mBounds.MoveTo(aX, aY);
4474
4475 if (mDocumentViewer) {
4476 NS_ENSURE_SUCCESS(mDocumentViewer->Move(aX, aY), NS_ERROR_FAILURE)do { nsresult __rv = mDocumentViewer->Move(aX, aY); 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", "mDocumentViewer->Move(aX, aY)"
, "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/docshell/base/nsDocShell.cpp"
, 4476); return NS_ERROR_FAILURE; } } while (false)
;
4477 }
4478
4479 return NS_OK;
4480}
4481
4482NS_IMETHODIMPnsresult
4483nsDocShell::SetPositionDesktopPix(int32_t aX, int32_t aY) {
4484 nsCOMPtr<nsIBaseWindow> ownerWindow(do_QueryInterface(mTreeOwner));
4485 if (ownerWindow) {
4486 return ownerWindow->SetPositionDesktopPix(aX, aY);
4487 }
4488
4489 double scale = 1.0;
4490 GetDevicePixelsPerDesktopPixel(&scale);
4491 return SetPosition(NSToIntRound(aX * scale), NSToIntRound(aY * scale));
4492}
4493
4494NS_IMETHODIMPnsresult
4495nsDocShell::GetPosition(int32_t* aX, int32_t* aY) {
4496 return GetPositionAndSize(aX, aY, nullptr, nullptr);
4497}
4498
4499NS_IMETHODIMPnsresult
4500nsDocShell::SetSize(int32_t aWidth, int32_t aHeight, bool aRepaint) {
4501 int32_t x = 0, y = 0;
4502 GetPosition(&x, &y);
4503 return SetPositionAndSize(x, y, aWidth, aHeight,
4504 aRepaint ? nsIBaseWindow::eRepaint : 0);
4505}
4506
4507NS_IMETHODIMPnsresult
4508nsDocShell::GetSize(int32_t* aWidth, int32_t* aHeight) {
4509 return GetPositionAndSize(nullptr, nullptr, aWidth, aHeight);
4510}
4511
4512NS_IMETHODIMPnsresult
4513nsDocShell::SetPositionAndSize(int32_t aX, int32_t aY, int32_t aWidth,
4514 int32_t aHeight, uint32_t aFlags) {
4515 mBounds.SetRect(aX, aY, aWidth, aHeight);
4516
4517 // Hold strong ref, since SetBounds can make us null out mDocumentViewer
4518 nsCOMPtr<nsIDocumentViewer> viewer = mDocumentViewer;
4519 if (viewer) {
4520 uint32_t cvflags = (aFlags & nsIBaseWindow::eDelayResize)
4521 ? nsIDocumentViewer::eDelayResize
4522 : 0;
4523 // XXX Border figured in here or is that handled elsewhere?
4524 nsresult rv = viewer->SetBoundsWithFlags(mBounds, cvflags);
4525 NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE)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", "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/docshell/base/nsDocShell.cpp"
, 4525); return NS_ERROR_FAILURE; } } while (false)
;
4526 }
4527
4528 return NS_OK;
4529}
4530
4531NS_IMETHODIMPnsresult
4532nsDocShell::GetPositionAndSize(int32_t* aX, int32_t* aY, int32_t* aWidth,
4533 int32_t* aHeight) {
4534 if (mParentWidget) {
4535 // ensure size is up-to-date if window has changed resolution
4536 LayoutDeviceIntRect r = mParentWidget->GetClientBounds();
4537 SetPositionAndSize(mBounds.X(), mBounds.Y(), r.Width(), r.Height(), 0);
4538 }
4539
4540 // We should really consider just getting this information from
4541 // our window instead of duplicating the storage and code...
4542 if (aWidth || aHeight) {
4543 // Caller wants to know our size; make sure to give them up to
4544 // date information.
4545 RefPtr<Document> doc(do_GetInterface(GetAsSupports(mParent)));
4546 if (doc) {
4547 doc->FlushPendingNotifications(FlushType::Layout);
4548 }
4549 }
4550
4551 DoGetPositionAndSize(aX, aY, aWidth, aHeight);
4552 return NS_OK;
4553}
4554
4555void nsDocShell::DoGetPositionAndSize(int32_t* aX, int32_t* aY, int32_t* aWidth,
4556 int32_t* aHeight) {
4557 if (aX) {
4558 *aX = mBounds.X();
4559 }
4560 if (aY) {
4561 *aY = mBounds.Y();
4562 }
4563 if (aWidth) {
4564 *aWidth = mBounds.Width();
4565 }
4566 if (aHeight) {
4567 *aHeight = mBounds.Height();
4568 }
4569}
4570
4571NS_IMETHODIMPnsresult
4572nsDocShell::SetDimensions(DimensionRequest&& aRequest) {
4573 return NS_ERROR_NOT_IMPLEMENTED;
4574}
4575
4576NS_IMETHODIMPnsresult
4577nsDocShell::GetDimensions(DimensionKind aDimensionKind, int32_t* aX,
4578 int32_t* aY, int32_t* aCX, int32_t* aCY) {
4579 return NS_ERROR_NOT_IMPLEMENTED;
4580}
4581
4582NS_IMETHODIMPnsresult
4583nsDocShell::Repaint(bool aForce) {
4584 PresShell* presShell = GetPresShell();
4585 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/docshell/base/nsDocShell.cpp"
, 4585); return NS_ERROR_FAILURE; } } while (false)
;
4586
4587 RefPtr<nsViewManager> viewManager = presShell->GetViewManager();
4588 NS_ENSURE_TRUE(viewManager, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(viewManager)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "viewManager" ") failed"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 4588); return NS_ERROR_FAILURE; } } while (false)
;
4589
4590 viewManager->InvalidateAllViews();
4591 return NS_OK;
4592}
4593
4594NS_IMETHODIMPnsresult
4595nsDocShell::GetParentWidget(nsIWidget** aParentWidget) {
4596 NS_ENSURE_ARG_POINTER(aParentWidget)do { if ((__builtin_expect(!!(!(aParentWidget)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aParentWidget" ") failed"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 4596); return NS_ERROR_INVALID_POINTER; } } while (false)
;
4597
4598 *aParentWidget = mParentWidget;
4599 NS_IF_ADDREF(*aParentWidget)ns_if_addref(*aParentWidget);
4600
4601 return NS_OK;
4602}
4603
4604NS_IMETHODIMPnsresult
4605nsDocShell::SetParentWidget(nsIWidget* aParentWidget) {
4606 MOZ_ASSERT(!mIsBeingDestroyed)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mIsBeingDestroyed)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mIsBeingDestroyed))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("!mIsBeingDestroyed"
, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 4606); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mIsBeingDestroyed"
")"); do { *((volatile int*)__null) = 4606; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4607 mParentWidget = aParentWidget;
4608
4609 return NS_OK;
4610}
4611
4612NS_IMETHODIMPnsresult
4613nsDocShell::GetParentNativeWindow(nativeWindow* aParentNativeWindow) {
4614 NS_ENSURE_ARG_POINTER(aParentNativeWindow)do { if ((__builtin_expect(!!(!(aParentNativeWindow)), 0))) {
NS_DebugBreak(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aParentNativeWindow"
") failed", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 4614); return NS_ERROR_INVALID_POINTER; } } while (false)
;
4615
4616 if (mParentWidget) {
4617 *aParentNativeWindow = mParentWidget->GetNativeData(NS_NATIVE_WIDGET3);
4618 } else {
4619 *aParentNativeWindow = nullptr;
4620 }
4621
4622 return NS_OK;
4623}
4624
4625NS_IMETHODIMPnsresult
4626nsDocShell::SetParentNativeWindow(nativeWindow aParentNativeWindow) {
4627 return NS_ERROR_NOT_IMPLEMENTED;
4628}
4629
4630NS_IMETHODIMPnsresult
4631nsDocShell::GetNativeHandle(nsAString& aNativeHandle) {
4632 // the nativeHandle should be accessed from nsIAppWindow
4633 return NS_ERROR_NOT_IMPLEMENTED;
4634}
4635
4636NS_IMETHODIMPnsresult
4637nsDocShell::GetVisibility(bool* aVisibility) {
4638 NS_ENSURE_ARG_POINTER(aVisibility)do { if ((__builtin_expect(!!(!(aVisibility)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aVisibility" ") failed"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 4638); return NS_ERROR_INVALID_POINTER; } } while (false)
;
4639
4640 *aVisibility = false;
4641
4642 if (!mDocumentViewer) {
4643 return NS_OK;
4644 }
4645
4646 PresShell* presShell = GetPresShell();
4647 if (!presShell) {
4648 return NS_OK;
4649 }
4650
4651 // get the view manager
4652 nsViewManager* vm = presShell->GetViewManager();
4653 NS_ENSURE_TRUE(vm, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(vm)), 0))) { NS_DebugBreak(NS_DEBUG_WARNING
, "NS_ENSURE_TRUE(" "vm" ") failed", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 4653); return NS_ERROR_FAILURE; } } while (false)
;
4654
4655 // get the root view
4656 nsView* view = vm->GetRootView(); // views are not ref counted
4657 NS_ENSURE_TRUE(view, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(view)), 0))) { NS_DebugBreak(
NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "view" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 4657); return NS_ERROR_FAILURE; } } while (false)
;
4658
4659 // if our root view is hidden, we are not visible
4660 if (view->GetVisibility() == ViewVisibility::Hide) {
4661 return NS_OK;
4662 }
4663
4664 // otherwise, we must walk up the document and view trees checking
4665 // for a hidden view, unless we're an off screen browser, which
4666 // would make this test meaningless.
4667
4668 RefPtr<nsDocShell> docShell = this;
4669 RefPtr<nsDocShell> parentItem = docShell->GetInProcessParentDocshell();
4670 while (parentItem) {
4671 // Null-check for crash in bug 267804
4672 if (!parentItem->GetPresShell()) {
4673 MOZ_ASSERT_UNREACHABLE("parent docshell has null pres shell")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "MOZ_ASSERT_UNREACHABLE: "
"parent docshell has null pres shell" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 4673); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "parent docshell has null pres shell"
")"); do { *((volatile int*)__null) = 4673; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4674 return NS_OK;
4675 }
4676
4677 vm = docShell->GetPresShell()->GetViewManager();
4678 if (vm) {
4679 view = vm->GetRootView();
4680 }
4681
4682 if (view) {
4683 view = view->GetParent(); // anonymous inner view
4684 if (view) {
4685 view = view->GetParent(); // subdocumentframe's view
4686 }
4687 }
4688
4689 nsIFrame* frame = view ? view->GetFrame() : nullptr;
4690 if (frame && !frame->IsVisibleConsideringAncestors(
4691 nsIFrame::VISIBILITY_CROSS_CHROME_CONTENT_BOUNDARY)) {
4692 return NS_OK;
4693 }
4694
4695 docShell = parentItem;
4696 parentItem = docShell->GetInProcessParentDocshell();
4697 }
4698
4699 nsCOMPtr<nsIBaseWindow> treeOwnerAsWin(do_QueryInterface(mTreeOwner));
4700 if (!treeOwnerAsWin) {
4701 *aVisibility = true;
4702 return NS_OK;
4703 }
4704
4705 // Check with the tree owner as well to give embedders a chance to
4706 // expose visibility as well.
4707 nsresult rv = treeOwnerAsWin->GetVisibility(aVisibility);
4708 if (rv == NS_ERROR_NOT_IMPLEMENTED) {
4709 // The tree owner had no opinion on our visibility.
4710 *aVisibility = true;
4711 return NS_OK;
4712 }
4713 return rv;
4714}
4715
4716void nsDocShell::ActivenessMaybeChanged() {
4717 const bool isActive = mBrowsingContext->IsActive();
4718 if (RefPtr<PresShell> presShell = GetPresShell()) {
4719 presShell->ActivenessMaybeChanged();
4720 }
4721
4722 // Tell the window about it
4723 if (mScriptGlobal) {
4724 mScriptGlobal->SetIsBackground(!isActive);
4725 if (RefPtr<Document> doc = mScriptGlobal->GetExtantDoc()) {
4726 // Update orientation when the top-level browsing context becomes active.
4727 if (isActive && mBrowsingContext->IsTop()) {
4728 // We only care about the top-level browsing context.
4729 auto orientation = mBrowsingContext->GetOrientationLock();
4730 ScreenOrientation::UpdateActiveOrientationLock(orientation);
4731 }
4732
4733 doc->PostVisibilityUpdateEvent();
4734 }
4735 }
4736
4737 // Tell the nsDOMNavigationTiming about it
4738 RefPtr<nsDOMNavigationTiming> timing = mTiming;
4739 if (!timing && mDocumentViewer) {
4740 if (Document* doc = mDocumentViewer->GetDocument()) {
4741 timing = doc->GetNavigationTiming();
4742 }
4743 }
4744 if (timing) {
4745 timing->NotifyDocShellStateChanged(
4746 isActive ? nsDOMNavigationTiming::DocShellState::eActive
4747 : nsDOMNavigationTiming::DocShellState::eInactive);
4748 }
4749
4750 // Restart or stop meta refresh timers if necessary
4751 if (mDisableMetaRefreshWhenInactive) {
4752 if (isActive) {
4753 ResumeRefreshURIs();
4754 } else {
4755 SuspendRefreshURIs();
4756 }
4757 }
4758
4759 if (InputTaskManager::CanSuspendInputEvent()) {
4760 mBrowsingContext->Group()->UpdateInputTaskManagerIfNeeded(isActive);
4761 }
4762}
4763
4764NS_IMETHODIMPnsresult
4765nsDocShell::SetDefaultLoadFlags(uint32_t aDefaultLoadFlags) {
4766 if (!mWillChangeProcess) {
4767 // Intentionally ignoring handling discarded browsing contexts.
4768 Unused << mBrowsingContext->SetDefaultLoadFlags(aDefaultLoadFlags);
4769 } else {
4770 // Bug 1623565: DevTools tries to clean up defaultLoadFlags on
4771 // shutdown. Sorry DevTools, your DocShell is in another process.
4772 NS_WARNING("nsDocShell::SetDefaultLoadFlags called on Zombie DocShell")NS_DebugBreak(NS_DEBUG_WARNING, "nsDocShell::SetDefaultLoadFlags called on Zombie DocShell"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 4772)
;
4773 }
4774 return NS_OK;
4775}
4776
4777NS_IMETHODIMPnsresult
4778nsDocShell::GetDefaultLoadFlags(uint32_t* aDefaultLoadFlags) {
4779 *aDefaultLoadFlags = mBrowsingContext->GetDefaultLoadFlags();
4780 return NS_OK;
4781}
4782
4783NS_IMETHODIMPnsresult
4784nsDocShell::GetFailedChannel(nsIChannel** aFailedChannel) {
4785 NS_ENSURE_ARG_POINTER(aFailedChannel)do { if ((__builtin_expect(!!(!(aFailedChannel)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aFailedChannel" ") failed"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 4785); return NS_ERROR_INVALID_POINTER; } } while (false)
;
4786 Document* doc = GetDocument();
4787 if (!doc) {
4788 *aFailedChannel = nullptr;
4789 return NS_OK;
4790 }
4791 NS_IF_ADDREF(*aFailedChannel = doc->GetFailedChannel())ns_if_addref(*aFailedChannel = doc->GetFailedChannel());
4792 return NS_OK;
4793}
4794
4795NS_IMETHODIMPnsresult
4796nsDocShell::SetVisibility(bool aVisibility) {
4797 // Show()/Hide() may change mDocumentViewer.
4798 nsCOMPtr<nsIDocumentViewer> viewer = mDocumentViewer;
4799 if (!viewer) {
4800 return NS_OK;
4801 }
4802 if (aVisibility) {
4803 viewer->Show();
4804 } else {
4805 viewer->Hide();
4806 }
4807
4808 return NS_OK;
4809}
4810
4811NS_IMETHODIMPnsresult
4812nsDocShell::GetEnabled(bool* aEnabled) {
4813 NS_ENSURE_ARG_POINTER(aEnabled)do { if ((__builtin_expect(!!(!(aEnabled)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aEnabled" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 4813); return NS_ERROR_INVALID_POINTER; } } while (false)
;
4814 *aEnabled = true;
4815 return NS_ERROR_NOT_IMPLEMENTED;
4816}
4817
4818NS_IMETHODIMPnsresult
4819nsDocShell::SetEnabled(bool aEnabled) { return NS_ERROR_NOT_IMPLEMENTED; }
4820
4821NS_IMETHODIMPnsresult
4822nsDocShell::GetMainWidget(nsIWidget** aMainWidget) {
4823 // We don't create our own widget, so simply return the parent one.
4824 return GetParentWidget(aMainWidget);
4825}
4826
4827NS_IMETHODIMPnsresult
4828nsDocShell::GetTitle(nsAString& aTitle) {
4829 aTitle = mTitle;
4830 return NS_OK;
4831}
4832
4833NS_IMETHODIMPnsresult
4834nsDocShell::SetTitle(const nsAString& aTitle) {
4835 // Avoid unnecessary updates of the title if the URI and the title haven't
4836 // changed.
4837 if (mTitleValidForCurrentURI && mTitle == aTitle) {
4838 return NS_OK;
4839 }
4840
4841 // Store local title
4842 mTitle = aTitle;
4843 mTitleValidForCurrentURI = true;
4844
4845 // When title is set on the top object it should then be passed to the
4846 // tree owner.
4847 if (mBrowsingContext->IsTop()) {
4848 nsCOMPtr<nsIBaseWindow> treeOwnerAsWin(do_QueryInterface(mTreeOwner));
4849 if (treeOwnerAsWin) {
4850 treeOwnerAsWin->SetTitle(aTitle);
4851 }
4852 }
4853
4854 if (mCurrentURI && mLoadType != LOAD_ERROR_PAGE) {
4855 UpdateGlobalHistoryTitle(mCurrentURI);
4856 }
4857
4858 // Update SessionHistory with the document's title.
4859 if (mLoadType != LOAD_BYPASS_HISTORY && mLoadType != LOAD_ERROR_PAGE) {
4860 SetTitleOnHistoryEntry(true);
4861 }
4862
4863 return NS_OK;
4864}
4865
4866void nsDocShell::SetTitleOnHistoryEntry(bool aUpdateEntryInSessionHistory) {
4867 if (mOSHE) {
4868 mOSHE->SetTitle(mTitle);
4869 }
4870
4871 if (mActiveEntry && mBrowsingContext) {
4872 mActiveEntry->SetTitle(mTitle);
4873 if (aUpdateEntryInSessionHistory) {
4874 if (XRE_IsParentProcess()) {
4875 SessionHistoryEntry* entry =
4876 mBrowsingContext->Canonical()->GetActiveSessionHistoryEntry();
4877 if (entry) {
4878 entry->SetTitle(mTitle);
4879 }
4880 } else {
4881 mozilla::Unused
4882 << ContentChild::GetSingleton()->SendSessionHistoryEntryTitle(
4883 mBrowsingContext, mTitle);
4884 }
4885 }
4886 }
4887}
4888
4889nsPoint nsDocShell::GetCurScrollPos() {
4890 nsPoint scrollPos;
4891 if (ScrollContainerFrame* sf = GetRootScrollContainerFrame()) {
4892 scrollPos = sf->GetVisualViewportOffset();
4893 }
4894 return scrollPos;
4895}
4896
4897nsresult nsDocShell::SetCurScrollPosEx(int32_t aCurHorizontalPos,
4898 int32_t aCurVerticalPos) {
4899 ScrollContainerFrame* sf = GetRootScrollContainerFrame();
4900 NS_ENSURE_TRUE(sf, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(sf)), 0))) { NS_DebugBreak(NS_DEBUG_WARNING
, "NS_ENSURE_TRUE(" "sf" ") failed", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 4900); return NS_ERROR_FAILURE; } } while (false)
;
4901
4902 ScrollMode scrollMode =
4903 sf->IsSmoothScroll() ? ScrollMode::SmoothMsd : ScrollMode::Instant;
4904
4905 nsPoint targetPos(aCurHorizontalPos, aCurVerticalPos);
4906 sf->ScrollTo(targetPos, scrollMode);
4907
4908 // Set the visual viewport offset as well.
4909
4910 RefPtr<PresShell> presShell = GetPresShell();
4911 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/docshell/base/nsDocShell.cpp"
, 4911); return NS_ERROR_FAILURE; } } while (false)
;
4912
4913 nsPresContext* presContext = presShell->GetPresContext();
4914 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/docshell/base/nsDocShell.cpp"
, 4914); return NS_ERROR_FAILURE; } } while (false)
;
4915
4916 // Only the root content document can have a distinct visual viewport offset.
4917 if (!presContext->IsRootContentDocumentCrossProcess()) {
4918 return NS_OK;
4919 }
4920
4921 // Not on a platform with a distinct visual viewport - don't bother setting
4922 // the visual viewport offset.
4923 if (!presShell->IsVisualViewportSizeSet()) {
4924 return NS_OK;
4925 }
4926
4927 presShell->ScrollToVisual(targetPos, layers::FrameMetrics::eMainThread,
4928 scrollMode);
4929
4930 return NS_OK;
4931}
4932
4933void nsDocShell::SetScrollbarPreference(mozilla::ScrollbarPreference aPref) {
4934 if (mScrollbarPref == aPref) {
4935 return;
4936 }
4937 mScrollbarPref = aPref;
4938 auto* ps = GetPresShell();
4939 if (!ps) {
4940 return;
4941 }
4942 nsIFrame* rootScrollContainerFrame = ps->GetRootScrollContainerFrame();
4943 if (!rootScrollContainerFrame) {
4944 return;
4945 }
4946 ps->FrameNeedsReflow(rootScrollContainerFrame,
4947 IntrinsicDirty::FrameAncestorsAndDescendants,
4948 NS_FRAME_IS_DIRTY);
4949}
4950
4951//*****************************************************************************
4952// nsDocShell::nsIRefreshURI
4953//*****************************************************************************
4954
4955NS_IMETHODIMPnsresult
4956nsDocShell::RefreshURI(nsIURI* aURI, nsIPrincipal* aPrincipal,
4957 uint32_t aDelay) {
4958 MOZ_ASSERT(!mIsBeingDestroyed)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mIsBeingDestroyed)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mIsBeingDestroyed))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("!mIsBeingDestroyed"
, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 4958); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mIsBeingDestroyed"
")"); do { *((volatile int*)__null) = 4958; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4959
4960 NS_ENSURE_ARG(aURI)do { if ((__builtin_expect(!!(!(aURI)), 0))) { NS_DebugBreak(
NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aURI" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 4960); return NS_ERROR_INVALID_ARG; } } while (false)
;
4961
4962 /* Check if Meta refresh/redirects are permitted. Some
4963 * embedded applications may not want to do this.
4964 * Must do this before sending out NOTIFY_REFRESH events
4965 * because listeners may have side effects (e.g. displaying a
4966 * button to manually trigger the refresh later).
4967 */
4968 bool allowRedirects = true;
4969 GetAllowMetaRedirects(&allowRedirects);
4970 if (!allowRedirects) {
4971 return NS_OK;
4972 }
4973
4974 // If any web progress listeners are listening for NOTIFY_REFRESH events,
4975 // give them a chance to block this refresh.
4976 bool sameURI;
4977 nsresult rv = aURI->Equals(mCurrentURI, &sameURI);
4978 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
4979 sameURI = false;
4980 }
4981 if (!RefreshAttempted(this, aURI, aDelay, sameURI)) {
4982 return NS_OK;
4983 }
4984
4985 nsCOMPtr<nsITimerCallback> refreshTimer =
4986 new nsRefreshTimer(this, aURI, aPrincipal, aDelay);
4987
4988 BusyFlags busyFlags = GetBusyFlags();
4989
4990 if (!mRefreshURIList) {
4991 mRefreshURIList = nsArray::Create();
4992 }
4993
4994 if (busyFlags & BUSY_FLAGS_BUSY ||
4995 (!mBrowsingContext->IsActive() && mDisableMetaRefreshWhenInactive)) {
4996 // We don't want to create the timer right now. Instead queue up the
4997 // request and trigger the timer in EndPageLoad() or whenever we become
4998 // active.
4999 mRefreshURIList->AppendElement(refreshTimer);
5000 } else {
5001 // There is no page loading going on right now. Create the
5002 // timer and fire it right away.
5003 nsCOMPtr<nsPIDOMWindowOuter> win = GetWindow();
5004 NS_ENSURE_TRUE(win, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(win)), 0))) { NS_DebugBreak(NS_DEBUG_WARNING
, "NS_ENSURE_TRUE(" "win" ") failed", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 5004); return NS_ERROR_FAILURE; } } while (false)
;
5005
5006 nsCOMPtr<nsITimer> timer;
5007 MOZ_TRY_VAR(timer, NS_NewTimerWithCallback(refreshTimer, aDelay,do { auto mozTryVarTempResult_ = (NS_NewTimerWithCallback(refreshTimer
, aDelay, nsITimer::TYPE_ONE_SHOT)); if ((__builtin_expect(!!
(mozTryVarTempResult_.isErr()), 0))) { return mozTryVarTempResult_
.propagateErr(); } (timer) = mozTryVarTempResult_.unwrap(); }
while (0)
5008 nsITimer::TYPE_ONE_SHOT))do { auto mozTryVarTempResult_ = (NS_NewTimerWithCallback(refreshTimer
, aDelay, nsITimer::TYPE_ONE_SHOT)); if ((__builtin_expect(!!
(mozTryVarTempResult_.isErr()), 0))) { return mozTryVarTempResult_
.propagateErr(); } (timer) = mozTryVarTempResult_.unwrap(); }
while (0)
;
5009
5010 mRefreshURIList->AppendElement(timer); // owning timer ref
5011 }
5012 return NS_OK;
5013}
5014
5015nsresult nsDocShell::ForceRefreshURIFromTimer(nsIURI* aURI,
5016 nsIPrincipal* aPrincipal,
5017 uint32_t aDelay,
5018 nsITimer* aTimer) {
5019 MOZ_ASSERT(aTimer, "Must have a timer here")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aTimer)>::isValid, "invalid assertion condition")
; if ((__builtin_expect(!!(!(!!(aTimer))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aTimer" " (" "Must have a timer here"
")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 5019); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aTimer" ") ("
"Must have a timer here" ")"); do { *((volatile int*)__null)
= 5019; __attribute__((nomerge)) ::abort(); } while (false);
} } while (false)
;
5020
5021 // Remove aTimer from mRefreshURIList if needed
5022 if (mRefreshURIList) {
5023 uint32_t n = 0;
5024 mRefreshURIList->GetLength(&n);
5025
5026 for (uint32_t i = 0; i < n; ++i) {
5027 nsCOMPtr<nsITimer> timer = do_QueryElementAt(mRefreshURIList, i);
5028 if (timer == aTimer) {
5029 mRefreshURIList->RemoveElementAt(i);
5030 break;
5031 }
5032 }
5033 }
5034
5035 return ForceRefreshURI(aURI, aPrincipal, aDelay);
5036}
5037
5038NS_IMETHODIMPnsresult
5039nsDocShell::ForceRefreshURI(nsIURI* aURI, nsIPrincipal* aPrincipal,
5040 uint32_t aDelay) {
5041 NS_ENSURE_ARG(aURI)do { if ((__builtin_expect(!!(!(aURI)), 0))) { NS_DebugBreak(
NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aURI" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 5041); return NS_ERROR_INVALID_ARG; } } while (false)
;
5042
5043 RefPtr<nsDocShellLoadState> loadState = new nsDocShellLoadState(aURI);
5044 loadState->SetOriginalURI(mCurrentURI);
5045 loadState->SetResultPrincipalURI(aURI);
5046 loadState->SetResultPrincipalURIIsSome(true);
5047 loadState->SetKeepResultPrincipalURIIfSet(true);
5048 loadState->SetIsMetaRefresh(true);
5049
5050 // Set the triggering pricipal to aPrincipal if available, or current
5051 // document's principal otherwise.
5052 nsCOMPtr<nsIPrincipal> principal = aPrincipal;
5053 RefPtr<Document> doc = GetDocument();
5054 if (!principal) {
5055 if (!doc) {
5056 return NS_ERROR_FAILURE;
5057 }
5058 principal = doc->NodePrincipal();
5059 }
5060 loadState->SetTriggeringPrincipal(principal);
5061 if (doc) {
5062 loadState->SetCsp(doc->GetCsp());
5063 loadState->SetHasValidUserGestureActivation(
5064 doc->HasValidTransientUserGestureActivation());
5065
5066 loadState->SetTextDirectiveUserActivation(
5067 doc->ConsumeTextDirectiveUserActivation() ||
5068 loadState->HasValidUserGestureActivation());
5069 loadState->SetTriggeringSandboxFlags(doc->GetSandboxFlags());
5070 loadState->SetTriggeringWindowId(doc->InnerWindowID());
5071 loadState->SetTriggeringStorageAccess(doc->UsingStorageAccess());
5072 }
5073
5074 loadState->SetPrincipalIsExplicit(true);
5075
5076 /* Check if this META refresh causes a redirection
5077 * to another site.
5078 */
5079 bool equalUri = false;
5080 nsresult rv = aURI->Equals(mCurrentURI, &equalUri);
5081
5082 nsCOMPtr<nsIReferrerInfo> referrerInfo;
5083 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && !equalUri && aDelay <= REFRESH_REDIRECT_TIMER15000) {
5084 /* It is a META refresh based redirection within the threshold time
5085 * we have in mind (15000 ms as defined by REFRESH_REDIRECT_TIMER).
5086 * Pass a REPLACE flag to LoadURI().
5087 */
5088 loadState->SetLoadType(LOAD_REFRESH_REPLACE);
5089
5090 /* For redirects we mimic HTTP, which passes the
5091 * original referrer.
5092 * We will pass in referrer but will not send to server
5093 */
5094 if (mReferrerInfo) {
5095 referrerInfo = static_cast<ReferrerInfo*>(mReferrerInfo.get())
5096 ->CloneWithNewSendReferrer(false);
5097 }
5098 } else {
5099 loadState->SetLoadType(LOAD_REFRESH);
5100 /* We do need to pass in a referrer, but we don't want it to
5101 * be sent to the server.
5102 * For most refreshes the current URI is an appropriate
5103 * internal referrer.
5104 */
5105 referrerInfo = new ReferrerInfo(mCurrentURI, ReferrerPolicy::_empty, false);
5106 }
5107
5108 loadState->SetReferrerInfo(referrerInfo);
5109 loadState->SetLoadFlags(
5110 nsIWebNavigation::LOAD_FLAGS_DISALLOW_INHERIT_PRINCIPAL);
5111 loadState->SetFirstParty(true);
5112
5113 /*
5114 * LoadURI(...) will cancel all refresh timers... This causes the
5115 * Timer and its refreshData instance to be released...
5116 */
5117 LoadURI(loadState, false);
5118
5119 return NS_OK;
5120}
5121
5122static const char16_t* SkipASCIIWhitespace(const char16_t* aStart,
5123 const char16_t* aEnd) {
5124 const char16_t* iter = aStart;
5125 while (iter != aEnd && mozilla::IsAsciiWhitespace(*iter)) {
5126 ++iter;
5127 }
5128 return iter;
5129}
5130
5131static std::tuple<const char16_t*, const char16_t*> ExtractURLString(
5132 const char16_t* aPosition, const char16_t* aEnd) {
5133 MOZ_ASSERT(aPosition != aEnd)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aPosition != aEnd)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aPosition != aEnd))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("aPosition != aEnd"
, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 5133); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPosition != aEnd"
")"); do { *((volatile int*)__null) = 5133; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5134
5135 // 1. Let urlString be the substring of input from the code point at
5136 // position to the end of the string.
5137 const char16_t* urlStart = aPosition;
5138 const char16_t* urlEnd = aEnd;
5139
5140 // 2. If the code point in input pointed to by position is U+0055 (U) or
5141 // U+0075 (u), then advance position to the next code point.
5142 // Otherwise, jump to the step labeled skip quotes.
5143 if (*aPosition == 'U' || *aPosition == 'u') {
5144 ++aPosition;
5145
5146 // 3. If the code point in input pointed to by position is U+0052 (R) or
5147 // U+0072 (r), then advance position to the next code point.
5148 // Otherwise, jump to the step labeled parse.
5149 if (aPosition == aEnd || (*aPosition != 'R' && *aPosition != 'r')) {
5150 return std::make_tuple(urlStart, urlEnd);
5151 }
5152
5153 ++aPosition;
5154
5155 // 4. If the code point in input pointed to by position is U+004C (L) or
5156 // U+006C (l), then advance position to the next code point.
5157 // Otherwise, jump to the step labeled parse.
5158 if (aPosition == aEnd || (*aPosition != 'L' && *aPosition != 'l')) {
5159 return std::make_tuple(urlStart, urlEnd);
5160 }
5161
5162 ++aPosition;
5163
5164 // 5. Skip ASCII whitespace within input given position.
5165 aPosition = SkipASCIIWhitespace(aPosition, aEnd);
5166
5167 // 6. If the code point in input pointed to by position is U+003D (=),
5168 // then advance position to the next code point. Otherwise, jump to
5169 // the step labeled parse.
5170 if (aPosition == aEnd || *aPosition != '=') {
5171 return std::make_tuple(urlStart, urlEnd);
5172 }
5173
5174 ++aPosition;
5175
5176 // 7. Skip ASCII whitespace within input given position.
5177 aPosition = SkipASCIIWhitespace(aPosition, aEnd);
5178 }
5179
5180 // 8. Skip quotes: If the code point in input pointed to by position is
5181 // U+0027 (') or U+0022 ("), then let quote be that code point, and
5182 // advance position to the next code point. Otherwise, let quote be
5183 // the empty string.
5184 Maybe<char> quote;
5185 if (aPosition != aEnd && (*aPosition == '\'' || *aPosition == '"')) {
5186 quote.emplace(*aPosition);
5187 ++aPosition;
5188 }
5189
5190 // 9. Set urlString to the substring of input from the code point at
5191 // position to the end of the string.
5192 urlStart = aPosition;
5193 urlEnd = aEnd;
5194
5195 // 10. If quote is not the empty string, and there is a code point in
5196 // urlString equal to quote, then truncate urlString at that code
5197 // point, so that it and all subsequent code points are removed.
5198 const char16_t* quotePos;
5199 if (quote.isSome() &&
5200 (quotePos = nsCharTraits<char16_t>::find(
5201 urlStart, std::distance(urlStart, aEnd), quote.value()))) {
5202 urlEnd = quotePos;
5203 }
5204
5205 return std::make_tuple(urlStart, urlEnd);
5206}
5207
5208void nsDocShell::SetupRefreshURIFromHeader(Document* aDocument,
5209 const nsAString& aHeader) {
5210 if (mIsBeingDestroyed) {
5211 return;
5212 }
5213
5214 const char16_t* position = aHeader.BeginReading();
5215 const char16_t* end = aHeader.EndReading();
5216
5217 // See
5218 // https://html.spec.whatwg.org/#pragma-directives:shared-declarative-refresh-steps.
5219
5220 // 3. Skip ASCII whitespace
5221 position = SkipASCIIWhitespace(position, end);
5222
5223 // 4. Let time be 0.
5224 CheckedInt<uint32_t> milliSeconds;
5225
5226 // 5. Collect a sequence of code points that are ASCII digits
5227 const char16_t* digitsStart = position;
5228 while (position != end && mozilla::IsAsciiDigit(*position)) {
5229 ++position;
5230 }
5231
5232 if (position == digitsStart) {
5233 // 6. If timeString is the empty string, then:
5234 // 1. If the code point in input pointed to by position is not U+002E
5235 // (.), then return.
5236 if (position == end || *position != '.') {
5237 return;
5238 }
5239 } else {
5240 // 7. Otherwise, set time to the result of parsing timeString using the
5241 // rules for parsing non-negative integers.
5242 nsContentUtils::ParseHTMLIntegerResultFlags result;
5243 uint32_t seconds =
5244 nsContentUtils::ParseHTMLInteger(digitsStart, position, &result);
5245 MOZ_ASSERT(!(result & nsContentUtils::eParseHTMLInteger_Negative))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!(result & nsContentUtils::eParseHTMLInteger_Negative
))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!(result & nsContentUtils::eParseHTMLInteger_Negative
)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!(result & nsContentUtils::eParseHTMLInteger_Negative)"
, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 5245); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!(result & nsContentUtils::eParseHTMLInteger_Negative)"
")"); do { *((volatile int*)__null) = 5245; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5246 if (result & nsContentUtils::eParseHTMLInteger_Error) {
5247 // The spec assumes no errors here (since we only pass ASCII digits in),
5248 // but we can still overflow, so this block should deal with that (and
5249 // only that).
5250 MOZ_ASSERT(!(result & nsContentUtils::eParseHTMLInteger_ErrorOverflow))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!(result & nsContentUtils::eParseHTMLInteger_ErrorOverflow
))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!(result & nsContentUtils::eParseHTMLInteger_ErrorOverflow
)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!(result & nsContentUtils::eParseHTMLInteger_ErrorOverflow)"
, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 5250); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!(result & nsContentUtils::eParseHTMLInteger_ErrorOverflow)"
")"); do { *((volatile int*)__null) = 5250; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5251 return;
5252 }
5253 MOZ_ASSERT(do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!(result & nsContentUtils::eParseHTMLInteger_DidNotConsumeAllInput
))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!(result & nsContentUtils::eParseHTMLInteger_DidNotConsumeAllInput
)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!(result & nsContentUtils::eParseHTMLInteger_DidNotConsumeAllInput)"
, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 5254); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!(result & nsContentUtils::eParseHTMLInteger_DidNotConsumeAllInput)"
")"); do { *((volatile int*)__null) = 5254; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
5254 !(result & nsContentUtils::eParseHTMLInteger_DidNotConsumeAllInput))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!(result & nsContentUtils::eParseHTMLInteger_DidNotConsumeAllInput
))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!(result & nsContentUtils::eParseHTMLInteger_DidNotConsumeAllInput
)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!(result & nsContentUtils::eParseHTMLInteger_DidNotConsumeAllInput)"
, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 5254); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!(result & nsContentUtils::eParseHTMLInteger_DidNotConsumeAllInput)"
")"); do { *((volatile int*)__null) = 5254; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5255
5256 milliSeconds = seconds;
5257 milliSeconds *= 1000;
5258 if (!milliSeconds.isValid()) {
5259 return;
5260 }
5261 }
5262
5263 // 8. Collect a sequence of code points that are ASCII digits and U+002E FULL
5264 // STOP characters (.) from input given position. Ignore any collected
5265 // characters.
5266 while (position != end &&
5267 (mozilla::IsAsciiDigit(*position) || *position == '.')) {
5268 ++position;
5269 }
5270
5271 // 9. Let urlRecord be document's URL.
5272 nsCOMPtr<nsIURI> urlRecord(aDocument->GetDocumentURI());
5273
5274 // 10. If position is not past the end of input
5275 if (position != end) {
5276 // 1. If the code point in input pointed to by position is not U+003B (;),
5277 // U+002C (,), or ASCII whitespace, then return.
5278 if (*position != ';' && *position != ',' &&
5279 !mozilla::IsAsciiWhitespace(*position)) {
5280 return;
5281 }
5282
5283 // 2. Skip ASCII whitespace within input given position.
5284 position = SkipASCIIWhitespace(position, end);
5285
5286 // 3. If the code point in input pointed to by position is U+003B (;) or
5287 // U+002C (,), then advance position to the next code point.
5288 if (position != end && (*position == ';' || *position == ',')) {
5289 ++position;
5290
5291 // 4. Skip ASCII whitespace within input given position.
5292 position = SkipASCIIWhitespace(position, end);
5293 }
5294
5295 // 11. If position is not past the end of input, then:
5296 if (position != end) {
5297 const char16_t* urlStart;
5298 const char16_t* urlEnd;
5299
5300 // 1-10. See ExtractURLString.
5301 std::tie(urlStart, urlEnd) = ExtractURLString(position, end);
5302
5303 // 11. Parse: Parse urlString relative to document. If that fails, return.
5304 // Otherwise, set urlRecord to the resulting URL record.
5305 nsresult rv =
5306 NS_NewURI(getter_AddRefs(urlRecord),
5307 Substring(urlStart, std::distance(urlStart, urlEnd)),
5308 /* charset = */ nullptr, aDocument->GetDocBaseURI());
5309 NS_ENSURE_SUCCESS_VOID(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_VOID(%s) failed with "
"result 0x%" "X" "%s%s%s", "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/docshell/base/nsDocShell.cpp"
, 5309); return; } } while (false)
;
5310 }
5311 }
5312
5313 nsIPrincipal* principal = aDocument->NodePrincipal();
5314 nsCOMPtr<nsIScriptSecurityManager> securityManager =
5315 nsContentUtils::GetSecurityManager();
5316 nsresult rv = securityManager->CheckLoadURIWithPrincipal(
5317 principal, urlRecord,
5318 nsIScriptSecurityManager::LOAD_IS_AUTOMATIC_DOCUMENT_REPLACEMENT,
5319 aDocument->InnerWindowID());
5320 NS_ENSURE_SUCCESS_VOID(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_VOID(%s) failed with "
"result 0x%" "X" "%s%s%s", "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/docshell/base/nsDocShell.cpp"
, 5320); return; } } while (false)
;
5321
5322 bool isjs = true;
5323 rv = NS_URIChainHasFlags(
5324 urlRecord, nsIProtocolHandler::URI_OPENING_EXECUTES_SCRIPT, &isjs);
5325 NS_ENSURE_SUCCESS_VOID(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_VOID(%s) failed with "
"result 0x%" "X" "%s%s%s", "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/docshell/base/nsDocShell.cpp"
, 5325); return; } } while (false)
;
5326
5327 if (isjs) {
5328 return;
5329 }
5330
5331 RefreshURI(urlRecord, principal, milliSeconds.value());
5332}
5333
5334static void DoCancelRefreshURITimers(nsIMutableArray* aTimerList) {
5335 if (!aTimerList) {
5336 return;
5337 }
5338
5339 uint32_t n = 0;
5340 aTimerList->GetLength(&n);
5341
5342 while (n) {
5343 nsCOMPtr<nsITimer> timer(do_QueryElementAt(aTimerList, --n));
5344
5345 aTimerList->RemoveElementAt(n); // bye bye owning timer ref
5346
5347 if (timer) {
5348 timer->Cancel();
5349 }
5350 }
5351}
5352
5353NS_IMETHODIMPnsresult
5354nsDocShell::CancelRefreshURITimers() {
5355 DoCancelRefreshURITimers(mRefreshURIList);
5356 DoCancelRefreshURITimers(mSavedRefreshURIList);
5357 DoCancelRefreshURITimers(mBFCachedRefreshURIList);
5358 mRefreshURIList = nullptr;
5359 mSavedRefreshURIList = nullptr;
5360 mBFCachedRefreshURIList = nullptr;
5361
5362 return NS_OK;
5363}
5364
5365NS_IMETHODIMPnsresult
5366nsDocShell::GetRefreshPending(bool* aResult) {
5367 if (!mRefreshURIList) {
5368 *aResult = false;
5369 return NS_OK;
5370 }
5371
5372 uint32_t count;
5373 nsresult rv = mRefreshURIList->GetLength(&count);
5374 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
5375 *aResult = (count != 0);
5376 }
5377 return rv;
5378}
5379
5380void nsDocShell::RefreshURIToQueue() {
5381 if (mRefreshURIList) {
5382 uint32_t n = 0;
5383 mRefreshURIList->GetLength(&n);
5384
5385 for (uint32_t i = 0; i < n; ++i) {
5386 nsCOMPtr<nsITimer> timer = do_QueryElementAt(mRefreshURIList, i);
5387 if (!timer) {
5388 continue; // this must be a nsRefreshURI already
5389 }
5390
5391 // Replace this timer object with a nsRefreshTimer object.
5392 nsCOMPtr<nsITimerCallback> callback;
5393 timer->GetCallback(getter_AddRefs(callback));
5394
5395 timer->Cancel();
5396
5397 mRefreshURIList->ReplaceElementAt(callback, i);
5398 }
5399 }
5400}
5401
5402NS_IMETHODIMPnsresult
5403nsDocShell::SuspendRefreshURIs() {
5404 RefreshURIToQueue();
5405
5406 // Suspend refresh URIs for our child shells as well.
5407 for (auto* child : mChildList.ForwardRange()) {
5408 nsCOMPtr<nsIDocShell> shell = do_QueryObject(child);
5409 if (shell) {
5410 shell->SuspendRefreshURIs();
5411 }
5412 }
5413
5414 return NS_OK;
5415}
5416
5417NS_IMETHODIMPnsresult
5418nsDocShell::ResumeRefreshURIs() {
5419 RefreshURIFromQueue();
5420
5421 // Resume refresh URIs for our child shells as well.
5422 for (auto* child : mChildList.ForwardRange()) {
5423 nsCOMPtr<nsIDocShell> shell = do_QueryObject(child);
5424 if (shell) {
5425 shell->ResumeRefreshURIs();
5426 }
5427 }
5428
5429 return NS_OK;
5430}
5431
5432nsresult nsDocShell::RefreshURIFromQueue() {
5433 if (!mRefreshURIList) {
5434 return NS_OK;
5435 }
5436 uint32_t n = 0;
5437 mRefreshURIList->GetLength(&n);
5438
5439 while (n) {
5440 nsCOMPtr<nsITimerCallback> refreshInfo =
5441 do_QueryElementAt(mRefreshURIList, --n);
5442
5443 if (refreshInfo) {
5444 // This is the nsRefreshTimer object, waiting to be
5445 // setup in a timer object and fired.
5446 // Create the timer and trigger it.
5447 uint32_t delay = static_cast<nsRefreshTimer*>(
5448 static_cast<nsITimerCallback*>(refreshInfo))
5449 ->GetDelay();
5450 nsCOMPtr<nsPIDOMWindowOuter> win = GetWindow();
5451 if (win) {
5452 nsCOMPtr<nsITimer> timer;
5453 NS_NewTimerWithCallback(getter_AddRefs(timer), refreshInfo, delay,
5454 nsITimer::TYPE_ONE_SHOT);
5455
5456 if (timer) {
5457 // Replace the nsRefreshTimer element in the queue with
5458 // its corresponding timer object, so that in case another
5459 // load comes through before the timer can go off, the timer will
5460 // get cancelled in CancelRefreshURITimer()
5461 mRefreshURIList->ReplaceElementAt(timer, n);
5462 }
5463 }
5464 }
5465 }
5466
5467 return NS_OK;
5468}
5469
5470static bool IsFollowupPartOfMultipart(nsIRequest* aRequest) {
5471 nsCOMPtr<nsIMultiPartChannel> multiPartChannel = do_QueryInterface(aRequest);
5472 bool firstPart = false;
5473 return multiPartChannel &&
5474 NS_SUCCEEDED(multiPartChannel->GetIsFirstPart(&firstPart))((bool)(__builtin_expect(!!(!NS_FAILED_impl(multiPartChannel->
GetIsFirstPart(&firstPart))), 1)))
&&
5475 !firstPart;
5476}
5477
5478nsresult nsDocShell::Embed(nsIDocumentViewer* aDocumentViewer,
5479 WindowGlobalChild* aWindowActor,
5480 bool aIsTransientAboutBlank, bool aPersist,
5481 nsIRequest* aRequest, nsIURI* aPreviousURI) {
5482 // Save the LayoutHistoryState of the previous document, before
5483 // setting up new document
5484 PersistLayoutHistoryState();
5485
5486 nsresult rv = SetupNewViewer(aDocumentViewer, aWindowActor);
5487 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/docshell/base/nsDocShell.cpp"
, 5487); return rv; } } while (false)
;
5488
5489 // XXX What if SetupNewViewer fails?
5490 if (mozilla::SessionHistoryInParent() ? !!mLoadingEntry : !!mLSHE) {
5491 // Set history.state
5492 SetDocCurrentStateObj(mLSHE,
5493 mLoadingEntry ? &mLoadingEntry->mInfo : nullptr);
5494 }
5495
5496 if (mLSHE) {
5497 // Restore the editing state, if it's stored in session history.
5498 if (mLSHE->HasDetachedEditor()) {
5499 ReattachEditorToWindow(mLSHE);
5500 }
5501
5502 SetHistoryEntryAndUpdateBC(Nothing(), Some<nsISHEntry*>(mLSHE));
5503 }
5504
5505 if (!aIsTransientAboutBlank && mozilla::SessionHistoryInParent() &&
5506 !IsFollowupPartOfMultipart(aRequest)) {
5507 bool expired = false;
5508 uint32_t cacheKey = 0;
5509 nsCOMPtr<nsICacheInfoChannel> cacheChannel = do_QueryInterface(aRequest);
5510 if (cacheChannel) {
5511 // Check if the page has expired from cache
5512 uint32_t expTime = 0;
5513 cacheChannel->GetCacheTokenExpirationTime(&expTime);
5514 uint32_t now = PRTimeToSeconds(PR_Now());
5515 if (expTime <= now) {
5516 expired = true;
5517 }
5518
5519 // The checks for updating cache key are similar to the old session
5520 // history in OnNewURI. Try to update the cache key if
5521 // - we should update session history and aren't doing a session
5522 // history load.
5523 // - we're doing a forced reload.
5524 if (((!mLoadingEntry || !mLoadingEntry->mLoadIsFromSessionHistory) &&
5525 mBrowsingContext->ShouldUpdateSessionHistory(mLoadType)) ||
5526 IsForceReloadType(mLoadType)) {
5527 cacheChannel->GetCacheKey(&cacheKey);
5528 }
5529 }
5530
5531 MOZ_LOG(gSHLog, LogLevel::Debug, ("document %p Embed", this))do { const ::mozilla::LogModule* moz_real_module = gSHLog; if
((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "document %p Embed", this); } } while (0)
;
5532 MoveLoadingToActiveEntry(aPersist, expired, cacheKey, aPreviousURI);
5533 }
5534
5535 bool updateHistory = true;
5536
5537 // Determine if this type of load should update history
5538 switch (mLoadType) {
5539 case LOAD_NORMAL_REPLACE:
5540 case LOAD_REFRESH_REPLACE:
5541 case LOAD_STOP_CONTENT_AND_REPLACE:
5542 case LOAD_RELOAD_BYPASS_CACHE:
5543 case LOAD_RELOAD_BYPASS_PROXY:
5544 case LOAD_RELOAD_BYPASS_PROXY_AND_CACHE:
5545 case LOAD_REPLACE_BYPASS_CACHE:
5546 updateHistory = false;
5547 break;
5548 default:
5549 break;
5550 }
5551
5552 if (!updateHistory) {
5553 SetLayoutHistoryState(nullptr);
5554 }
5555
5556 return NS_OK;
5557}
5558
5559//*****************************************************************************
5560// nsDocShell::nsIWebProgressListener
5561//*****************************************************************************
5562
5563NS_IMETHODIMPnsresult
5564nsDocShell::OnProgressChange(nsIWebProgress* aProgress, nsIRequest* aRequest,
5565 int32_t aCurSelfProgress, int32_t aMaxSelfProgress,
5566 int32_t aCurTotalProgress,
5567 int32_t aMaxTotalProgress) {
5568 return NS_OK;
5569}
5570
5571NS_IMETHODIMPnsresult
5572nsDocShell::OnStateChange(nsIWebProgress* aProgress, nsIRequest* aRequest,
5573 uint32_t aStateFlags, nsresult aStatus) {
5574 if ((~aStateFlags & (STATE_START | STATE_IS_NETWORK)) == 0) {
5575 // Save timing statistics.
5576 nsCOMPtr<nsIChannel> channel(do_QueryInterface(aRequest));
5577 nsCOMPtr<nsIURI> uri;
5578 channel->GetURI(getter_AddRefs(uri));
5579 nsAutoCString aURI;
5580 uri->GetAsciiSpec(aURI);
5581
5582 if (this == aProgress) {
5583 mozilla::Unused << MaybeInitTiming();
5584 mTiming->NotifyFetchStart(uri,
5585 ConvertLoadTypeToNavigationType(mLoadType));
5586 // If we are starting a DocumentChannel, we need to pass the timing
5587 // statistics so that should a process switch occur, the starting type can
5588 // be passed to the new DocShell running in the other content process.
5589 if (RefPtr<DocumentChannel> docChannel = do_QueryObject(aRequest)) {
5590 docChannel->SetNavigationTiming(mTiming);
5591 }
5592 }
5593
5594 // Page has begun to load
5595 mBusyFlags = (BusyFlags)(BUSY_FLAGS_BUSY | BUSY_FLAGS_BEFORE_PAGE_LOAD);
5596
5597 if ((aStateFlags & STATE_RESTORING) == 0) {
5598 if (SessionStorePlatformCollection()) {
5599 if (IsForceReloadType(mLoadType)) {
5600 if (WindowContext* windowContext =
5601 mBrowsingContext->GetCurrentWindowContext()) {
5602 SessionStoreChild::From(windowContext->GetWindowGlobalChild())
5603 ->ResetSessionStore(mBrowsingContext,
5604 mBrowsingContext->GetSessionStoreEpoch());
5605 }
5606 }
5607 }
5608 }
5609 } else if ((~aStateFlags & (STATE_TRANSFERRING | STATE_IS_DOCUMENT)) == 0) {
5610 // Page is loading
5611 mBusyFlags = (BusyFlags)(BUSY_FLAGS_BUSY | BUSY_FLAGS_PAGE_LOADING);
5612 } else if ((aStateFlags & STATE_STOP) && (aStateFlags & STATE_IS_NETWORK)) {
5613 // Page has finished loading
5614 mBusyFlags = BUSY_FLAGS_NONE;
5615 }
5616
5617 if ((~aStateFlags & (STATE_IS_DOCUMENT | STATE_STOP)) == 0) {
5618 nsCOMPtr<nsIWebProgress> webProgress =
5619 do_QueryInterface(GetAsSupports(this));
5620 // Is the document stop notification for this document?
5621 if (aProgress == webProgress.get()) {
5622 nsCOMPtr<nsIChannel> channel(do_QueryInterface(aRequest));
5623 EndPageLoad(aProgress, channel, aStatus);
5624 }
5625 }
5626 // note that redirect state changes will go through here as well, but it
5627 // is better to handle those in OnRedirectStateChange where more
5628 // information is available.
5629 return NS_OK;
5630}
5631
5632NS_IMETHODIMPnsresult
5633nsDocShell::OnLocationChange(nsIWebProgress* aProgress, nsIRequest* aRequest,
5634 nsIURI* aURI, uint32_t aFlags) {
5635 // Since we've now changed Documents, notify the BrowsingContext that we've
5636 // changed. Ideally we'd just let the BrowsingContext do this when it
5637 // changes the current window global, but that happens before this and we
5638 // have a lot of tests that depend on the specific ordering of messages.
5639 bool isTopLevel = false;
5640 if (XRE_IsParentProcess() &&
5641 !(aFlags & nsIWebProgressListener::LOCATION_CHANGE_SAME_DOCUMENT) &&
5642 NS_SUCCEEDED(aProgress->GetIsTopLevel(&isTopLevel))((bool)(__builtin_expect(!!(!NS_FAILED_impl(aProgress->GetIsTopLevel
(&isTopLevel))), 1)))
&& isTopLevel) {
5643 GetBrowsingContext()->Canonical()->UpdateSecurityState();
5644 }
5645 return NS_OK;
5646}
5647
5648void nsDocShell::OnRedirectStateChange(nsIChannel* aOldChannel,
5649 nsIChannel* aNewChannel,
5650 uint32_t aRedirectFlags,
5651 uint32_t aStateFlags) {
5652 NS_ASSERTION(aStateFlags & STATE_REDIRECTING,do { if (!(aStateFlags & STATE_REDIRECTING)) { NS_DebugBreak
(NS_DEBUG_ASSERTION, "Calling OnRedirectStateChange when there is no redirect"
, "aStateFlags & STATE_REDIRECTING", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 5653); MOZ_PretendNoReturn(); } } while (0)
5653 "Calling OnRedirectStateChange when there is no redirect")do { if (!(aStateFlags & STATE_REDIRECTING)) { NS_DebugBreak
(NS_DEBUG_ASSERTION, "Calling OnRedirectStateChange when there is no redirect"
, "aStateFlags & STATE_REDIRECTING", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 5653); MOZ_PretendNoReturn(); } } while (0)
;
5654
5655 if (!(aStateFlags & STATE_IS_DOCUMENT)) {
5656 return; // not a toplevel document
5657 }
5658
5659 nsCOMPtr<nsIURI> oldURI, newURI;
5660 aOldChannel->GetURI(getter_AddRefs(oldURI));
5661 aNewChannel->GetURI(getter_AddRefs(newURI));
5662 if (!oldURI || !newURI) {
5663 return;
5664 }
5665
5666 // DocumentChannel adds redirect chain to global history in the parent
5667 // process. The redirect chain can't be queried from the content process, so
5668 // there's no need to update global history here.
5669 RefPtr<DocumentChannel> docChannel = do_QueryObject(aOldChannel);
5670 if (!docChannel) {
5671 // Below a URI visit is saved (see AddURIVisit method doc).
5672 // The visit chain looks something like:
5673 // ...
5674 // Site N - 1
5675 // => Site N
5676 // (redirect to =>) Site N + 1 (we are here!)
5677
5678 // Get N - 1 and transition type
5679 nsCOMPtr<nsIURI> previousURI;
5680 uint32_t previousFlags = 0;
5681 ExtractLastVisit(aOldChannel, getter_AddRefs(previousURI), &previousFlags);
5682
5683 if (aRedirectFlags & nsIChannelEventSink::REDIRECT_INTERNAL ||
5684 net::ChannelIsPost(aOldChannel)) {
5685 // 1. Internal redirects are ignored because they are specific to the
5686 // channel implementation.
5687 // 2. POSTs are not saved by global history.
5688 //
5689 // Regardless, we need to propagate the previous visit to the new
5690 // channel.
5691 SaveLastVisit(aNewChannel, previousURI, previousFlags);
5692 } else {
5693 // Get the HTTP response code, if available.
5694 uint32_t responseStatus = 0;
5695 nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(aOldChannel);
5696 if (httpChannel) {
5697 Unused << httpChannel->GetResponseStatus(&responseStatus);
5698 }
5699
5700 // Add visit N -1 => N
5701 AddURIVisit(oldURI, previousURI, previousFlags, responseStatus);
5702
5703 // Since N + 1 could be the final destination, we will not save N => N + 1
5704 // here. OnNewURI will do that, so we will cache it.
5705 SaveLastVisit(aNewChannel, oldURI, aRedirectFlags);
5706 }
5707 }
5708
5709 if (!(aRedirectFlags & nsIChannelEventSink::REDIRECT_INTERNAL) &&
5710 mLoadType & (LOAD_CMD_RELOAD | LOAD_CMD_HISTORY)) {
5711 mLoadType = LOAD_NORMAL_REPLACE;
5712 SetHistoryEntryAndUpdateBC(Some(nullptr), Nothing());
5713 }
5714}
5715
5716NS_IMETHODIMPnsresult
5717nsDocShell::OnStatusChange(nsIWebProgress* aWebProgress, nsIRequest* aRequest,
5718 nsresult aStatus, const char16_t* aMessage) {
5719 MOZ_ASSERT_UNREACHABLE("notification excluded in AddProgressListener(...)")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "MOZ_ASSERT_UNREACHABLE: "
"notification excluded in AddProgressListener(...)" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 5719); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "notification excluded in AddProgressListener(...)"
")"); do { *((volatile int*)__null) = 5719; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5720 return NS_OK;
5721}
5722
5723NS_IMETHODIMPnsresult
5724nsDocShell::OnSecurityChange(nsIWebProgress* aWebProgress, nsIRequest* aRequest,
5725 uint32_t aState) {
5726 MOZ_ASSERT_UNREACHABLE("notification excluded in AddProgressListener(...)")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "MOZ_ASSERT_UNREACHABLE: "
"notification excluded in AddProgressListener(...)" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 5726); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "notification excluded in AddProgressListener(...)"
")"); do { *((volatile int*)__null) = 5726; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5727 return NS_OK;
5728}
5729
5730NS_IMETHODIMPnsresult
5731nsDocShell::OnContentBlockingEvent(nsIWebProgress* aWebProgress,
5732 nsIRequest* aRequest, uint32_t aEvent) {
5733 MOZ_ASSERT_UNREACHABLE("notification excluded in AddProgressListener(...)")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "MOZ_ASSERT_UNREACHABLE: "
"notification excluded in AddProgressListener(...)" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 5733); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "notification excluded in AddProgressListener(...)"
")"); do { *((volatile int*)__null) = 5733; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5734 return NS_OK;
5735}
5736
5737already_AddRefed<nsIURIFixupInfo> nsDocShell::KeywordToURI(
5738 const nsACString& aKeyword, bool aIsPrivateContext) {
5739 nsCOMPtr<nsIURIFixupInfo> info;
5740 if (!XRE_IsContentProcess()) {
5741 nsCOMPtr<nsIURIFixup> uriFixup = components::URIFixup::Service();
5742 if (uriFixup) {
5743 uriFixup->KeywordToURI(aKeyword, aIsPrivateContext, getter_AddRefs(info));
5744 }
5745 }
5746 return info.forget();
5747}
5748
5749/* static */
5750already_AddRefed<nsIURI> nsDocShell::MaybeFixBadCertDomainErrorURI(
5751 nsIChannel* aChannel, nsIURI* aUrl) {
5752 if (!aChannel) {
5753 return nullptr;
5754 }
5755
5756 nsresult rv = NS_OK;
5757 nsAutoCString host;
5758 rv = aUrl->GetAsciiHost(host);
5759 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/docshell/base/nsDocShell.cpp"
, 5759)
) {
5760 return nullptr;
5761 }
5762
5763 // Return if fixup enable pref is turned off.
5764 if (!mozilla::StaticPrefs::security_bad_cert_domain_error_url_fix_enabled()) {
5765 return nullptr;
5766 }
5767
5768 // Return if scheme is not HTTPS.
5769 if (!SchemeIsHTTPS(aUrl)) {
5770 return nullptr;
5771 }
5772
5773 nsCOMPtr<nsILoadInfo> info = aChannel->LoadInfo();
5774 if (!info) {
5775 return nullptr;
5776 }
5777
5778 // Skip doing the fixup if our channel was redirected, because we
5779 // shouldn't be guessing things about the post-redirect URI.
5780 if (!info->RedirectChain().IsEmpty()) {
5781 return nullptr;
5782 }
5783
5784 int32_t port = 0;
5785 rv = aUrl->GetPort(&port);
5786 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/docshell/base/nsDocShell.cpp"
, 5786)
) {
5787 return nullptr;
5788 }
5789
5790 // Don't fix up hosts with ports.
5791 if (port != -1) {
5792 return nullptr;
5793 }
5794
5795 // Don't fix up localhost url.
5796 if (host == "localhost") {
5797 return nullptr;
5798 }
5799
5800 // Don't fix up hostnames with IP address.
5801 if (net_IsValidIPv4Addr(host) || net_IsValidIPv6Addr(host)) {
5802 return nullptr;
5803 }
5804
5805 nsAutoCString userPass;
5806 rv = aUrl->GetUserPass(userPass);
5807 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/docshell/base/nsDocShell.cpp"
, 5807)
) {
5808 return nullptr;
5809 }
5810
5811 // Security - URLs with user / password info should NOT be modified.
5812 if (!userPass.IsEmpty()) {
5813 return nullptr;
5814 }
5815
5816 nsCOMPtr<nsITransportSecurityInfo> tsi;
5817 rv = aChannel->GetSecurityInfo(getter_AddRefs(tsi));
5818 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/docshell/base/nsDocShell.cpp"
, 5818)
) {
5819 return nullptr;
5820 }
5821
5822 if (NS_WARN_IF(!tsi)NS_warn_if_impl(!tsi, "!tsi", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 5822)
) {
5823 return nullptr;
5824 }
5825
5826 nsCOMPtr<nsIX509Cert> cert;
5827 rv = tsi->GetServerCert(getter_AddRefs(cert));
5828 if (NS_WARN_IF(NS_FAILED(rv) || !cert)NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(rv
)), 0))) || !cert, "NS_FAILED(rv) || !cert", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 5828)
) {
5829 return nullptr;
5830 }
5831
5832 nsTArray<uint8_t> certBytes;
5833 rv = cert->GetRawDER(certBytes);
5834 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
5835 return nullptr;
5836 }
5837
5838 mozilla::pkix::Input serverCertInput;
5839 mozilla::pkix::Result result =
5840 serverCertInput.Init(certBytes.Elements(), certBytes.Length());
5841 if (result != mozilla::pkix::Success) {
5842 return nullptr;
5843 }
5844
5845 constexpr auto wwwPrefix = "www."_ns;
5846 nsAutoCString newHost;
5847 if (StringBeginsWith(host, wwwPrefix)) {
5848 // Try www.example.com -> example.com
5849 newHost.Assign(Substring(host, wwwPrefix.Length()));
5850 } else {
5851 // Try example.com -> www.example.com
5852 newHost.Assign(wwwPrefix);
5853 newHost.Append(host);
5854 }
5855
5856 mozilla::pkix::Input newHostInput;
5857 result = newHostInput.Init(
5858 BitwiseCast<const uint8_t*, const char*>(newHost.BeginReading()),
5859 newHost.Length());
5860 if (result != mozilla::pkix::Success) {
5861 return nullptr;
5862 }
5863
5864 // Because certificate verification returned Result::ERROR_BAD_CERT_DOMAIN /
5865 // SSL_ERROR_BAD_CERT_DOMAIN, a chain was built and we know whether or not
5866 // the root was a built-in.
5867 bool rootIsBuiltIn;
5868 if (NS_FAILED(tsi->GetIsBuiltCertChainRootBuiltInRoot(&rootIsBuiltIn))((bool)(__builtin_expect(!!(NS_FAILED_impl(tsi->GetIsBuiltCertChainRootBuiltInRoot
(&rootIsBuiltIn))), 0)))
) {
5869 return nullptr;
5870 }
5871 mozilla::psm::SkipInvalidSANsForNonBuiltInRootsPolicy nameMatchingPolicy(
5872 rootIsBuiltIn);
5873
5874 // Check if the certificate is valid for the new hostname.
5875 result = mozilla::pkix::CheckCertHostname(serverCertInput, newHostInput,
5876 nameMatchingPolicy);
5877 if (result != mozilla::pkix::Success) {
5878 return nullptr;
5879 }
5880
5881 nsCOMPtr<nsIURI> newURI;
5882 Unused << NS_MutateURI(aUrl).SetHost(newHost).Finalize(
5883 getter_AddRefs(newURI));
5884
5885 return newURI.forget();
5886}
5887
5888/* static */
5889already_AddRefed<nsIURI> nsDocShell::AttemptURIFixup(
5890 nsIChannel* aChannel, nsresult aStatus,
5891 const mozilla::Maybe<nsCString>& aOriginalURIString, uint32_t aLoadType,
5892 bool aIsTopFrame, bool aAllowKeywordFixup, bool aUsePrivateBrowsing,
5893 bool aNotifyKeywordSearchLoading, nsIInputStream** aNewPostData,
5894 bool* outWasSchemelessInput) {
5895 if (aStatus != NS_ERROR_UNKNOWN_HOST && aStatus != NS_ERROR_NET_RESET &&
5896 aStatus != NS_ERROR_CONNECTION_REFUSED &&
5897 aStatus !=
5898 mozilla::psm::GetXPCOMFromNSSError(SSL_ERROR_BAD_CERT_DOMAIN)) {
5899 return nullptr;
5900 }
5901
5902 if (!(aLoadType == LOAD_NORMAL && aIsTopFrame) && !aAllowKeywordFixup) {
5903 return nullptr;
5904 }
5905
5906 nsCOMPtr<nsIURI> url;
5907 nsresult rv = aChannel->GetURI(getter_AddRefs(url));
5908 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
5909 return nullptr;
5910 }
5911
5912 //
5913 // Try and make an alternative URI from the old one
5914 //
5915 nsCOMPtr<nsIURI> newURI;
5916 nsCOMPtr<nsIInputStream> newPostData;
5917
5918 nsAutoCString oldSpec;
5919 url->GetSpec(oldSpec);
5920
5921 //
5922 // First try keyword fixup
5923 //
5924 nsAutoString keywordProviderName, keywordAsSent;
5925 if (aStatus == NS_ERROR_UNKNOWN_HOST && aAllowKeywordFixup) {
5926 // we should only perform a keyword search under the following
5927 // conditions:
5928 // (0) Pref keyword.enabled is true
5929 // (1) the url scheme is http (or https)
5930 // (2) the url does not have a protocol scheme
5931 // If we don't enforce such a policy, then we end up doing
5932 // keyword searchs on urls we don't intend like imap, file,
5933 // mailbox, etc. This could lead to a security problem where we
5934 // send data to the keyword server that we shouldn't be.
5935 // Someone needs to clean up keywords in general so we can
5936 // determine on a per url basis if we want keywords
5937 // enabled...this is just a bandaid...
5938 nsAutoCString scheme;
5939 Unused << url->GetScheme(scheme);
5940 if (Preferences::GetBool("keyword.enabled", false) &&
5941 StringBeginsWith(scheme, "http"_ns)) {
5942 bool attemptFixup = false;
5943 nsAutoCString host;
5944 Unused << url->GetHost(host);
5945 if (host.FindChar('.') == kNotFound) {
5946 attemptFixup = true;
5947 } else {
5948 // For domains with dots, we check the public suffix validity.
5949 nsCOMPtr<nsIEffectiveTLDService> tldService =
5950 do_GetService(NS_EFFECTIVETLDSERVICE_CONTRACTID"@mozilla.org/network/effective-tld-service;1");
5951 if (tldService) {
5952 nsAutoCString suffix;
5953 attemptFixup =
5954 NS_SUCCEEDED(tldService->GetKnownPublicSuffix(url, suffix))((bool)(__builtin_expect(!!(!NS_FAILED_impl(tldService->GetKnownPublicSuffix
(url, suffix))), 1)))
&&
5955 suffix.IsEmpty();
5956 }
5957 }
5958 if (attemptFixup) {
5959 nsCOMPtr<nsIURIFixupInfo> info;
5960 // only send non-qualified hosts to the keyword server
5961 if (aOriginalURIString && !aOriginalURIString->IsEmpty()) {
5962 info = KeywordToURI(*aOriginalURIString, aUsePrivateBrowsing);
5963 } else {
5964 //
5965 // If this string was passed through nsStandardURL by
5966 // chance, then it may have been converted from UTF-8 to
5967 // Punycode, which would result in a completely bogus keyword
5968 // query. Here we try to recover the original Unicode
5969 // value, but this is not 100% correct since the value may
5970 // have been normalized per the IDN normalization rules.
5971 //
5972 // Since we don't have access to the exact original string
5973 // that was entered by the user, this will just have to do.
5974 nsAutoCString utf8Host;
5975 mozilla_net_recover_keyword_from_punycode(&host, &utf8Host);
5976 info = KeywordToURI(utf8Host, aUsePrivateBrowsing);
5977 }
5978 if (info) {
5979 info->GetPreferredURI(getter_AddRefs(newURI));
5980 info->GetWasSchemelessInput(outWasSchemelessInput);
5981 if (newURI) {
5982 info->GetKeywordAsSent(keywordAsSent);
5983 info->GetKeywordProviderName(keywordProviderName);
5984 info->GetPostData(getter_AddRefs(newPostData));
5985 }
5986 }
5987 }
5988 }
5989 }
5990
5991 //
5992 // Now try change the address, e.g. turn http://foo into
5993 // http://www.foo.com, and if that doesn't work try https with
5994 // https://foo and https://www.foo.com.
5995 //
5996 if (aStatus == NS_ERROR_UNKNOWN_HOST || aStatus == NS_ERROR_NET_RESET) {
5997 // Skip fixup for anything except a normal document load
5998 // operation on the topframe.
5999 bool doCreateAlternate = aLoadType == LOAD_NORMAL && aIsTopFrame;
6000
6001 if (doCreateAlternate) {
6002 nsCOMPtr<nsILoadInfo> loadInfo = aChannel->LoadInfo();
6003 nsIPrincipal* principal = loadInfo->TriggeringPrincipal();
6004 // Only do this if our channel was loaded directly by the user from the
6005 // URL bar or similar (system principal) and not redirected, because we
6006 // shouldn't be guessing things about links from other sites, or a
6007 // post-redirect URI.
6008 doCreateAlternate = principal && principal->IsSystemPrincipal() &&
6009 loadInfo->RedirectChain().IsEmpty();
6010 }
6011 // Test if keyword lookup produced a new URI or not
6012 if (doCreateAlternate && newURI) {
6013 bool sameURI = false;
6014 url->Equals(newURI, &sameURI);
6015 if (!sameURI) {
6016 // Keyword lookup made a new URI so no need to try
6017 // an alternate one.
6018 doCreateAlternate = false;
6019 }
6020 }
6021 if (doCreateAlternate) {
6022 newURI = nullptr;
6023 newPostData = nullptr;
6024 keywordProviderName.Truncate();
6025 keywordAsSent.Truncate();
6026 nsCOMPtr<nsIURIFixup> uriFixup = components::URIFixup::Service();
6027 if (uriFixup) {
6028 nsCOMPtr<nsIURIFixupInfo> fixupInfo;
6029 uriFixup->GetFixupURIInfo(oldSpec, nsIURIFixup::FIXUP_FLAG_NONE,
6030 getter_AddRefs(fixupInfo));
6031 if (fixupInfo) {
6032 fixupInfo->GetPreferredURI(getter_AddRefs(newURI));
6033 }
6034 }
6035 }
6036 } else if (aStatus == NS_ERROR_CONNECTION_REFUSED &&
6037 Preferences::GetBool("browser.fixup.fallback-to-https", false)) {
6038 // Try HTTPS, since http didn't work
6039 if (SchemeIsHTTP(url)) {
6040 int32_t port = 0;
6041 url->GetPort(&port);
6042
6043 // Fall back to HTTPS only if port is default
6044 if (port == -1) {
6045 newURI = nullptr;
6046 newPostData = nullptr;
6047 Unused << NS_MutateURI(url)
6048 .SetScheme("https"_ns)
6049 .Finalize(getter_AddRefs(newURI));
6050 }
6051 }
6052 }
6053
6054 // If we have a SSL_ERROR_BAD_CERT_DOMAIN error, try adding or removing
6055 // "www." to/from the beginning of the domain name to see if we can avoid
6056 // showing the cert error page. For example, https://example.com ->
6057 // https://www.example.com or https://www.example.com -> https://example.com.
6058 if (aStatus ==
6059 mozilla::psm::GetXPCOMFromNSSError(SSL_ERROR_BAD_CERT_DOMAIN)) {
6060 newPostData = nullptr;
6061 newURI = MaybeFixBadCertDomainErrorURI(aChannel, url);
6062 }
6063
6064 // Did we make a new URI that is different to the old one? If so
6065 // load it.
6066 //
6067 if (newURI) {
6068 // Make sure the new URI is different from the old one,
6069 // otherwise there's little point trying to load it again.
6070 bool sameURI = false;
6071 url->Equals(newURI, &sameURI);
6072 if (!sameURI) {
6073 if (aNewPostData) {
6074 newPostData.forget(aNewPostData);
6075 }
6076 if (aNotifyKeywordSearchLoading) {
6077 // This notification is meant for Firefox Health Report so it
6078 // can increment counts from the search engine
6079 MaybeNotifyKeywordSearchLoading(keywordProviderName, keywordAsSent);
6080 }
6081 return newURI.forget();
6082 }
6083 }
6084
6085 return nullptr;
6086}
6087
6088nsresult nsDocShell::FilterStatusForErrorPage(
6089 nsresult aStatus, nsIChannel* aChannel, uint32_t aLoadType,
6090 bool aIsTopFrame, bool aUseErrorPages,
6091 bool* aSkippedUnknownProtocolNavigation) {
6092 // Errors to be shown only on top-level frames
6093 if ((aStatus == NS_ERROR_UNKNOWN_HOST ||
6094 aStatus == NS_ERROR_CONNECTION_REFUSED ||
6095 aStatus == NS_ERROR_UNKNOWN_PROXY_HOST ||
6096 aStatus == NS_ERROR_PROXY_CONNECTION_REFUSED ||
6097 aStatus == NS_ERROR_PROXY_FORBIDDEN ||
6098 aStatus == NS_ERROR_PROXY_NOT_IMPLEMENTED ||
6099 aStatus == NS_ERROR_PROXY_AUTHENTICATION_FAILED ||
6100 aStatus == NS_ERROR_PROXY_TOO_MANY_REQUESTS ||
6101 aStatus == NS_ERROR_MALFORMED_URI ||
6102 aStatus == NS_ERROR_BLOCKED_BY_POLICY ||
6103 aStatus == NS_ERROR_DOM_COOP_FAILED ||
6104 aStatus == NS_ERROR_DOM_COEP_FAILED) &&
6105 (aIsTopFrame || aUseErrorPages)) {
6106 return aStatus;
6107 }
6108
6109 if (aStatus == NS_ERROR_NET_TIMEOUT ||
6110 aStatus == NS_ERROR_NET_TIMEOUT_EXTERNAL ||
6111 aStatus == NS_ERROR_NET_ERROR_RESPONSE ||
6112 aStatus == NS_ERROR_PROXY_GATEWAY_TIMEOUT ||
6113 aStatus == NS_ERROR_REDIRECT_LOOP ||
6114 aStatus == NS_ERROR_UNKNOWN_SOCKET_TYPE ||
6115 aStatus == NS_ERROR_NET_INTERRUPT || aStatus == NS_ERROR_NET_RESET ||
6116 aStatus == NS_ERROR_PROXY_BAD_GATEWAY || aStatus == NS_ERROR_OFFLINE ||
6117 aStatus == NS_ERROR_MALWARE_URI || aStatus == NS_ERROR_PHISHING_URI ||
6118 aStatus == NS_ERROR_UNWANTED_URI || aStatus == NS_ERROR_HARMFUL_URI ||
6119 aStatus == NS_ERROR_UNSAFE_CONTENT_TYPE ||
6120 aStatus == NS_ERROR_INTERCEPTION_FAILED ||
6121 aStatus == NS_ERROR_NET_INADEQUATE_SECURITY ||
6122 aStatus == NS_ERROR_NET_HTTP2_SENT_GOAWAY ||
6123 aStatus == NS_ERROR_NET_HTTP3_PROTOCOL_ERROR ||
6124 aStatus == NS_ERROR_DOM_BAD_URI || aStatus == NS_ERROR_FILE_NOT_FOUND ||
6125 aStatus == NS_ERROR_FILE_ACCESS_DENIED ||
6126 aStatus == NS_ERROR_CORRUPTED_CONTENT ||
6127 aStatus == NS_ERROR_INVALID_CONTENT_ENCODING ||
6128 NS_ERROR_GET_MODULE(aStatus) == NS_ERROR_MODULE_SECURITY21) {
6129 // Errors to be shown for any frame
6130 return aStatus;
6131 }
6132
6133 if (aStatus == NS_ERROR_UNKNOWN_PROTOCOL) {
6134 // For unknown protocols we only display an error if the load is triggered
6135 // by the browser itself. Showing the error for page-triggered navigations
6136 // causes annoying behavior for users, see bug 1528305.
6137 nsCOMPtr<nsILoadInfo> info = aChannel->LoadInfo();
6138 if (!info->TriggeringPrincipal()->IsSystemPrincipal()) {
6139 if (aSkippedUnknownProtocolNavigation) {
6140 *aSkippedUnknownProtocolNavigation = true;
6141 }
6142 return NS_OK;
6143 }
6144 return aStatus;
6145 }
6146
6147 if (aStatus == NS_ERROR_DOCUMENT_NOT_CACHED) {
6148 // Non-caching channels will simply return NS_ERROR_OFFLINE.
6149 // Caching channels would have to look at their flags to work
6150 // out which error to return. Or we can fix up the error here.
6151 if (!(aLoadType & LOAD_CMD_HISTORY)) {
6152 return NS_ERROR_OFFLINE;
6153 }
6154 return aStatus;
6155 }
6156
6157 return NS_OK;
6158}
6159
6160nsresult nsDocShell::EndPageLoad(nsIWebProgress* aProgress,
6161 nsIChannel* aChannel, nsresult aStatus) {
6162 MOZ_LOG(gDocShellLeakLog, LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = gDocShellLeakLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "DOCSHELL %p EndPageLoad status: %" "x" "\n"
, this, static_cast<uint32_t>(aStatus)); } } while (0)
6163 ("DOCSHELL %p EndPageLoad status: %" PRIx32 "\n", this,do { const ::mozilla::LogModule* moz_real_module = gDocShellLeakLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "DOCSHELL %p EndPageLoad status: %" "x" "\n"
, this, static_cast<uint32_t>(aStatus)); } } while (0)
6164 static_cast<uint32_t>(aStatus)))do { const ::mozilla::LogModule* moz_real_module = gDocShellLeakLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "DOCSHELL %p EndPageLoad status: %" "x" "\n"
, this, static_cast<uint32_t>(aStatus)); } } while (0)
;
6165 if (!aChannel) {
6166 return NS_ERROR_NULL_POINTER;
6167 }
6168
6169 // Make sure to discard the initial client if we never created the initial
6170 // about:blank document. Do this before possibly returning from the method
6171 // due to an error.
6172 mInitialClientSource.reset();
6173
6174 nsCOMPtr<nsIConsoleReportCollector> reporter = do_QueryInterface(aChannel);
6175 if (reporter) {
6176 nsCOMPtr<nsILoadGroup> loadGroup;
6177 aChannel->GetLoadGroup(getter_AddRefs(loadGroup));
6178 if (loadGroup) {
6179 reporter->FlushConsoleReports(loadGroup);
6180 } else {
6181 reporter->FlushConsoleReports(GetDocument());
6182 }
6183 }
6184
6185 nsCOMPtr<nsIURI> url;
6186 nsresult rv = aChannel->GetURI(getter_AddRefs(url));
6187 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
6188 return rv;
6189 }
6190
6191 nsCOMPtr<nsITimedChannel> timingChannel = do_QueryInterface(aChannel);
6192 if (timingChannel) {
6193 TimeStamp channelCreationTime;
6194 rv = timingChannel->GetChannelCreation(&channelCreationTime);
6195 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && !channelCreationTime.IsNull()) {
6196 glean::performance_page::total_content_page_load.AccumulateRawDuration(
6197 TimeStamp::Now() - channelCreationTime);
6198 }
6199 }
6200
6201 // Timing is picked up by the window, we don't need it anymore
6202 mTiming = nullptr;
6203
6204 // clean up reload state for meta charset
6205 if (eCharsetReloadRequested == mCharsetReloadState) {
6206 mCharsetReloadState = eCharsetReloadStopOrigional;
6207 } else {
6208 mCharsetReloadState = eCharsetReloadInit;
6209 }
6210
6211 // Save a pointer to the currently-loading history entry.
6212 // nsDocShell::EndPageLoad will clear mLSHE, but we may need this history
6213 // entry further down in this method.
6214 nsCOMPtr<nsISHEntry> loadingSHE = mLSHE;
6215 mozilla::Unused << loadingSHE; // XXX: Not sure if we need this anymore
6216
6217 //
6218 // one of many safeguards that prevent death and destruction if
6219 // someone is so very very rude as to bring this window down
6220 // during this load handler.
6221 //
6222 nsCOMPtr<nsIDocShell> kungFuDeathGrip(this);
6223
6224 // Notify the DocumentViewer that the Document has finished loading. This
6225 // will cause any OnLoad(...) and PopState(...) handlers to fire.
6226 if (!mEODForCurrentDocument && mDocumentViewer) {
6227 mIsExecutingOnLoadHandler = true;
6228 nsCOMPtr<nsIDocumentViewer> viewer = mDocumentViewer;
6229 viewer->LoadComplete(aStatus);
6230 mIsExecutingOnLoadHandler = false;
6231
6232 mEODForCurrentDocument = true;
6233 }
6234 /* Check if the httpChannel has any cache-control related response headers,
6235 * like no-store, no-cache. If so, update SHEntry so that
6236 * when a user goes back/forward to this page, we appropriately do
6237 * form value restoration or load from server.
6238 */
6239 nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(aChannel));
6240 if (!httpChannel) {
6241 // HttpChannel could be hiding underneath a Multipart channel.
6242 GetHttpChannel(aChannel, getter_AddRefs(httpChannel));
6243 }
6244
6245 if (httpChannel) {
6246 // figure out if SH should be saving layout state.
6247 bool discardLayoutState = ShouldDiscardLayoutState(httpChannel);
6248 if (mLSHE && discardLayoutState && (mLoadType & LOAD_CMD_NORMAL) &&
6249 (mLoadType != LOAD_BYPASS_HISTORY) && (mLoadType != LOAD_ERROR_PAGE)) {
6250 mLSHE->SetSaveLayoutStateFlag(false);
6251 }
6252 }
6253
6254 // Clear mLSHE after calling the onLoadHandlers. This way, if the
6255 // onLoadHandler tries to load something different in
6256 // itself or one of its children, we can deal with it appropriately.
6257 if (mLSHE) {
6258 mLSHE->SetLoadType(LOAD_HISTORY);
6259
6260 // Clear the mLSHE reference to indicate document loading is done one
6261 // way or another.
6262 SetHistoryEntryAndUpdateBC(Some(nullptr), Nothing());
6263 }
6264 mActiveEntryIsLoadingFromSessionHistory = false;
6265
6266 // if there's a refresh header in the channel, this method
6267 // will set it up for us.
6268 if (mBrowsingContext->IsActive() || !mDisableMetaRefreshWhenInactive)
6269 RefreshURIFromQueue();
6270
6271 // Test whether this is the top frame or a subframe
6272 bool isTopFrame = mBrowsingContext->IsTop();
6273
6274 bool hadErrorStatus = false;
6275 // If status code indicates an error it means that DocumentChannel already
6276 // tried to fixup the uri and failed. Throw an error dialog box here.
6277 if (NS_FAILED(aStatus)((bool)(__builtin_expect(!!(NS_FAILED_impl(aStatus)), 0)))) {
6278 // If we got CONTENT_BLOCKED from EndPageLoad, then we need to fire
6279 // the error event to our embedder, since tests are relying on this.
6280 // The error event is usually fired by the caller of InternalLoad, but
6281 // this particular error can happen asynchronously.
6282 // Bug 1629201 is filed for having much clearer decision making around
6283 // which cases need error events.
6284 bool fireFrameErrorEvent = (aStatus == NS_ERROR_CONTENT_BLOCKED_SHOW_ALT ||
6285 aStatus == NS_ERROR_CONTENT_BLOCKED);
6286 UnblockEmbedderLoadEventForFailure(fireFrameErrorEvent);
6287
6288 bool skippedUnknownProtocolNavigation = false;
6289 aStatus = FilterStatusForErrorPage(aStatus, aChannel, mLoadType, isTopFrame,
6290 mBrowsingContext->GetUseErrorPages(),
6291 &skippedUnknownProtocolNavigation);
6292 hadErrorStatus = true;
6293 if (NS_FAILED(aStatus)((bool)(__builtin_expect(!!(NS_FAILED_impl(aStatus)), 0)))) {
6294 if (!mIsBeingDestroyed) {
6295 DisplayLoadError(aStatus, url, nullptr, aChannel);
6296 }
6297 } else if (skippedUnknownProtocolNavigation) {
6298 nsAutoCString sanitized;
6299 nsTArray<nsString> params;
6300 if (NS_SUCCEEDED(NS_GetSanitizedURIStringFromURI(url, sanitized))((bool)(__builtin_expect(!!(!NS_FAILED_impl(NS_GetSanitizedURIStringFromURI
(url, sanitized))), 1)))
) {
6301 params.AppendElement(NS_ConvertUTF8toUTF16(sanitized));
6302 } else {
6303 params.AppendElement(u"(unknown uri)"_ns);
6304 }
6305 nsContentUtils::ReportToConsole(
6306 nsIScriptError::warningFlag, "DOM"_ns, GetExtantDocument(),
6307 nsContentUtils::eDOM_PROPERTIES, "UnknownProtocolNavigationPrevented",
6308 params);
6309 }
6310 } else {
6311 // If we have a host
6312 nsCOMPtr<nsILoadInfo> loadInfo = aChannel->LoadInfo();
6313 PredictorLearnRedirect(url, aChannel, loadInfo->GetOriginAttributes());
6314 }
6315
6316 if (hadErrorStatus) {
6317 // Don't send session store updates if the reason EndPageLoad was called is
6318 // because we are process switching. Sometimes the update takes too long and
6319 // incorrectly overrides session store data from the following load.
6320 return NS_OK;
6321 }
6322 if (SessionStorePlatformCollection()) {
6323 if (WindowContext* windowContext =
6324 mBrowsingContext->GetCurrentWindowContext()) {
6325 using Change = SessionStoreChangeListener::Change;
6326
6327 // We've finished loading the page and now we want to collect all the
6328 // session store state that the page is initialized with.
6329 SessionStoreChangeListener::CollectSessionStoreData(
6330 windowContext,
6331 EnumSet<Change>(Change::Input, Change::Scroll, Change::SessionHistory,
6332 Change::WireFrame));
6333 }
6334 }
6335
6336 return NS_OK;
6337}
6338
6339//*****************************************************************************
6340// nsDocShell: Content Viewer Management
6341//*****************************************************************************
6342
6343nsresult nsDocShell::EnsureDocumentViewer() {
6344 if (mDocumentViewer) {
6345 return NS_OK;
6346 }
6347 if (mIsBeingDestroyed) {
6348 return NS_ERROR_FAILURE;
6349 }
6350
6351 nsCOMPtr<nsIContentSecurityPolicy> cspToInheritForAboutBlank;
6352 nsCOMPtr<nsIURI> baseURI;
6353 nsIPrincipal* principal = GetInheritedPrincipal(false);
6354 nsIPrincipal* partitionedPrincipal = GetInheritedPrincipal(false, true);
6355
6356 nsCOMPtr<nsIDocShellTreeItem> parentItem;
6357 GetInProcessSameTypeParent(getter_AddRefs(parentItem));
6358 if (parentItem) {
6359 if (nsCOMPtr<nsPIDOMWindowOuter> domWin = GetWindow()) {
6360 nsCOMPtr<Element> parentElement = domWin->GetFrameElementInternal();
6361 if (parentElement) {
6362 baseURI = parentElement->GetBaseURI();
6363 cspToInheritForAboutBlank = parentElement->GetCsp();
6364 }
6365 }
6366 }
6367
6368 nsresult rv = CreateAboutBlankDocumentViewer(
6369 principal, partitionedPrincipal, cspToInheritForAboutBlank, baseURI,
6370 /* aIsInitialDocument */ true);
6371
6372 NS_ENSURE_STATE(mDocumentViewer)do { if ((__builtin_expect(!!(!(mDocumentViewer)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "mDocumentViewer" ") failed"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 6372); return NS_ERROR_UNEXPECTED; } } while (false)
;
6373
6374 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
6375 RefPtr<Document> doc(GetDocument());
6376 MOZ_ASSERT(doc,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(doc)>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(doc))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("doc" " (" "Should have doc if CreateAboutBlankDocumentViewer "
"succeeded!" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 6378); AnnotateMozCrashReason("MOZ_ASSERT" "(" "doc" ") (" "Should have doc if CreateAboutBlankDocumentViewer "
"succeeded!" ")"); do { *((volatile int*)__null) = 6378; __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
6377 "Should have doc if CreateAboutBlankDocumentViewer "do { static_assert( mozilla::detail::AssertionConditionType<
decltype(doc)>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(doc))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("doc" " (" "Should have doc if CreateAboutBlankDocumentViewer "
"succeeded!" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 6378); AnnotateMozCrashReason("MOZ_ASSERT" "(" "doc" ") (" "Should have doc if CreateAboutBlankDocumentViewer "
"succeeded!" ")"); do { *((volatile int*)__null) = 6378; __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
6378 "succeeded!")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(doc)>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(doc))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("doc" " (" "Should have doc if CreateAboutBlankDocumentViewer "
"succeeded!" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 6378); AnnotateMozCrashReason("MOZ_ASSERT" "(" "doc" ") (" "Should have doc if CreateAboutBlankDocumentViewer "
"succeeded!" ")"); do { *((volatile int*)__null) = 6378; __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
;
6379 MOZ_ASSERT(doc->IsInitialDocument(), "Document should be initial document")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(doc->IsInitialDocument())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(doc->IsInitialDocument())
)), 0))) { do { } while (false); MOZ_ReportAssertionFailure("doc->IsInitialDocument()"
" (" "Document should be initial document" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 6379); AnnotateMozCrashReason("MOZ_ASSERT" "(" "doc->IsInitialDocument()"
") (" "Document should be initial document" ")"); do { *((volatile
int*)__null) = 6379; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
6380
6381 // Documents created using EnsureDocumentViewer may be transient
6382 // placeholders created by framescripts before content has a
6383 // chance to load. In some cases, window.open(..., "noopener")
6384 // will create such a document and then synchronously tear it
6385 // down, firing a "pagehide" event. Doing so violates our
6386 // assertions about DocGroups. It's easier to silence the
6387 // assertion here than to avoid creating the extra document.
6388 doc->IgnoreDocGroupMismatches();
6389 }
6390
6391 return rv;
6392}
6393
6394nsresult nsDocShell::CreateAboutBlankDocumentViewer(
6395 nsIPrincipal* aPrincipal, nsIPrincipal* aPartitionedPrincipal,
6396 nsIContentSecurityPolicy* aCSP, nsIURI* aBaseURI, bool aIsInitialDocument,
6397 const Maybe<nsILoadInfo::CrossOriginEmbedderPolicy>& aCOEP,
6398 bool aTryToSaveOldPresentation, bool aCheckPermitUnload,
6399 WindowGlobalChild* aActor) {
6400 RefPtr<Document> blankDoc;
6401 nsCOMPtr<nsIDocumentViewer> viewer;
6402 nsresult rv = NS_ERROR_FAILURE;
6403
6404 PROFILER_MARKER_UNTYPED("CreateAboutBlankDocumentViewer", DOM,do { ; do { if (profiler_is_collecting_markers()) { ::profiler_add_marker_impl
("CreateAboutBlankDocumentViewer", ::geckoprofiler::category::
DOM, MarkerStack::Capture()); } } while (false); } while (false
)
6405 MarkerStack::Capture())do { ; do { if (profiler_is_collecting_markers()) { ::profiler_add_marker_impl
("CreateAboutBlankDocumentViewer", ::geckoprofiler::category::
DOM, MarkerStack::Capture()); } } while (false); } while (false
)
;
6406
6407 MOZ_ASSERT_IF(aActor, aActor->DocumentPrincipal() == aPrincipal)do { if (aActor) { do { static_assert( mozilla::detail::AssertionConditionType
<decltype(aActor->DocumentPrincipal() == aPrincipal)>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(aActor->DocumentPrincipal() == aPrincipal))), 0))
) { do { } while (false); MOZ_ReportAssertionFailure("aActor->DocumentPrincipal() == aPrincipal"
, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 6407); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aActor->DocumentPrincipal() == aPrincipal"
")"); do { *((volatile int*)__null) = 6407; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
6408
6409 /* mCreatingDocument should never be true at this point. However, it's
6410 a theoretical possibility. We want to know about it and make it stop,
6411 and this sounds like a job for an assertion. */
6412 NS_ASSERTION(!mCreatingDocument,do { if (!(!mCreatingDocument)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "infinite(?) loop creating document averted", "!mCreatingDocument"
, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 6413); MOZ_PretendNoReturn(); } } while (0)
6413 "infinite(?) loop creating document averted")do { if (!(!mCreatingDocument)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "infinite(?) loop creating document averted", "!mCreatingDocument"
, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 6413); MOZ_PretendNoReturn(); } } while (0)
;
6414 if (mCreatingDocument) {
6415 return NS_ERROR_FAILURE;
6416 }
6417
6418 if (!mBrowsingContext->AncestorsAreCurrent() ||
6419 mBrowsingContext->IsInBFCache()) {
6420 mBrowsingContext->RemoveRootFromBFCacheSync();
6421 return NS_ERROR_NOT_AVAILABLE;
6422 }
6423
6424 // mDocumentViewer->PermitUnload may release |this| docshell.
6425 nsCOMPtr<nsIDocShell> kungFuDeathGrip(this);
6426
6427 AutoRestore<bool> creatingDocument(mCreatingDocument);
6428 mCreatingDocument = true;
6429
6430 if (aPrincipal && !aPrincipal->IsSystemPrincipal() &&
6431 mItemType != typeChrome) {
6432 MOZ_ASSERT(aPrincipal->OriginAttributesRef() ==do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aPrincipal->OriginAttributesRef() == mBrowsingContext
->OriginAttributesRef())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aPrincipal->OriginAttributesRef
() == mBrowsingContext->OriginAttributesRef()))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("aPrincipal->OriginAttributesRef() == mBrowsingContext->OriginAttributesRef()"
, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 6433); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPrincipal->OriginAttributesRef() == mBrowsingContext->OriginAttributesRef()"
")"); do { *((volatile int*)__null) = 6433; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6433 mBrowsingContext->OriginAttributesRef())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aPrincipal->OriginAttributesRef() == mBrowsingContext
->OriginAttributesRef())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aPrincipal->OriginAttributesRef
() == mBrowsingContext->OriginAttributesRef()))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("aPrincipal->OriginAttributesRef() == mBrowsingContext->OriginAttributesRef()"
, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 6433); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPrincipal->OriginAttributesRef() == mBrowsingContext->OriginAttributesRef()"
")"); do { *((volatile int*)__null) = 6433; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6434 }
6435
6436 // Make sure timing is created. But first record whether we had it
6437 // already, so we don't clobber the timing for an in-progress load.
6438 bool hadTiming = mTiming;
6439 bool toBeReset = MaybeInitTiming();
6440 if (mDocumentViewer) {
6441 if (aCheckPermitUnload) {
6442 // We've got a content viewer already. Make sure the user
6443 // permits us to discard the current document and replace it
6444 // with about:blank. And also ensure we fire the unload events
6445 // in the current document.
6446
6447 // Unload gets fired first for
6448 // document loaded from the session history.
6449 mTiming->NotifyBeforeUnload();
6450
6451 bool okToUnload;
6452 rv = mDocumentViewer->PermitUnload(&okToUnload);
6453
6454 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && !okToUnload) {
6455 // The user chose not to unload the page, interrupt the load.
6456 MaybeResetInitTiming(toBeReset);
6457 return NS_ERROR_FAILURE;
6458 }
6459 if (mTiming) {
6460 mTiming->NotifyUnloadAccepted(mCurrentURI);
6461 }
6462 }
6463
6464 mSavingOldViewer =
6465 aTryToSaveOldPresentation &&
6466 CanSavePresentation(LOAD_NORMAL, nullptr, nullptr,
6467 /* aReportBFCacheComboTelemetry */ true);
6468
6469 // Make sure to blow away our mLoadingURI just in case. No loads
6470 // from inside this pagehide.
6471 mLoadingURI = nullptr;
6472
6473 // Stop any in-progress loading, so that we don't accidentally trigger any
6474 // PageShow notifications from Embed() interrupting our loading below.
6475 Stop();
6476
6477 // Notify the current document that it is about to be unloaded!!
6478 //
6479 // It is important to fire the unload() notification *before* any state
6480 // is changed within the DocShell - otherwise, javascript will get the
6481 // wrong information :-(
6482 //
6483 (void)FirePageHideNotification(!mSavingOldViewer);
6484 // pagehide notification might destroy this docshell.
6485 if (mIsBeingDestroyed) {
6486 return NS_ERROR_DOCSHELL_DYING;
6487 }
6488 }
6489
6490 // Now make sure we don't think we're in the middle of firing unload after
6491 // this point. This will make us fire unload when the about:blank document
6492 // unloads... but that's ok, more or less. Would be nice if it fired load
6493 // too, of course.
6494 mFiredUnloadEvent = false;
6495
6496 nsCOMPtr<nsIDocumentLoaderFactory> docFactory =
6497 nsContentUtils::FindInternalDocumentViewer("text/html"_ns);
6498
6499 if (docFactory) {
6500 nsCOMPtr<nsIPrincipal> principal, partitionedPrincipal;
6501 const uint32_t sandboxFlags =
6502 mBrowsingContext->GetHasLoadedNonInitialDocument()
6503 ? mBrowsingContext->GetSandboxFlags()
6504 : mBrowsingContext->GetInitialSandboxFlags();
6505 // If we're sandboxed, then create a new null principal. We skip
6506 // this if we're being created from WindowGlobalChild, since in
6507 // that case we already have a null principal if required.
6508 // We can't compare againt the BrowsingContext sandbox flag, since
6509 // the value was taken when the load initiated and may have since
6510 // changed.
6511 if ((sandboxFlags & SANDBOXED_ORIGIN) && !aActor) {
6512 if (aPrincipal) {
6513 principal = NullPrincipal::CreateWithInheritedAttributes(aPrincipal);
6514 } else {
6515 principal = NullPrincipal::Create(GetOriginAttributes());
6516 }
6517 partitionedPrincipal = principal;
6518 } else {
6519 principal = aPrincipal;
6520 partitionedPrincipal = aPartitionedPrincipal;
6521 }
6522
6523 // We cannot get the foreign partitioned prinicpal for the initial
6524 // about:blank page. So, we change to check if we need to use the
6525 // partitioned principal for the service worker here.
6526 MaybeCreateInitialClientSource(
6527 StoragePrincipalHelper::ShouldUsePartitionPrincipalForServiceWorker(
6528 this)
6529 ? partitionedPrincipal
6530 : principal);
6531
6532 // generate (about:blank) document to load
6533 blankDoc = nsContentDLF::CreateBlankDocument(mLoadGroup, principal,
6534 partitionedPrincipal, this);
6535 if (blankDoc) {
6536 // Hack: manually set the CSP for the new document
6537 // Please create an actual copy of the CSP (do not share the same
6538 // reference) otherwise appending a new policy within the new
6539 // document will be incorrectly propagated to the opening doc.
6540 if (aCSP) {
6541 RefPtr<nsCSPContext> cspToInherit = new nsCSPContext();
6542 cspToInherit->InitFromOther(static_cast<nsCSPContext*>(aCSP));
6543 blankDoc->SetCsp(cspToInherit);
6544 }
6545
6546 blankDoc->SetIsInitialDocument(aIsInitialDocument);
6547
6548 blankDoc->SetEmbedderPolicy(aCOEP);
6549
6550 // Hack: set the base URI manually, since this document never
6551 // got Reset() with a channel.
6552 blankDoc->SetBaseURI(aBaseURI);
6553
6554 // Copy our sandbox flags to the document. These are immutable
6555 // after being set here.
6556 blankDoc->SetSandboxFlags(sandboxFlags);
6557
6558 // create a content viewer for us and the new document
6559 docFactory->CreateInstanceForDocument(
6560 NS_ISUPPORTS_CAST(nsIDocShell*, this)static_cast<nsISupports*>(static_cast<nsIDocShell*>
(this))
, blankDoc, "view",
6561 getter_AddRefs(viewer));
6562
6563 // hook 'em up
6564 if (viewer) {
6565 viewer->SetContainer(this);
6566 rv = Embed(viewer, aActor, true, false, nullptr, mCurrentURI);
6567 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/docshell/base/nsDocShell.cpp"
, 6567); return rv; } } while (false)
;
6568
6569 SetCurrentURI(blankDoc->GetDocumentURI(), nullptr,
6570 /* aFireLocationChange */ true,
6571 /* aIsInitialAboutBlank */ true,
6572 /* aLocationFlags */ 0);
6573 rv = mIsBeingDestroyed ? NS_ERROR_NOT_AVAILABLE : NS_OK;
6574 }
6575
6576 if (Element* embedderElement = blankDoc->GetEmbedderElement()) {
6577 blankDoc->InitFeaturePolicy(AsVariant(embedderElement));
6578 } else {
6579 blankDoc->InitFeaturePolicy(AsVariant(Nothing{}));
6580 }
6581 }
6582 }
6583
6584 // The transient about:blank viewer doesn't have a session history entry.
6585 SetHistoryEntryAndUpdateBC(Nothing(), Some(nullptr));
6586
6587 // Clear out our mTiming like we would in EndPageLoad, if we didn't
6588 // have one before entering this function.
6589 if (!hadTiming) {
6590 mTiming = nullptr;
6591 mBlankTiming = true;
6592 }
6593
6594 return rv;
6595}
6596
6597NS_IMETHODIMPnsresult
6598nsDocShell::CreateAboutBlankDocumentViewer(nsIPrincipal* aPrincipal,
6599 nsIPrincipal* aPartitionedPrincipal,
6600 nsIContentSecurityPolicy* aCSP) {
6601 return CreateAboutBlankDocumentViewer(aPrincipal, aPartitionedPrincipal, aCSP,
6602 nullptr,
6603 /* aIsInitialDocument */ false);
6604}
6605
6606nsresult nsDocShell::CreateDocumentViewerForActor(
6607 WindowGlobalChild* aWindowActor) {
6608 MOZ_ASSERT(aWindowActor)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aWindowActor)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aWindowActor))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("aWindowActor", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 6608); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aWindowActor"
")"); do { *((volatile int*)__null) = 6608; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6609
6610 // FIXME: WindowGlobalChild should provide the PartitionedPrincipal.
6611 // FIXME: We may want to support non-initial documents here.
6612 nsresult rv = CreateAboutBlankDocumentViewer(
6613 aWindowActor->DocumentPrincipal(), aWindowActor->DocumentPrincipal(),
6614 /* aCsp */ nullptr,
6615 /* aBaseURI */ nullptr,
6616 /* aIsInitialDocument */ true,
6617 /* aCOEP */ Nothing(),
6618 /* aTryToSaveOldPresentation */ true,
6619 /* aCheckPermitUnload */ true, aWindowActor);
6620#ifdef DEBUG1
6621 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
6622 RefPtr<Document> doc(GetDocument());
6623 MOZ_ASSERT(do { static_assert( mozilla::detail::AssertionConditionType<
decltype(doc)>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(doc))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("doc" " (" "Should have a document if CreateAboutBlankDocumentViewer succeeded"
")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 6625); AnnotateMozCrashReason("MOZ_ASSERT" "(" "doc" ") (" "Should have a document if CreateAboutBlankDocumentViewer succeeded"
")"); do { *((volatile int*)__null) = 6625; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6624 doc,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(doc)>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(doc))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("doc" " (" "Should have a document if CreateAboutBlankDocumentViewer succeeded"
")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 6625); AnnotateMozCrashReason("MOZ_ASSERT" "(" "doc" ") (" "Should have a document if CreateAboutBlankDocumentViewer succeeded"
")"); do { *((volatile int*)__null) = 6625; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6625 "Should have a document if CreateAboutBlankDocumentViewer succeeded")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(doc)>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(doc))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("doc" " (" "Should have a document if CreateAboutBlankDocumentViewer succeeded"
")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 6625); AnnotateMozCrashReason("MOZ_ASSERT" "(" "doc" ") (" "Should have a document if CreateAboutBlankDocumentViewer succeeded"
")"); do { *((volatile int*)__null) = 6625; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6626 MOZ_ASSERT(doc->GetOwnerGlobal() == aWindowActor->GetWindowGlobal(),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(doc->GetOwnerGlobal() == aWindowActor->GetWindowGlobal
())>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(doc->GetOwnerGlobal() == aWindowActor->GetWindowGlobal
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("doc->GetOwnerGlobal() == aWindowActor->GetWindowGlobal()"
" (" "New document should be in the same global as our actor"
")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 6627); AnnotateMozCrashReason("MOZ_ASSERT" "(" "doc->GetOwnerGlobal() == aWindowActor->GetWindowGlobal()"
") (" "New document should be in the same global as our actor"
")"); do { *((volatile int*)__null) = 6627; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6627 "New document should be in the same global as our actor")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(doc->GetOwnerGlobal() == aWindowActor->GetWindowGlobal
())>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(doc->GetOwnerGlobal() == aWindowActor->GetWindowGlobal
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("doc->GetOwnerGlobal() == aWindowActor->GetWindowGlobal()"
" (" "New document should be in the same global as our actor"
")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 6627); AnnotateMozCrashReason("MOZ_ASSERT" "(" "doc->GetOwnerGlobal() == aWindowActor->GetWindowGlobal()"
") (" "New document should be in the same global as our actor"
")"); do { *((volatile int*)__null) = 6627; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6628 MOZ_ASSERT(doc->IsInitialDocument(),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(doc->IsInitialDocument())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(doc->IsInitialDocument())
)), 0))) { do { } while (false); MOZ_ReportAssertionFailure("doc->IsInitialDocument()"
" (" "New document should be an initial document" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 6629); AnnotateMozCrashReason("MOZ_ASSERT" "(" "doc->IsInitialDocument()"
") (" "New document should be an initial document" ")"); do {
*((volatile int*)__null) = 6629; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
6629 "New document should be an initial document")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(doc->IsInitialDocument())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(doc->IsInitialDocument())
)), 0))) { do { } while (false); MOZ_ReportAssertionFailure("doc->IsInitialDocument()"
" (" "New document should be an initial document" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 6629); AnnotateMozCrashReason("MOZ_ASSERT" "(" "doc->IsInitialDocument()"
") (" "New document should be an initial document" ")"); do {
*((volatile int*)__null) = 6629; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
6630 }
6631#endif
6632
6633 return rv;
6634}
6635
6636bool nsDocShell::CanSavePresentation(uint32_t aLoadType,
6637 nsIRequest* aNewRequest,
6638 Document* aNewDocument,
6639 bool aReportBFCacheComboTelemetry) {
6640 if (!mOSHE) {
6641 return false; // no entry to save into
6642 }
6643
6644 MOZ_ASSERT(!mozilla::SessionHistoryInParent(),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mozilla::SessionHistoryInParent())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mozilla::SessionHistoryInParent
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!mozilla::SessionHistoryInParent()" " (" "mOSHE cannot be non-null with SHIP"
")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 6645); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mozilla::SessionHistoryInParent()"
") (" "mOSHE cannot be non-null with SHIP" ")"); do { *((volatile
int*)__null) = 6645; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
6645 "mOSHE cannot be non-null with SHIP")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mozilla::SessionHistoryInParent())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mozilla::SessionHistoryInParent
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!mozilla::SessionHistoryInParent()" " (" "mOSHE cannot be non-null with SHIP"
")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 6645); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mozilla::SessionHistoryInParent()"
") (" "mOSHE cannot be non-null with SHIP" ")"); do { *((volatile
int*)__null) = 6645; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
6646 nsCOMPtr<nsIDocumentViewer> viewer = mOSHE->GetDocumentViewer();
6647 if (viewer) {
6648 NS_WARNING("mOSHE already has a content viewer!")NS_DebugBreak(NS_DEBUG_WARNING, "mOSHE already has a content viewer!"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 6648)
;
6649 return false;
6650 }
6651
6652 // Only save presentation for "normal" loads and link loads. Anything else
6653 // probably wants to refetch the page, so caching the old presentation
6654 // would be incorrect.
6655 if (aLoadType != LOAD_NORMAL && aLoadType != LOAD_HISTORY &&
6656 aLoadType != LOAD_LINK && aLoadType != LOAD_STOP_CONTENT &&
6657 aLoadType != LOAD_STOP_CONTENT_AND_REPLACE &&
6658 aLoadType != LOAD_ERROR_PAGE) {
6659 return false;
6660 }
6661
6662 // If the session history entry has the saveLayoutState flag set to false,
6663 // then we should not cache the presentation.
6664 if (!mOSHE->GetSaveLayoutStateFlag()) {
6665 return false;
6666 }
6667
6668 // If the document is not done loading, don't cache it.
6669 if (!mScriptGlobal || mScriptGlobal->IsLoading()) {
6670 MOZ_LOG(gPageCacheLog, mozilla::LogLevel::Verbose,do { const ::mozilla::LogModule* moz_real_module = gPageCacheLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Verbose)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Verbose, "Blocked due to document still loading"
); } } while (0)
6671 ("Blocked due to document still loading"))do { const ::mozilla::LogModule* moz_real_module = gPageCacheLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Verbose)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Verbose, "Blocked due to document still loading"
); } } while (0)
;
6672 return false;
6673 }
6674
6675 if (mScriptGlobal->WouldReuseInnerWindow(aNewDocument)) {
6676 return false;
6677 }
6678
6679 // Avoid doing the work of saving the presentation state in the case where
6680 // the content viewer cache is disabled.
6681 if (nsSHistory::GetMaxTotalViewers() == 0) {
6682 return false;
6683 }
6684
6685 // Don't cache the content viewer if we're in a subframe.
6686 if (mBrowsingContext->GetParent()) {
6687 return false; // this is a subframe load
6688 }
6689
6690 // If the document does not want its presentation cached, then don't.
6691 RefPtr<Document> doc = mScriptGlobal->GetExtantDoc();
6692
6693 uint32_t bfCacheCombo = 0;
6694 bool canSavePresentation =
6695 doc->CanSavePresentation(aNewRequest, bfCacheCombo, true);
6696 MOZ_ASSERT_IF(canSavePresentation, bfCacheCombo == 0)do { if (canSavePresentation) { do { static_assert( mozilla::
detail::AssertionConditionType<decltype(bfCacheCombo == 0)
>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(bfCacheCombo == 0))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("bfCacheCombo == 0", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 6696); AnnotateMozCrashReason("MOZ_ASSERT" "(" "bfCacheCombo == 0"
")"); do { *((volatile int*)__null) = 6696; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
6697 if (canSavePresentation && doc->IsTopLevelContentDocument()) {
6698 auto* browsingContextGroup = mBrowsingContext->Group();
6699 nsTArray<RefPtr<BrowsingContext>>& topLevelContext =
6700 browsingContextGroup->Toplevels();
6701
6702 for (const auto& browsingContext : topLevelContext) {
6703 if (browsingContext != mBrowsingContext) {
6704 if (StaticPrefs::docshell_shistory_bfcache_require_no_opener()) {
6705 canSavePresentation = false;
6706 }
6707 bfCacheCombo |= BFCacheStatus::NOT_ONLY_TOPLEVEL_IN_BCG;
6708 break;
6709 }
6710 }
6711 }
6712
6713 if (aReportBFCacheComboTelemetry) {
6714 ReportBFCacheComboTelemetry(bfCacheCombo);
6715 }
6716 return doc && canSavePresentation;
6717}
6718
6719/* static */
6720void nsDocShell::ReportBFCacheComboTelemetry(uint32_t aCombo) {
6721 // There are 11 possible reasons to make a request fails to use BFCache
6722 // (see BFCacheStatus in dom/base/Document.h), and we'd like to record
6723 // the common combinations for reasons which make requests fail to use
6724 // BFCache. These combinations are generated based on some local browsings,
6725 // we need to adjust them when necessary.
6726 enum BFCacheStatusCombo : uint32_t {
6727 BFCACHE_SUCCESS,
6728 NOT_ONLY_TOPLEVEL = mozilla::dom::BFCacheStatus::NOT_ONLY_TOPLEVEL_IN_BCG,
6729 // If both unload and beforeunload listeners are presented, it'll be
6730 // recorded as unload
6731 UNLOAD = mozilla::dom::BFCacheStatus::UNLOAD_LISTENER,
6732 UNLOAD_REQUEST = mozilla::dom::BFCacheStatus::UNLOAD_LISTENER |
6733 mozilla::dom::BFCacheStatus::REQUEST,
6734 REQUEST = mozilla::dom::BFCacheStatus::REQUEST,
6735 UNLOAD_REQUEST_PEER = mozilla::dom::BFCacheStatus::UNLOAD_LISTENER |
6736 mozilla::dom::BFCacheStatus::REQUEST |
6737 mozilla::dom::BFCacheStatus::ACTIVE_PEER_CONNECTION,
6738 UNLOAD_REQUEST_PEER_MSE =
6739 mozilla::dom::BFCacheStatus::UNLOAD_LISTENER |
6740 mozilla::dom::BFCacheStatus::REQUEST |
6741 mozilla::dom::BFCacheStatus::ACTIVE_PEER_CONNECTION |
6742 mozilla::dom::BFCacheStatus::CONTAINS_MSE_CONTENT,
6743 UNLOAD_REQUEST_MSE = mozilla::dom::BFCacheStatus::UNLOAD_LISTENER |
6744 mozilla::dom::BFCacheStatus::REQUEST |
6745 mozilla::dom::BFCacheStatus::CONTAINS_MSE_CONTENT,
6746 SUSPENDED_UNLOAD_REQUEST_PEER =
6747 mozilla::dom::BFCacheStatus::SUSPENDED |
6748 mozilla::dom::BFCacheStatus::UNLOAD_LISTENER |
6749 mozilla::dom::BFCacheStatus::REQUEST |
6750 mozilla::dom::BFCacheStatus::ACTIVE_PEER_CONNECTION,
6751 REMOTE_SUBFRAMES = mozilla::dom::BFCacheStatus::CONTAINS_REMOTE_SUBFRAMES,
6752 BEFOREUNLOAD = mozilla::dom::BFCacheStatus::BEFOREUNLOAD_LISTENER,
6753 };
6754
6755 // Beforeunload is recorded as a blocker only if it is the only one to block
6756 // bfcache.
6757 if (aCombo != mozilla::dom::BFCacheStatus::BEFOREUNLOAD_LISTENER) {
6758 aCombo &= ~mozilla::dom::BFCacheStatus::BEFOREUNLOAD_LISTENER;
6759 }
6760 switch (aCombo) {
6761 case BFCACHE_SUCCESS:
6762 Telemetry::AccumulateCategorical(
6763 Telemetry::LABELS_BFCACHE_COMBO::BFCache_Success);
6764 break;
6765 case NOT_ONLY_TOPLEVEL:
6766 if (StaticPrefs::docshell_shistory_bfcache_require_no_opener()) {
6767 Telemetry::AccumulateCategorical(
6768 Telemetry::LABELS_BFCACHE_COMBO::Other);
6769 break;
6770 }
6771 Telemetry::AccumulateCategorical(
6772 Telemetry::LABELS_BFCACHE_COMBO::BFCache_Success);
6773 Telemetry::AccumulateCategorical(
6774 Telemetry::LABELS_BFCACHE_COMBO::Success_Not_Toplevel);
6775 break;
6776 case UNLOAD:
6777 Telemetry::AccumulateCategorical(Telemetry::LABELS_BFCACHE_COMBO::Unload);
6778 break;
6779 case BEFOREUNLOAD:
6780 Telemetry::AccumulateCategorical(
6781 Telemetry::LABELS_BFCACHE_COMBO::Beforeunload);
6782 break;
6783 case UNLOAD_REQUEST:
6784 Telemetry::AccumulateCategorical(
6785 Telemetry::LABELS_BFCACHE_COMBO::Unload_Req);
6786 break;
6787 case REQUEST:
6788 Telemetry::AccumulateCategorical(Telemetry::LABELS_BFCACHE_COMBO::Req);
6789 break;
6790 case UNLOAD_REQUEST_PEER:
6791 Telemetry::AccumulateCategorical(
6792 Telemetry::LABELS_BFCACHE_COMBO::Unload_Req_Peer);
6793 break;
6794 case UNLOAD_REQUEST_PEER_MSE:
6795 Telemetry::AccumulateCategorical(
6796 Telemetry::LABELS_BFCACHE_COMBO::Unload_Req_Peer_MSE);
6797 break;
6798 case UNLOAD_REQUEST_MSE:
6799 Telemetry::AccumulateCategorical(
6800 Telemetry::LABELS_BFCACHE_COMBO::Unload_Req_MSE);
6801 break;
6802 case SUSPENDED_UNLOAD_REQUEST_PEER:
6803 Telemetry::AccumulateCategorical(
6804 Telemetry::LABELS_BFCACHE_COMBO::SPD_Unload_Req_Peer);
6805 break;
6806 case REMOTE_SUBFRAMES:
6807 Telemetry::AccumulateCategorical(
6808 Telemetry::LABELS_BFCACHE_COMBO::Remote_Subframes);
6809 break;
6810 default:
6811 Telemetry::AccumulateCategorical(Telemetry::LABELS_BFCACHE_COMBO::Other);
6812 break;
6813 }
6814};
6815
6816void nsDocShell::ReattachEditorToWindow(nsISHEntry* aSHEntry) {
6817 MOZ_ASSERT(!mozilla::SessionHistoryInParent())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mozilla::SessionHistoryInParent())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mozilla::SessionHistoryInParent
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!mozilla::SessionHistoryInParent()", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 6817); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mozilla::SessionHistoryInParent()"
")"); do { *((volatile int*)__null) = 6817; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6818 MOZ_ASSERT(!mIsBeingDestroyed)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mIsBeingDestroyed)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mIsBeingDestroyed))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("!mIsBeingDestroyed"
, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 6818); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mIsBeingDestroyed"
")"); do { *((volatile int*)__null) = 6818; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6819
6820 NS_ASSERTION(!mEditorData,do { if (!(!mEditorData)) { NS_DebugBreak(NS_DEBUG_ASSERTION,
"Why reattach an editor when we already have one?", "!mEditorData"
, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 6821); MOZ_PretendNoReturn(); } } while (0)
6821 "Why reattach an editor when we already have one?")do { if (!(!mEditorData)) { NS_DebugBreak(NS_DEBUG_ASSERTION,
"Why reattach an editor when we already have one?", "!mEditorData"
, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 6821); MOZ_PretendNoReturn(); } } while (0)
;
6822 NS_ASSERTION(aSHEntry && aSHEntry->HasDetachedEditor(),do { if (!(aSHEntry && aSHEntry->HasDetachedEditor
())) { NS_DebugBreak(NS_DEBUG_ASSERTION, "Reattaching when there's not a detached editor."
, "aSHEntry && aSHEntry->HasDetachedEditor()", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 6823); MOZ_PretendNoReturn(); } } while (0)
6823 "Reattaching when there's not a detached editor.")do { if (!(aSHEntry && aSHEntry->HasDetachedEditor
())) { NS_DebugBreak(NS_DEBUG_ASSERTION, "Reattaching when there's not a detached editor."
, "aSHEntry && aSHEntry->HasDetachedEditor()", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 6823); MOZ_PretendNoReturn(); } } while (0)
;
6824
6825 if (mEditorData || !aSHEntry) {
6826 return;
6827 }
6828
6829 mEditorData = WrapUnique(aSHEntry->ForgetEditorData());
6830 if (mEditorData) {
6831#ifdef DEBUG1
6832 nsresult rv =
6833#endif
6834 mEditorData->ReattachToWindow(this);
6835 NS_ASSERTION(NS_SUCCEEDED(rv), "Failed to reattach editing session")do { if (!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1
))))) { NS_DebugBreak(NS_DEBUG_ASSERTION, "Failed to reattach editing session"
, "NS_SUCCEEDED(rv)", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 6835); MOZ_PretendNoReturn(); } } while (0)
;
6836 }
6837}
6838
6839void nsDocShell::DetachEditorFromWindow() {
6840 if (!mEditorData || mEditorData->WaitingForLoad()) {
6841 // If there's nothing to detach, or if the editor data is actually set
6842 // up for the _new_ page that's coming in, don't detach.
6843 return;
6844 }
6845
6846 NS_ASSERTION(!mOSHE || !mOSHE->HasDetachedEditor(),do { if (!(!mOSHE || !mOSHE->HasDetachedEditor())) { NS_DebugBreak
(NS_DEBUG_ASSERTION, "Detaching editor when it's already detached."
, "!mOSHE || !mOSHE->HasDetachedEditor()", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 6847); MOZ_PretendNoReturn(); } } while (0)
6847 "Detaching editor when it's already detached.")do { if (!(!mOSHE || !mOSHE->HasDetachedEditor())) { NS_DebugBreak
(NS_DEBUG_ASSERTION, "Detaching editor when it's already detached."
, "!mOSHE || !mOSHE->HasDetachedEditor()", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 6847); MOZ_PretendNoReturn(); } } while (0)
;
6848
6849 nsresult res = mEditorData->DetachFromWindow();
6850 NS_ASSERTION(NS_SUCCEEDED(res), "Failed to detach editor")do { if (!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(res)),
1))))) { NS_DebugBreak(NS_DEBUG_ASSERTION, "Failed to detach editor"
, "NS_SUCCEEDED(res)", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 6850); MOZ_PretendNoReturn(); } } while (0)
;
6851
6852 if (NS_SUCCEEDED(res)((bool)(__builtin_expect(!!(!NS_FAILED_impl(res)), 1)))) {
6853 // Make mOSHE hold the owning ref to the editor data.
6854 if (mOSHE) {
6855 MOZ_ASSERT(!mIsBeingDestroyed || !mOSHE->HasDetachedEditor(),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mIsBeingDestroyed || !mOSHE->HasDetachedEditor()
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!mIsBeingDestroyed || !mOSHE->HasDetachedEditor()
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"!mIsBeingDestroyed || !mOSHE->HasDetachedEditor()" " (" "We should not set the editor data again once after we "
"detached the editor data during destroying this docshell" ")"
, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 6857); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mIsBeingDestroyed || !mOSHE->HasDetachedEditor()"
") (" "We should not set the editor data again once after we "
"detached the editor data during destroying this docshell" ")"
); do { *((volatile int*)__null) = 6857; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6856 "We should not set the editor data again once after we "do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mIsBeingDestroyed || !mOSHE->HasDetachedEditor()
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!mIsBeingDestroyed || !mOSHE->HasDetachedEditor()
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"!mIsBeingDestroyed || !mOSHE->HasDetachedEditor()" " (" "We should not set the editor data again once after we "
"detached the editor data during destroying this docshell" ")"
, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 6857); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mIsBeingDestroyed || !mOSHE->HasDetachedEditor()"
") (" "We should not set the editor data again once after we "
"detached the editor data during destroying this docshell" ")"
); do { *((volatile int*)__null) = 6857; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6857 "detached the editor data during destroying this docshell")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mIsBeingDestroyed || !mOSHE->HasDetachedEditor()
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!mIsBeingDestroyed || !mOSHE->HasDetachedEditor()
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"!mIsBeingDestroyed || !mOSHE->HasDetachedEditor()" " (" "We should not set the editor data again once after we "
"detached the editor data during destroying this docshell" ")"
, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 6857); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mIsBeingDestroyed || !mOSHE->HasDetachedEditor()"
") (" "We should not set the editor data again once after we "
"detached the editor data during destroying this docshell" ")"
); do { *((volatile int*)__null) = 6857; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6858 mOSHE->SetEditorData(mEditorData.release());
6859 } else {
6860 mEditorData = nullptr;
6861 }
6862 }
6863
6864#ifdef DEBUG1
6865 {
6866 bool isEditable;
6867 GetEditable(&isEditable);
6868 NS_ASSERTION(!isEditable,do { if (!(!isEditable)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "Window is still editable after detaching editor."
, "!isEditable", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 6869); MOZ_PretendNoReturn(); } } while (0)
6869 "Window is still editable after detaching editor.")do { if (!(!isEditable)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "Window is still editable after detaching editor."
, "!isEditable", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 6869); MOZ_PretendNoReturn(); } } while (0)
;
6870 }
6871#endif // DEBUG
6872}
6873
6874nsresult nsDocShell::CaptureState() {
6875 MOZ_ASSERT(!mozilla::SessionHistoryInParent())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mozilla::SessionHistoryInParent())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mozilla::SessionHistoryInParent
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!mozilla::SessionHistoryInParent()", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 6875); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mozilla::SessionHistoryInParent()"
")"); do { *((volatile int*)__null) = 6875; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6876
6877 if (!mOSHE || mOSHE == mLSHE) {
6878 // No entry to save into, or we're replacing the existing entry.
6879 return NS_ERROR_FAILURE;
6880 }
6881
6882 if (!mScriptGlobal) {
6883 return NS_ERROR_FAILURE;
6884 }
6885
6886 nsCOMPtr<nsISupports> windowState = mScriptGlobal->SaveWindowState();
6887 NS_ENSURE_TRUE(windowState, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(windowState)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "windowState" ") failed"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 6887); return NS_ERROR_FAILURE; } } while (false)
;
6888
6889 if (MOZ_UNLIKELY(MOZ_LOG_TEST(gPageCacheLog, LogLevel::Debug))(__builtin_expect(!!((__builtin_expect(!!(mozilla::detail::log_test
(gPageCacheLog, LogLevel::Debug)), 0))), 0))
) {
6890 nsAutoCString spec;
6891 nsCOMPtr<nsIURI> uri = mOSHE->GetURI();
6892 if (uri) {
6893 uri->GetSpec(spec);
6894 }
6895 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, "Saving presentation into session history, URI: %s"
, spec.get()); } } while (0)
6896 ("Saving presentation into session history, URI: %s", spec.get()))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, "Saving presentation into session history, URI: %s"
, spec.get()); } } while (0)
;
6897 }
6898
6899 mOSHE->SetWindowState(windowState);
6900
6901 // Suspend refresh URIs and save off the timer queue
6902 mOSHE->SetRefreshURIList(mSavedRefreshURIList);
6903
6904 // Capture the current content viewer bounds.
6905 if (mDocumentViewer) {
6906 nsIntRect bounds;
6907 mDocumentViewer->GetBounds(bounds);
6908 mOSHE->SetViewerBounds(bounds);
6909 }
6910
6911 // Capture the docshell hierarchy.
6912 mOSHE->ClearChildShells();
6913
6914 uint32_t childCount = mChildList.Length();
6915 for (uint32_t i = 0; i < childCount; ++i) {
6916 nsCOMPtr<nsIDocShellTreeItem> childShell = do_QueryInterface(ChildAt(i));
6917 NS_ASSERTION(childShell, "null child shell")do { if (!(childShell)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "null child shell"
, "childShell", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 6917); MOZ_PretendNoReturn(); } } while (0)
;
6918
6919 mOSHE->AddChildShell(childShell);
6920 }
6921
6922 return NS_OK;
6923}
6924
6925NS_IMETHODIMPnsresult
6926nsDocShell::RestorePresentationEvent::Run() {
6927 MOZ_ASSERT(!mozilla::SessionHistoryInParent())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mozilla::SessionHistoryInParent())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mozilla::SessionHistoryInParent
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!mozilla::SessionHistoryInParent()", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 6927); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mozilla::SessionHistoryInParent()"
")"); do { *((volatile int*)__null) = 6927; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6928
6929 if (mDocShell && NS_FAILED(mDocShell->RestoreFromHistory())((bool)(__builtin_expect(!!(NS_FAILED_impl(mDocShell->RestoreFromHistory
())), 0)))
) {
6930 NS_WARNING("RestoreFromHistory failed")NS_DebugBreak(NS_DEBUG_WARNING, "RestoreFromHistory failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 6930)
;
6931 }
6932 return NS_OK;
6933}
6934
6935NS_IMETHODIMPnsresult
6936nsDocShell::BeginRestore(nsIDocumentViewer* aDocumentViewer, bool aTop) {
6937 MOZ_ASSERT(!mozilla::SessionHistoryInParent())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mozilla::SessionHistoryInParent())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mozilla::SessionHistoryInParent
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!mozilla::SessionHistoryInParent()", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 6937); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mozilla::SessionHistoryInParent()"
")"); do { *((volatile int*)__null) = 6937; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6938
6939 nsresult rv;
6940 if (!aDocumentViewer) {
6941 rv = EnsureDocumentViewer();
6942 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/docshell/base/nsDocShell.cpp"
, 6942); return rv; } } while (false)
;
6943
6944 aDocumentViewer = mDocumentViewer;
6945 }
6946
6947 // Dispatch events for restoring the presentation. We try to simulate
6948 // the progress notifications loading the document would cause, so we add
6949 // the document's channel to the loadgroup to initiate stateChange
6950 // notifications.
6951
6952 RefPtr<Document> doc = aDocumentViewer->GetDocument();
6953 if (doc) {
6954 nsIChannel* channel = doc->GetChannel();
6955 if (channel) {
6956 mEODForCurrentDocument = false;
6957 mIsRestoringDocument = true;
6958 mLoadGroup->AddRequest(channel, nullptr);
6959 mIsRestoringDocument = false;
6960 }
6961 }
6962
6963 if (!aTop) {
6964 // This point corresponds to us having gotten OnStartRequest or
6965 // STATE_START, so do the same thing that CreateDocumentViewer does at
6966 // this point to ensure that unload/pagehide events for this document
6967 // will fire when it's unloaded again.
6968 mFiredUnloadEvent = false;
6969
6970 // For non-top frames, there is no notion of making sure that the
6971 // previous document is in the domwindow when STATE_START notifications
6972 // happen. We can just call BeginRestore for all of the child shells
6973 // now.
6974 rv = BeginRestoreChildren();
6975 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/docshell/base/nsDocShell.cpp"
, 6975); return rv; } } while (false)
;
6976 }
6977
6978 return NS_OK;
6979}
6980
6981nsresult nsDocShell::BeginRestoreChildren() {
6982 MOZ_ASSERT(!mozilla::SessionHistoryInParent())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mozilla::SessionHistoryInParent())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mozilla::SessionHistoryInParent
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!mozilla::SessionHistoryInParent()", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 6982); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mozilla::SessionHistoryInParent()"
")"); do { *((volatile int*)__null) = 6982; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6983
6984 for (auto* childDocLoader : mChildList.ForwardRange()) {
6985 nsCOMPtr<nsIDocShell> child = do_QueryObject(childDocLoader);
6986 if (child) {
6987 nsresult rv = child->BeginRestore(nullptr, false);
6988 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/docshell/base/nsDocShell.cpp"
, 6988); return rv; } } while (false)
;
6989 }
6990 }
6991 return NS_OK;
6992}
6993
6994NS_IMETHODIMPnsresult
6995nsDocShell::FinishRestore() {
6996 MOZ_ASSERT(!mozilla::SessionHistoryInParent())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mozilla::SessionHistoryInParent())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mozilla::SessionHistoryInParent
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!mozilla::SessionHistoryInParent()", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 6996); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mozilla::SessionHistoryInParent()"
")"); do { *((volatile int*)__null) = 6996; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6997
6998 // First we call finishRestore() on our children. In the simulated load,
6999 // all of the child frames finish loading before the main document.
7000
7001 for (auto* childDocLoader : mChildList.ForwardRange()) {
7002 nsCOMPtr<nsIDocShell> child = do_QueryObject(childDocLoader);
7003 if (child) {
7004 child->FinishRestore();
7005 }
7006 }
7007
7008 if (mOSHE && mOSHE->HasDetachedEditor()) {
7009 ReattachEditorToWindow(mOSHE);
7010 }
7011
7012 RefPtr<Document> doc = GetDocument();
7013 if (doc) {
7014 // Finally, we remove the request from the loadgroup. This will
7015 // cause onStateChange(STATE_STOP) to fire, which will fire the
7016 // pageshow event to the chrome.
7017
7018 nsIChannel* channel = doc->GetChannel();
7019 if (channel) {
7020 mIsRestoringDocument = true;
7021 mLoadGroup->RemoveRequest(channel, nullptr, NS_OK);
7022 mIsRestoringDocument = false;
7023 }
7024 }
7025
7026 return NS_OK;
7027}
7028
7029NS_IMETHODIMPnsresult
7030nsDocShell::GetRestoringDocument(bool* aRestoring) {
7031 *aRestoring = mIsRestoringDocument;
7032 return NS_OK;
7033}
7034
7035nsresult nsDocShell::RestorePresentation(nsISHEntry* aSHEntry,
7036 bool* aRestoring) {
7037 MOZ_ASSERT(!mozilla::SessionHistoryInParent())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mozilla::SessionHistoryInParent())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mozilla::SessionHistoryInParent
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!mozilla::SessionHistoryInParent()", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 7037); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mozilla::SessionHistoryInParent()"
")"); do { *((volatile int*)__null) = 7037; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7038 MOZ_ASSERT(!mIsBeingDestroyed)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mIsBeingDestroyed)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mIsBeingDestroyed))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("!mIsBeingDestroyed"
, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 7038); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mIsBeingDestroyed"
")"); do { *((volatile int*)__null) = 7038; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7039
7040 NS_ASSERTION(mLoadType & LOAD_CMD_HISTORY,do { if (!(mLoadType & LOAD_CMD_HISTORY)) { NS_DebugBreak
(NS_DEBUG_ASSERTION, "RestorePresentation should only be called for history loads"
, "mLoadType & LOAD_CMD_HISTORY", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 7041); MOZ_PretendNoReturn(); } } while (0)
7041 "RestorePresentation should only be called for history loads")do { if (!(mLoadType & LOAD_CMD_HISTORY)) { NS_DebugBreak
(NS_DEBUG_ASSERTION, "RestorePresentation should only be called for history loads"
, "mLoadType & LOAD_CMD_HISTORY", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 7041); MOZ_PretendNoReturn(); } } while (0)
;
7042
7043 nsCOMPtr<nsIDocumentViewer> viewer = aSHEntry->GetDocumentViewer();
7044
7045 nsAutoCString spec;
7046 if (MOZ_UNLIKELY(MOZ_LOG_TEST(gPageCacheLog, LogLevel::Debug))(__builtin_expect(!!((__builtin_expect(!!(mozilla::detail::log_test
(gPageCacheLog, LogLevel::Debug)), 0))), 0))
) {
7047 nsCOMPtr<nsIURI> uri = aSHEntry->GetURI();
7048 if (uri) {
7049 uri->GetSpec(spec);
7050 }
7051 }
7052
7053 *aRestoring = false;
7054
7055 if (!viewer) {
7056 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, "no saved presentation for uri: %s", spec.
get()); } } while (0)
7057 ("no saved presentation for uri: %s", spec.get()))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, "no saved presentation for uri: %s", spec.
get()); } } while (0)
;
7058 return NS_OK;
7059 }
7060
7061 // We need to make sure the content viewer's container is this docshell.
7062 // In subframe navigation, it's possible for the docshell that the
7063 // content viewer was originally loaded into to be replaced with a
7064 // different one. We don't currently support restoring the presentation
7065 // in that case.
7066
7067 nsCOMPtr<nsIDocShell> container;
7068 viewer->GetContainer(getter_AddRefs(container));
7069 if (!::SameCOMIdentity(container, GetAsSupports(this))) {
7070 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, "No valid container, clearing presentation"
); } } while (0)
7071 ("No valid container, clearing presentation"))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, "No valid container, clearing presentation"
); } } while (0)
;
7072 aSHEntry->SetDocumentViewer(nullptr);
7073 return NS_ERROR_FAILURE;
7074 }
7075
7076 NS_ASSERTION(mDocumentViewer != viewer, "Restoring existing presentation")do { if (!(mDocumentViewer != viewer)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "Restoring existing presentation", "mDocumentViewer != viewer"
, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 7076); MOZ_PretendNoReturn(); } } while (0)
;
7077
7078 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, "restoring presentation from session history: %s"
, spec.get()); } } while (0)
7079 ("restoring presentation from session history: %s", spec.get()))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, "restoring presentation from session history: %s"
, spec.get()); } } while (0)
;
7080
7081 SetHistoryEntryAndUpdateBC(Some(aSHEntry), Nothing());
7082
7083 // Post an event that will remove the request after we've returned
7084 // to the event loop. This mimics the way it is called by nsIChannel
7085 // implementations.
7086
7087 // Revoke any pending restore (just in case).
7088 NS_ASSERTION(!mRestorePresentationEvent.IsPending(),do { if (!(!mRestorePresentationEvent.IsPending())) { NS_DebugBreak
(NS_DEBUG_ASSERTION, "should only have one RestorePresentationEvent"
, "!mRestorePresentationEvent.IsPending()", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 7089); MOZ_PretendNoReturn(); } } while (0)
7089 "should only have one RestorePresentationEvent")do { if (!(!mRestorePresentationEvent.IsPending())) { NS_DebugBreak
(NS_DEBUG_ASSERTION, "should only have one RestorePresentationEvent"
, "!mRestorePresentationEvent.IsPending()", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 7089); MOZ_PretendNoReturn(); } } while (0)
;
7090 mRestorePresentationEvent.Revoke();
7091
7092 RefPtr<RestorePresentationEvent> evt = new RestorePresentationEvent(this);
7093 nsresult rv = Dispatch(do_AddRef(evt));
7094 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
7095 mRestorePresentationEvent = evt.get();
7096 // The rest of the restore processing will happen on our event
7097 // callback.
7098 *aRestoring = true;
7099 }
7100
7101 return rv;
7102}
7103
7104namespace {
7105class MOZ_STACK_CLASS PresentationEventForgetter {
7106 public:
7107 explicit PresentationEventForgetter(
7108 nsRevocableEventPtr<nsDocShell::RestorePresentationEvent>&
7109 aRestorePresentationEvent)
7110 : mRestorePresentationEvent(aRestorePresentationEvent),
7111 mEvent(aRestorePresentationEvent.get()) {}
7112
7113 ~PresentationEventForgetter() { Forget(); }
7114
7115 void Forget() {
7116 if (mRestorePresentationEvent.get() == mEvent) {
7117 mRestorePresentationEvent.Forget();
7118 mEvent = nullptr;
7119 }
7120 }
7121
7122 private:
7123 nsRevocableEventPtr<nsDocShell::RestorePresentationEvent>&
7124 mRestorePresentationEvent;
7125 RefPtr<nsDocShell::RestorePresentationEvent> mEvent;
7126};
7127
7128} // namespace
7129
7130bool nsDocShell::SandboxFlagsImplyCookies(const uint32_t& aSandboxFlags) {
7131 return (aSandboxFlags & (SANDBOXED_ORIGIN | SANDBOXED_SCRIPTS)) == 0;
7132}
7133
7134nsresult nsDocShell::RestoreFromHistory() {
7135 MOZ_ASSERT(!mozilla::SessionHistoryInParent())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mozilla::SessionHistoryInParent())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mozilla::SessionHistoryInParent
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!mozilla::SessionHistoryInParent()", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 7135); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mozilla::SessionHistoryInParent()"
")"); do { *((volatile int*)__null) = 7135; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7136 MOZ_ASSERT(mRestorePresentationEvent.IsPending())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mRestorePresentationEvent.IsPending())>::isValid,
"invalid assertion condition"); if ((__builtin_expect(!!(!(!
!(mRestorePresentationEvent.IsPending()))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("mRestorePresentationEvent.IsPending()"
, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 7136); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mRestorePresentationEvent.IsPending()"
")"); do { *((volatile int*)__null) = 7136; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7137 PresentationEventForgetter forgetter(mRestorePresentationEvent);
7138
7139 // This section of code follows the same ordering as CreateDocumentViewer.
7140 if (!mLSHE) {
7141 return NS_ERROR_FAILURE;
7142 }
7143
7144 nsCOMPtr<nsIDocumentViewer> viewer = mLSHE->GetDocumentViewer();
7145 if (!viewer) {
7146 return NS_ERROR_FAILURE;
7147 }
7148
7149 if (mSavingOldViewer) {
7150 // We determined that it was safe to cache the document presentation
7151 // at the time we initiated the new load. We need to check whether
7152 // it's still safe to do so, since there may have been DOM mutations
7153 // or new requests initiated.
7154 RefPtr<Document> doc = viewer->GetDocument();
7155 nsIRequest* request = nullptr;
7156 if (doc) {
7157 request = doc->GetChannel();
7158 }
7159 mSavingOldViewer = CanSavePresentation(
7160 mLoadType, request, doc, /* aReportBFCacheComboTelemetry */ false);
7161 }
7162
7163 // Protect against mLSHE going away via a load triggered from
7164 // pagehide or unload.
7165 nsCOMPtr<nsISHEntry> origLSHE = mLSHE;
7166
7167 // Make sure to blow away our mLoadingURI just in case. No loads
7168 // from inside this pagehide.
7169 mLoadingURI = nullptr;
7170
7171 // Notify the old content viewer that it's being hidden.
7172 FirePageHideNotification(!mSavingOldViewer);
7173 // pagehide notification might destroy this docshell.
7174 if (mIsBeingDestroyed) {
7175 return NS_ERROR_DOCSHELL_DYING;
7176 }
7177
7178 // If mLSHE was changed as a result of the pagehide event, then
7179 // something else was loaded. Don't finish restoring.
7180 if (mLSHE != origLSHE) {
7181 return NS_OK;
7182 }
7183
7184 // Add the request to our load group. We do this before swapping out
7185 // the content viewers so that consumers of STATE_START can access
7186 // the old document. We only deal with the toplevel load at this time --
7187 // to be consistent with normal document loading, subframes cannot start
7188 // loading until after data arrives, which is after STATE_START completes.
7189
7190 RefPtr<RestorePresentationEvent> currentPresentationRestoration =
7191 mRestorePresentationEvent.get();
7192 Stop();
7193 // Make sure we're still restoring the same presentation.
7194 // If we aren't, docshell is in process doing another load already.
7195 NS_ENSURE_STATE(currentPresentationRestoration ==do { if ((__builtin_expect(!!(!(currentPresentationRestoration
== mRestorePresentationEvent.get())), 0))) { NS_DebugBreak(NS_DEBUG_WARNING
, "NS_ENSURE_TRUE(" "currentPresentationRestoration == mRestorePresentationEvent.get()"
") failed", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 7196); return NS_ERROR_UNEXPECTED; } } while (false)
7196 mRestorePresentationEvent.get())do { if ((__builtin_expect(!!(!(currentPresentationRestoration
== mRestorePresentationEvent.get())), 0))) { NS_DebugBreak(NS_DEBUG_WARNING
, "NS_ENSURE_TRUE(" "currentPresentationRestoration == mRestorePresentationEvent.get()"
") failed", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 7196); return NS_ERROR_UNEXPECTED; } } while (false)
;
7197 BeginRestore(viewer, true);
7198 NS_ENSURE_STATE(currentPresentationRestoration ==do { if ((__builtin_expect(!!(!(currentPresentationRestoration
== mRestorePresentationEvent.get())), 0))) { NS_DebugBreak(NS_DEBUG_WARNING
, "NS_ENSURE_TRUE(" "currentPresentationRestoration == mRestorePresentationEvent.get()"
") failed", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 7199); return NS_ERROR_UNEXPECTED; } } while (false)
7199 mRestorePresentationEvent.get())do { if ((__builtin_expect(!!(!(currentPresentationRestoration
== mRestorePresentationEvent.get())), 0))) { NS_DebugBreak(NS_DEBUG_WARNING
, "NS_ENSURE_TRUE(" "currentPresentationRestoration == mRestorePresentationEvent.get()"
") failed", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 7199); return NS_ERROR_UNEXPECTED; } } while (false)
;
7200 forgetter.Forget();
7201
7202 // Set mFiredUnloadEvent = false so that the unload handler for the
7203 // *new* document will fire.
7204 mFiredUnloadEvent = false;
7205
7206 mURIResultedInDocument = true;
7207 RefPtr<ChildSHistory> rootSH = GetRootSessionHistory();
7208 if (rootSH) {
7209 mPreviousEntryIndex = rootSH->Index();
7210 rootSH->LegacySHistory()->UpdateIndex();
7211 mLoadedEntryIndex = rootSH->Index();
7212 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, "Previous index: %d, Loaded index: %d", mPreviousEntryIndex
, mLoadedEntryIndex); } } while (0)
7213 ("Previous index: %d, Loaded index: %d", mPreviousEntryIndex,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, "Previous index: %d, Loaded index: %d", mPreviousEntryIndex
, mLoadedEntryIndex); } } while (0)
7214 mLoadedEntryIndex))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, "Previous index: %d, Loaded index: %d", mPreviousEntryIndex
, mLoadedEntryIndex); } } while (0)
;
7215 }
7216
7217 // Rather than call Embed(), we will retrieve the viewer from the session
7218 // history entry and swap it in.
7219 // XXX can we refactor this so that we can just call Embed()?
7220 PersistLayoutHistoryState();
7221 nsresult rv;
7222 if (mDocumentViewer) {
7223 if (mSavingOldViewer && NS_FAILED(CaptureState())((bool)(__builtin_expect(!!(NS_FAILED_impl(CaptureState())), 0
)))
) {
7224 if (mOSHE) {
7225 mOSHE->SyncPresentationState();
7226 }
7227 mSavingOldViewer = false;
7228 }
7229 }
7230
7231 mSavedRefreshURIList = nullptr;
7232
7233 // In cases where we use a transient about:blank viewer between loads,
7234 // we never show the transient viewer, so _its_ previous viewer is never
7235 // unhooked from the view hierarchy. Destroy any such previous viewer now,
7236 // before we grab the root view sibling, so that we don't grab a view
7237 // that's about to go away.
7238
7239 if (mDocumentViewer) {
7240 // Make sure to hold a strong ref to previousViewer here while we
7241 // drop the reference to it from mDocumentViewer.
7242 nsCOMPtr<nsIDocumentViewer> previousViewer =
7243 mDocumentViewer->GetPreviousViewer();
7244 if (previousViewer) {
7245 mDocumentViewer->SetPreviousViewer(nullptr);
7246 previousViewer->Destroy();
7247 }
7248 }
7249
7250 // Save off the root view's parent and sibling so that we can insert the
7251 // new content viewer's root view at the same position. Also save the
7252 // bounds of the root view's widget.
7253
7254 nsView* rootViewSibling = nullptr;
7255 nsView* rootViewParent = nullptr;
7256 nsIntRect newBounds(0, 0, 0, 0);
7257
7258 PresShell* oldPresShell = GetPresShell();
7259 if (oldPresShell) {
7260 nsViewManager* vm = oldPresShell->GetViewManager();
7261 if (vm) {
7262 nsView* oldRootView = vm->GetRootView();
7263
7264 if (oldRootView) {
7265 rootViewSibling = oldRootView->GetNextSibling();
7266 rootViewParent = oldRootView->GetParent();
7267
7268 mDocumentViewer->GetBounds(newBounds);
7269 }
7270 }
7271 }
7272
7273 nsCOMPtr<nsIContent> container;
7274 RefPtr<Document> sibling;
7275 if (rootViewParent && rootViewParent->GetParent()) {
7276 nsIFrame* frame = rootViewParent->GetParent()->GetFrame();
7277 container = frame ? frame->GetContent() : nullptr;
7278 }
7279 if (rootViewSibling) {
7280 nsIFrame* frame = rootViewSibling->GetFrame();
7281 sibling = frame ? frame->PresShell()->GetDocument() : nullptr;
7282 }
7283
7284 // Transfer ownership to mDocumentViewer. By ensuring that either the
7285 // docshell or the session history, but not both, have references to the
7286 // content viewer, we prevent the viewer from being torn down after
7287 // Destroy() is called.
7288
7289 if (mDocumentViewer) {
7290 mDocumentViewer->Close(mSavingOldViewer ? mOSHE.get() : nullptr);
7291 viewer->SetPreviousViewer(mDocumentViewer);
7292 }
7293 if (mOSHE && (!mDocumentViewer || !mSavingOldViewer)) {
7294 // We don't plan to save a viewer in mOSHE; tell it to drop
7295 // any other state it's holding.
7296 mOSHE->SyncPresentationState();
7297 }
7298
7299 // Order the mDocumentViewer setup just like Embed does.
7300 mDocumentViewer = nullptr;
7301
7302 // Now that we're about to switch documents, forget all of our children.
7303 // Note that we cached them as needed up in CaptureState above.
7304 DestroyChildren();
7305
7306 mDocumentViewer.swap(viewer);
7307
7308 // Grab all of the related presentation from the SHEntry now.
7309 // Clearing the viewer from the SHEntry will clear all of this state.
7310 nsCOMPtr<nsISupports> windowState = mLSHE->GetWindowState();
7311 mLSHE->SetWindowState(nullptr);
7312
7313 bool sticky = mLSHE->GetSticky();
7314
7315 RefPtr<Document> document = mDocumentViewer->GetDocument();
7316
7317 nsCOMArray<nsIDocShellTreeItem> childShells;
7318 int32_t i = 0;
7319 nsCOMPtr<nsIDocShellTreeItem> child;
7320 while (NS_SUCCEEDED(mLSHE->ChildShellAt(i++, getter_AddRefs(child)))((bool)(__builtin_expect(!!(!NS_FAILED_impl(mLSHE->ChildShellAt
(i++, getter_AddRefs(child)))), 1)))
&&
7321 child) {
7322 childShells.AppendObject(child);
7323 }
7324
7325 // get the previous content viewer size
7326 nsIntRect oldBounds(0, 0, 0, 0);
7327 mLSHE->GetViewerBounds(oldBounds);
7328
7329 // Restore the refresh URI list. The refresh timers will be restarted
7330 // when EndPageLoad() is called.
7331 nsCOMPtr<nsIMutableArray> refreshURIList = mLSHE->GetRefreshURIList();
7332
7333 // Reattach to the window object.
7334 mIsRestoringDocument = true; // for MediaDocument::BecomeInteractive
7335 rv = mDocumentViewer->Open(windowState, mLSHE);
7336 mIsRestoringDocument = false;
7337
7338 // Hack to keep nsDocShellEditorData alive across the
7339 // SetContentViewer(nullptr) call below.
7340 UniquePtr<nsDocShellEditorData> data(mLSHE->ForgetEditorData());
7341
7342 // Now remove it from the cached presentation.
7343 mLSHE->SetDocumentViewer(nullptr);
7344 mEODForCurrentDocument = false;
7345
7346 mLSHE->SetEditorData(data.release());
7347
7348#ifdef DEBUG1
7349 {
7350 nsCOMPtr<nsIMutableArray> refreshURIs = mLSHE->GetRefreshURIList();
7351 nsCOMPtr<nsIDocShellTreeItem> childShell;
7352 mLSHE->ChildShellAt(0, getter_AddRefs(childShell));
7353 NS_ASSERTION(!refreshURIs && !childShell,do { if (!(!refreshURIs && !childShell)) { NS_DebugBreak
(NS_DEBUG_ASSERTION, "SHEntry should have cleared presentation state"
, "!refreshURIs && !childShell", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 7354); MOZ_PretendNoReturn(); } } while (0)
7354 "SHEntry should have cleared presentation state")do { if (!(!refreshURIs && !childShell)) { NS_DebugBreak
(NS_DEBUG_ASSERTION, "SHEntry should have cleared presentation state"
, "!refreshURIs && !childShell", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 7354); MOZ_PretendNoReturn(); } } while (0)
;
7355 }
7356#endif
7357
7358 // Restore the sticky state of the viewer. The viewer has set this state
7359 // on the history entry in Destroy() just before marking itself non-sticky,
7360 // to avoid teardown of the presentation.
7361 mDocumentViewer->SetSticky(sticky);
7362
7363 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/docshell/base/nsDocShell.cpp"
, 7363); return rv; } } while (false)
;
7364
7365 // mLSHE is now our currently-loaded document.
7366 SetHistoryEntryAndUpdateBC(Nothing(), Some<nsISHEntry*>(mLSHE));
7367
7368 // We aren't going to restore any items from the LayoutHistoryState,
7369 // but we don't want them to stay around in case the page is reloaded.
7370 SetLayoutHistoryState(nullptr);
7371
7372 // This is the end of our Embed() replacement
7373
7374 mSavingOldViewer = false;
7375 mEODForCurrentDocument = false;
7376
7377 if (document) {
7378 RefPtr<nsDocShell> parent = GetInProcessParentDocshell();
7379 if (parent) {
7380 RefPtr<Document> d = parent->GetDocument();
7381 if (d) {
7382 if (d->EventHandlingSuppressed()) {
7383 document->SuppressEventHandling(d->EventHandlingSuppressed());
7384 }
7385 }
7386 }
7387
7388 // Use the uri from the mLSHE we had when we entered this function
7389 // (which need not match the document's URI if anchors are involved),
7390 // since that's the history entry we're loading. Note that if we use
7391 // origLSHE we don't have to worry about whether the entry in question
7392 // is still mLSHE or whether it's now mOSHE.
7393 nsCOMPtr<nsIURI> uri = origLSHE->GetURI();
7394 SetCurrentURI(uri, document->GetChannel(), /* aFireLocationChange */ true,
7395 /* aIsInitialAboutBlank */ false,
7396 /* aLocationFlags */ 0);
7397 }
7398
7399 // This is the end of our CreateDocumentViewer() replacement.
7400 // Now we simulate a load. First, we restore the state of the javascript
7401 // window object.
7402 nsCOMPtr<nsPIDOMWindowOuter> privWin = GetWindow();
7403 NS_ASSERTION(privWin, "could not get nsPIDOMWindow interface")do { if (!(privWin)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "could not get nsPIDOMWindow interface"
, "privWin", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 7403); MOZ_PretendNoReturn(); } } while (0)
;
7404
7405 // Now, dispatch a title change event which would happen as the
7406 // <head> is parsed.
7407 document->NotifyPossibleTitleChange(false);
7408
7409 // Now we simulate appending child docshells for subframes.
7410 for (i = 0; i < childShells.Count(); ++i) {
7411 nsIDocShellTreeItem* childItem = childShells.ObjectAt(i);
7412 nsCOMPtr<nsIDocShell> childShell = do_QueryInterface(childItem);
7413
7414 // Make sure to not clobber the state of the child. Since AddChild
7415 // always clobbers it, save it off first.
7416 bool allowRedirects;
7417 childShell->GetAllowMetaRedirects(&allowRedirects);
7418
7419 bool allowSubframes;
7420 childShell->GetAllowSubframes(&allowSubframes);
7421
7422 bool allowImages;
7423 childShell->GetAllowImages(&allowImages);
7424
7425 bool allowMedia = childShell->GetAllowMedia();
7426
7427 bool allowDNSPrefetch;
7428 childShell->GetAllowDNSPrefetch(&allowDNSPrefetch);
7429
7430 bool allowContentRetargeting = childShell->GetAllowContentRetargeting();
7431 bool allowContentRetargetingOnChildren =
7432 childShell->GetAllowContentRetargetingOnChildren();
7433
7434 // this.AddChild(child) calls child.SetDocLoaderParent(this), meaning that
7435 // the child inherits our state. Among other things, this means that the
7436 // child inherits our mPrivateBrowsingId, which is what we want.
7437 AddChild(childItem);
7438
7439 childShell->SetAllowMetaRedirects(allowRedirects);
7440 childShell->SetAllowSubframes(allowSubframes);
7441 childShell->SetAllowImages(allowImages);
7442 childShell->SetAllowMedia(allowMedia);
7443 childShell->SetAllowDNSPrefetch(allowDNSPrefetch);
7444 childShell->SetAllowContentRetargeting(allowContentRetargeting);
7445 childShell->SetAllowContentRetargetingOnChildren(
7446 allowContentRetargetingOnChildren);
7447
7448 rv = childShell->BeginRestore(nullptr, false);
7449 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/docshell/base/nsDocShell.cpp"
, 7449); return rv; } } while (false)
;
7450 }
7451
7452 // Make sure to restore the window state after adding the child shells back
7453 // to the tree. This is necessary for Thaw() and Resume() to propagate
7454 // properly.
7455 rv = privWin->RestoreWindowState(windowState);
7456 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/docshell/base/nsDocShell.cpp"
, 7456); return rv; } } while (false)
;
7457
7458 RefPtr<PresShell> presShell = GetPresShell();
7459
7460 // We may be displayed on a different monitor (or in a different
7461 // HiDPI mode) than when we got into the history list. So we need
7462 // to check if this has happened. See bug 838239.
7463
7464 // Because the prescontext normally handles resolution changes via
7465 // a runnable (see nsPresContext::UIResolutionChanged), its device
7466 // context won't be -immediately- updated as a result of calling
7467 // presShell->BackingScaleFactorChanged().
7468
7469 // But we depend on that device context when adjusting the view size
7470 // via mDocumentViewer->SetBounds(newBounds) below. So we need to
7471 // explicitly tell it to check for changed resolution here.
7472 if (presShell) {
7473 RefPtr<nsPresContext> pc = presShell->GetPresContext();
7474 if (pc->DeviceContext()->CheckDPIChange()) {
7475 presShell->BackingScaleFactorChanged();
7476 }
7477 // Recompute zoom and text-zoom and such.
7478 pc->RecomputeBrowsingContextDependentData();
7479 }
7480
7481 nsViewManager* newVM = presShell ? presShell->GetViewManager() : nullptr;
7482 nsView* newRootView = newVM ? newVM->GetRootView() : nullptr;
7483
7484 // Insert the new root view at the correct location in the view tree.
7485 if (container) {
7486 nsSubDocumentFrame* subDocFrame =
7487 do_QueryFrame(container->GetPrimaryFrame());
7488 rootViewParent = subDocFrame ? subDocFrame->EnsureInnerView() : nullptr;
7489 } else {
7490 rootViewParent = nullptr;
7491 }
7492 if (sibling && sibling->GetPresShell() &&
7493 sibling->GetPresShell()->GetViewManager()) {
7494 rootViewSibling = sibling->GetPresShell()->GetViewManager()->GetRootView();
7495 } else {
7496 rootViewSibling = nullptr;
7497 }
7498 if (rootViewParent && newRootView &&
7499 newRootView->GetParent() != rootViewParent) {
7500 nsViewManager* parentVM = rootViewParent->GetViewManager();
7501 if (parentVM) {
7502 // InsertChild(parent, child, sib, true) inserts the child after
7503 // sib in content order, which is before sib in view order. BUT
7504 // when sib is null it inserts at the end of the the document
7505 // order, i.e., first in view order. But when oldRootSibling is
7506 // null, the old root as at the end of the view list --- last in
7507 // content order --- and we want to call InsertChild(parent, child,
7508 // nullptr, false) in that case.
7509 parentVM->InsertChild(rootViewParent, newRootView, rootViewSibling,
7510 rootViewSibling ? true : false);
7511
7512 NS_ASSERTION(newRootView->GetNextSibling() == rootViewSibling,do { if (!(newRootView->GetNextSibling() == rootViewSibling
)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "error in InsertChild"
, "newRootView->GetNextSibling() == rootViewSibling", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 7513); MOZ_PretendNoReturn(); } } while (0)
7513 "error in InsertChild")do { if (!(newRootView->GetNextSibling() == rootViewSibling
)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "error in InsertChild"
, "newRootView->GetNextSibling() == rootViewSibling", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 7513); MOZ_PretendNoReturn(); } } while (0)
;
7514 }
7515 }
7516
7517 nsCOMPtr<nsPIDOMWindowInner> privWinInner = privWin->GetCurrentInnerWindow();
7518
7519 // If parent is suspended, increase suspension count.
7520 // This can't be done as early as event suppression since this
7521 // depends on docshell tree.
7522 privWinInner->SyncStateFromParentWindow();
7523
7524 // Now that all of the child docshells have been put into place, we can
7525 // restart the timers for the window and all of the child frames.
7526 privWinInner->Resume();
7527
7528 // Now that we have found the inner window of the page restored
7529 // from the history, we have to make sure that
7530 // performance.navigation.type is 2.
7531 Performance* performance = privWinInner->GetPerformance();
7532 if (performance) {
7533 performance->GetDOMTiming()->NotifyRestoreStart();
7534 }
7535
7536 // Restore the refresh URI list. The refresh timers will be restarted
7537 // when EndPageLoad() is called.
7538 mRefreshURIList = refreshURIList;
7539
7540 // Meta-refresh timers have been restarted for this shell, but not
7541 // for our children. Walk the child shells and restart their timers.
7542 for (auto* childDocLoader : mChildList.ForwardRange()) {
7543 nsCOMPtr<nsIDocShell> child = do_QueryObject(childDocLoader);
7544 if (child) {
7545 child->ResumeRefreshURIs();
7546 }
7547 }
7548
7549 // Make sure this presentation is the same size as the previous
7550 // presentation. If this is not the same size we showed it at last time,
7551 // then we need to resize the widget.
7552
7553 // XXXbryner This interacts poorly with Firefox's infobar. If the old
7554 // presentation had the infobar visible, then we will resize the new
7555 // presentation to that smaller size. However, firing the locationchanged
7556 // event will hide the infobar, which will immediately resize the window
7557 // back to the larger size. A future optimization might be to restore
7558 // the presentation at the "wrong" size, then fire the locationchanged
7559 // event and check whether the docshell's new size is the same as the
7560 // cached viewer size (skipping the resize if they are equal).
7561
7562 if (newRootView) {
7563 if (!newBounds.IsEmpty() && !newBounds.IsEqualEdges(oldBounds)) {
7564 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, "resize widget(%d, %d, %d, %d)", newBounds
.x, newBounds.y, newBounds.width, newBounds.height); } } while
(0)
7565 ("resize widget(%d, %d, %d, %d)", newBounds.x, newBounds.y,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, "resize widget(%d, %d, %d, %d)", newBounds
.x, newBounds.y, newBounds.width, newBounds.height); } } while
(0)
7566 newBounds.width, newBounds.height))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, "resize widget(%d, %d, %d, %d)", newBounds
.x, newBounds.y, newBounds.width, newBounds.height); } } while
(0)
;
7567 mDocumentViewer->SetBounds(newBounds);
7568 } else if (ScrollContainerFrame* sf =
7569 presShell->GetRootScrollContainerFrame()) {
7570 sf->PostScrolledAreaEventForCurrentArea();
7571 }
7572 }
7573
7574 // The FinishRestore call below can kill these, null them out so we don't
7575 // have invalid pointer lying around.
7576 newRootView = rootViewSibling = rootViewParent = nullptr;
7577 newVM = nullptr;
7578
7579 // If the IsUnderHiddenEmbedderElement() state has been changed, we need to
7580 // update it.
7581 if (oldPresShell && presShell &&
7582 presShell->IsUnderHiddenEmbedderElement() !=
7583 oldPresShell->IsUnderHiddenEmbedderElement()) {
7584 presShell->SetIsUnderHiddenEmbedderElement(
7585 oldPresShell->IsUnderHiddenEmbedderElement());
7586 }
7587
7588 // Simulate the completion of the load.
7589 nsDocShell::FinishRestore();
7590
7591 // Restart plugins, and paint the content.
7592 if (presShell) {
7593 presShell->Thaw();
7594 }
7595
7596 return privWin->FireDelayedDOMEvents(true);
7597}
7598
7599nsresult nsDocShell::CreateDocumentViewer(const nsACString& aContentType,
7600 nsIRequest* aRequest,
7601 nsIStreamListener** aContentHandler) {
7602 *aContentHandler = nullptr;
7603
7604 if (!mTreeOwner || mIsBeingDestroyed) {
7605 // If we don't have a tree owner, then we're in the process of being
7606 // destroyed. Rather than continue trying to load something, just give up.
7607 return NS_ERROR_DOCSHELL_DYING;
7608 }
7609
7610 if (!mBrowsingContext->AncestorsAreCurrent() ||
7611 mBrowsingContext->IsInBFCache()) {
7612 mBrowsingContext->RemoveRootFromBFCacheSync();
7613 return NS_ERROR_NOT_AVAILABLE;
7614 }
7615
7616 // Can we check the content type of the current content viewer
7617 // and reuse it without destroying it and re-creating it?
7618
7619 NS_ASSERTION(mLoadGroup, "Someone ignored return from Init()?")do { if (!(mLoadGroup)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "Someone ignored return from Init()?"
, "mLoadGroup", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 7619); MOZ_PretendNoReturn(); } } while (0)
;
7620
7621 // Instantiate the content viewer object
7622 nsCOMPtr<nsIDocumentViewer> viewer;
7623 nsresult rv = NewDocumentViewerObj(aContentType, aRequest, mLoadGroup,
7624 aContentHandler, getter_AddRefs(viewer));
7625
7626 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
7627 return rv;
7628 }
7629
7630 // Notify the current document that it is about to be unloaded!!
7631 //
7632 // It is important to fire the unload() notification *before* any state
7633 // is changed within the DocShell - otherwise, javascript will get the
7634 // wrong information :-(
7635 //
7636
7637 if (mSavingOldViewer) {
7638 // We determined that it was safe to cache the document presentation
7639 // at the time we initiated the new load. We need to check whether
7640 // it's still safe to do so, since there may have been DOM mutations
7641 // or new requests initiated.
7642 RefPtr<Document> doc = viewer->GetDocument();
7643 mSavingOldViewer = CanSavePresentation(
7644 mLoadType, aRequest, doc, /* aReportBFCacheComboTelemetry */ false);
7645 }
7646
7647 NS_ASSERTION(!mLoadingURI, "Re-entering unload?")do { if (!(!mLoadingURI)) { NS_DebugBreak(NS_DEBUG_ASSERTION,
"Re-entering unload?", "!mLoadingURI", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 7647); MOZ_PretendNoReturn(); } } while (0)
;
7648
7649 nsCOMPtr<nsIChannel> aOpenedChannel = do_QueryInterface(aRequest);
7650 if (aOpenedChannel) {
7651 aOpenedChannel->GetURI(getter_AddRefs(mLoadingURI));
7652 }
7653
7654 // Grab the current URI, we need to pass it to Embed, and OnNewURI will reset
7655 // it before we do call Embed.
7656 nsCOMPtr<nsIURI> previousURI = mCurrentURI;
7657
7658 FirePageHideNotification(!mSavingOldViewer);
7659 if (mIsBeingDestroyed) {
7660 // Force to stop the newly created orphaned viewer.
7661 viewer->Stop();
7662 return NS_ERROR_DOCSHELL_DYING;
7663 }
7664 mLoadingURI = nullptr;
7665
7666 // Set mFiredUnloadEvent = false so that the unload handler for the
7667 // *new* document will fire.
7668 mFiredUnloadEvent = false;
7669
7670 // we've created a new document so go ahead and call
7671 // OnNewURI(), but don't fire OnLocationChange()
7672 // notifications before we've called Embed(). See bug 284993.
7673 mURIResultedInDocument = true;
7674 bool errorOnLocationChangeNeeded = false;
7675 nsCOMPtr<nsIChannel> failedChannel = mFailedChannel;
7676 nsCOMPtr<nsIURI> failedURI;
7677
7678 if (mLoadType == LOAD_ERROR_PAGE) {
7679 // We need to set the SH entry and our current URI here and not
7680 // at the moment we load the page. We want the same behavior
7681 // of Stop() as for a normal page load. See bug 514232 for details.
7682
7683 // Revert mLoadType to load type to state the page load failed,
7684 // following function calls need it.
7685 mLoadType = mFailedLoadType;
7686
7687 Document* doc = viewer->GetDocument();
7688 if (doc) {
7689 doc->SetFailedChannel(failedChannel);
7690 }
7691
7692 nsCOMPtr<nsIPrincipal> triggeringPrincipal;
7693 if (failedChannel) {
7694 // Make sure we have a URI to set currentURI.
7695 NS_GetFinalChannelURI(failedChannel, getter_AddRefs(failedURI));
7696 } else {
7697 // if there is no failed channel we have to explicitly provide
7698 // a triggeringPrincipal for the history entry.
7699 triggeringPrincipal = nsContentUtils::GetSystemPrincipal();
7700 }
7701
7702 if (!failedURI) {
7703 failedURI = mFailedURI;
7704 }
7705 if (!failedURI) {
7706 // We need a URI object to store a session history entry, so make up a URI
7707 NS_NewURI(getter_AddRefs(failedURI), "about:blank");
7708 }
7709
7710 // When we don't have failedURI, something wrong will happen. See
7711 // bug 291876.
7712 MOZ_ASSERT(failedURI, "We don't have a URI for history APIs.")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(failedURI)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(failedURI))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("failedURI" " (" "We don't have a URI for history APIs."
")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 7712); AnnotateMozCrashReason("MOZ_ASSERT" "(" "failedURI" ") ("
"We don't have a URI for history APIs." ")"); do { *((volatile
int*)__null) = 7712; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
7713
7714 mFailedChannel = nullptr;
7715 mFailedURI = nullptr;
7716
7717 // Create an shistory entry for the old load.
7718 if (failedURI) {
7719 errorOnLocationChangeNeeded =
7720 OnNewURI(failedURI, failedChannel, triggeringPrincipal, nullptr,
7721 nullptr, nullptr, false, false);
7722 }
7723
7724 // Be sure to have a correct mLSHE, it may have been cleared by
7725 // EndPageLoad. See bug 302115.
7726 ChildSHistory* shistory = GetSessionHistory();
7727 if (!mozilla::SessionHistoryInParent() && shistory && !mLSHE) {
7728 int32_t idx = shistory->LegacySHistory()->GetRequestedIndex();
7729 if (idx == -1) {
7730 idx = shistory->Index();
7731 }
7732 shistory->LegacySHistory()->GetEntryAtIndex(idx, getter_AddRefs(mLSHE));
7733 }
7734
7735 mLoadType = LOAD_ERROR_PAGE;
7736 }
7737
7738 nsCOMPtr<nsIURI> finalURI;
7739 // If this a redirect, use the final url (uri)
7740 // else use the original url
7741 //
7742 // Note that this should match what documents do (see Document::Reset).
7743 NS_GetFinalChannelURI(aOpenedChannel, getter_AddRefs(finalURI));
7744
7745 bool onLocationChangeNeeded = false;
7746 if (finalURI) {
7747 // Pass false for aCloneSHChildren, since we're loading a new page here.
7748 onLocationChangeNeeded = OnNewURI(finalURI, aOpenedChannel, nullptr,
7749 nullptr, nullptr, nullptr, true, false);
7750 }
7751
7752 // let's try resetting the load group if we need to...
7753 nsCOMPtr<nsILoadGroup> currentLoadGroup;
7754 NS_ENSURE_SUCCESS(do { nsresult __rv = aOpenedChannel->GetLoadGroup(getter_AddRefs
(currentLoadGroup)); 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", "aOpenedChannel->GetLoadGroup(getter_AddRefs(currentLoadGroup))"
, "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/docshell/base/nsDocShell.cpp"
, 7756); return NS_ERROR_FAILURE; } } while (false)
7755 aOpenedChannel->GetLoadGroup(getter_AddRefs(currentLoadGroup)),do { nsresult __rv = aOpenedChannel->GetLoadGroup(getter_AddRefs
(currentLoadGroup)); 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", "aOpenedChannel->GetLoadGroup(getter_AddRefs(currentLoadGroup))"
, "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/docshell/base/nsDocShell.cpp"
, 7756); return NS_ERROR_FAILURE; } } while (false)
7756 NS_ERROR_FAILURE)do { nsresult __rv = aOpenedChannel->GetLoadGroup(getter_AddRefs
(currentLoadGroup)); 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", "aOpenedChannel->GetLoadGroup(getter_AddRefs(currentLoadGroup))"
, "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/docshell/base/nsDocShell.cpp"
, 7756); return NS_ERROR_FAILURE; } } while (false)
;
7757
7758 if (currentLoadGroup != mLoadGroup) {
7759 nsLoadFlags loadFlags = 0;
7760
7761 // Cancel any URIs that are currently loading...
7762 // XXX: Need to do this eventually Stop();
7763 //
7764 // Retarget the document to this loadgroup...
7765 //
7766 /* First attach the channel to the right loadgroup
7767 * and then remove from the old loadgroup. This
7768 * puts the notifications in the right order and
7769 * we don't null-out mLSHE in OnStateChange() for
7770 * all redirected urls
7771 */
7772 aOpenedChannel->SetLoadGroup(mLoadGroup);
7773
7774 // Mark the channel as being a document URI...
7775 aOpenedChannel->GetLoadFlags(&loadFlags);
7776 loadFlags |= nsIChannel::LOAD_DOCUMENT_URI;
7777 nsCOMPtr<nsILoadInfo> loadInfo = aOpenedChannel->LoadInfo();
7778 if (SandboxFlagsImplyCookies(loadInfo->GetSandboxFlags())) {
7779 loadFlags |= nsIRequest::LOAD_DOCUMENT_NEEDS_COOKIE;
7780 }
7781
7782 aOpenedChannel->SetLoadFlags(loadFlags);
7783
7784 mLoadGroup->AddRequest(aRequest, nullptr);
7785 if (currentLoadGroup) {
7786 currentLoadGroup->RemoveRequest(aRequest, nullptr, NS_BINDING_RETARGETED);
7787 }
7788
7789 // Update the notification callbacks, so that progress and
7790 // status information are sent to the right docshell...
7791 aOpenedChannel->SetNotificationCallbacks(this);
7792 }
7793
7794 NS_ENSURE_SUCCESS(Embed(viewer, nullptr, false,do { nsresult __rv = Embed(viewer, nullptr, false, ShouldAddToSessionHistory
(finalURI, aOpenedChannel), aOpenedChannel, previousURI); 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", "Embed(viewer, nullptr, false, ShouldAddToSessionHistory(finalURI, aOpenedChannel), aOpenedChannel, previousURI)"
, "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/docshell/base/nsDocShell.cpp"
, 7797); return NS_ERROR_FAILURE; } } while (false)
7795 ShouldAddToSessionHistory(finalURI, aOpenedChannel),do { nsresult __rv = Embed(viewer, nullptr, false, ShouldAddToSessionHistory
(finalURI, aOpenedChannel), aOpenedChannel, previousURI); 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", "Embed(viewer, nullptr, false, ShouldAddToSessionHistory(finalURI, aOpenedChannel), aOpenedChannel, previousURI)"
, "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/docshell/base/nsDocShell.cpp"
, 7797); return NS_ERROR_FAILURE; } } while (false)
7796 aOpenedChannel, previousURI),do { nsresult __rv = Embed(viewer, nullptr, false, ShouldAddToSessionHistory
(finalURI, aOpenedChannel), aOpenedChannel, previousURI); 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", "Embed(viewer, nullptr, false, ShouldAddToSessionHistory(finalURI, aOpenedChannel), aOpenedChannel, previousURI)"
, "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/docshell/base/nsDocShell.cpp"
, 7797); return NS_ERROR_FAILURE; } } while (false)
7797 NS_ERROR_FAILURE)do { nsresult __rv = Embed(viewer, nullptr, false, ShouldAddToSessionHistory
(finalURI, aOpenedChannel), aOpenedChannel, previousURI); 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", "Embed(viewer, nullptr, false, ShouldAddToSessionHistory(finalURI, aOpenedChannel), aOpenedChannel, previousURI)"
, "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/docshell/base/nsDocShell.cpp"
, 7797); return NS_ERROR_FAILURE; } } while (false)
;
7798
7799 if (!mBrowsingContext->GetHasLoadedNonInitialDocument()) {
7800 MOZ_ALWAYS_SUCCEEDS(mBrowsingContext->SetHasLoadedNonInitialDocument(true))do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(mBrowsingContext->SetHasLoadedNonInitialDocument(true))),
1)))), 1))) { } else { do { static_assert( mozilla::detail::
AssertionConditionType<decltype(false)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("false" " (" "NS_SUCCEEDED(mBrowsingContext->SetHasLoadedNonInitialDocument(true))"
")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 7800); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "false"
") (" "NS_SUCCEEDED(mBrowsingContext->SetHasLoadedNonInitialDocument(true))"
")"); do { *((volatile int*)__null) = 7800; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
7801 }
7802
7803 mSavedRefreshURIList = nullptr;
7804 mSavingOldViewer = false;
7805 mEODForCurrentDocument = false;
7806
7807 // if this document is part of a multipart document,
7808 // the ID can be used to distinguish it from the other parts.
7809 nsCOMPtr<nsIMultiPartChannel> multiPartChannel(do_QueryInterface(aRequest));
7810 if (multiPartChannel) {
7811 if (PresShell* presShell = GetPresShell()) {
7812 if (Document* doc = presShell->GetDocument()) {
7813 uint32_t partID;
7814 multiPartChannel->GetPartID(&partID);
7815 doc->SetPartID(partID);
7816 }
7817 }
7818 }
7819
7820 if (errorOnLocationChangeNeeded) {
7821 FireOnLocationChange(this, failedChannel, failedURI,
7822 LOCATION_CHANGE_ERROR_PAGE);
7823 } else if (onLocationChangeNeeded) {
7824 uint32_t locationFlags =
7825 (mLoadType & LOAD_CMD_RELOAD) ? uint32_t(LOCATION_CHANGE_RELOAD) : 0;
7826 FireOnLocationChange(this, aRequest, mCurrentURI, locationFlags);
7827 }
7828
7829 return NS_OK;
7830}
7831
7832nsresult nsDocShell::NewDocumentViewerObj(const nsACString& aContentType,
7833 nsIRequest* aRequest,
7834 nsILoadGroup* aLoadGroup,
7835 nsIStreamListener** aContentHandler,
7836 nsIDocumentViewer** aViewer) {
7837 nsCOMPtr<nsIChannel> aOpenedChannel = do_QueryInterface(aRequest);
7838
7839 nsCOMPtr<nsIDocumentLoaderFactory> docLoaderFactory =
7840 nsContentUtils::FindInternalDocumentViewer(aContentType);
7841 if (!docLoaderFactory) {
7842 return NS_ERROR_FAILURE;
7843 }
7844
7845 // Now create an instance of the content viewer nsLayoutDLF makes the
7846 // determination if it should be a "view-source" instead of "view"
7847 nsresult rv = docLoaderFactory->CreateInstance(
7848 "view", aOpenedChannel, aLoadGroup, aContentType, this, nullptr,
7849 aContentHandler, aViewer);
7850 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/docshell/base/nsDocShell.cpp"
, 7850); return rv; } } while (false)
;
7851
7852 (*aViewer)->SetContainer(this);
7853 return NS_OK;
7854}
7855
7856nsresult nsDocShell::SetupNewViewer(nsIDocumentViewer* aNewViewer,
7857 WindowGlobalChild* aWindowActor) {
7858 MOZ_ASSERT(!mIsBeingDestroyed)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mIsBeingDestroyed)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mIsBeingDestroyed))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("!mIsBeingDestroyed"
, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 7858); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mIsBeingDestroyed"
")"); do { *((volatile int*)__null) = 7858; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7859
7860 //
7861 // Copy content viewer state from previous or parent content viewer.
7862 //
7863 // The following logic is mirrored in nsHTMLDocument::StartDocumentLoad!
7864 //
7865 // Do NOT to maintain a reference to the old content viewer outside
7866 // of this "copying" block, or it will not be destroyed until the end of
7867 // this routine and all <SCRIPT>s and event handlers fail! (bug 20315)
7868 //
7869 // In this block of code, if we get an error result, we return it
7870 // but if we get a null pointer, that's perfectly legal for parent
7871 // and parentContentViewer.
7872 //
7873
7874 int32_t x = 0;
7875 int32_t y = 0;
7876 int32_t cx = 0;
7877 int32_t cy = 0;
7878
7879 // This will get the size from the current content viewer or from the
7880 // Init settings
7881 DoGetPositionAndSize(&x, &y, &cx, &cy);
7882
7883 nsCOMPtr<nsIDocShellTreeItem> parentAsItem;
7884 NS_ENSURE_SUCCESS(GetInProcessSameTypeParent(getter_AddRefs(parentAsItem)),do { nsresult __rv = GetInProcessSameTypeParent(getter_AddRefs
(parentAsItem)); 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", "GetInProcessSameTypeParent(getter_AddRefs(parentAsItem))"
, "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/docshell/base/nsDocShell.cpp"
, 7885); return NS_ERROR_FAILURE; } } while (false)
7885 NS_ERROR_FAILURE)do { nsresult __rv = GetInProcessSameTypeParent(getter_AddRefs
(parentAsItem)); 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", "GetInProcessSameTypeParent(getter_AddRefs(parentAsItem))"
, "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/docshell/base/nsDocShell.cpp"
, 7885); return NS_ERROR_FAILURE; } } while (false)
;
7886 nsCOMPtr<nsIDocShell> parent(do_QueryInterface(parentAsItem));
7887
7888 const Encoding* reloadEncoding = nullptr;
7889 int32_t reloadEncodingSource = kCharsetUninitialized;
7890 // |newMUDV| also serves as a flag to set the data from the above vars
7891 nsCOMPtr<nsIDocumentViewer> newViewer;
7892
7893 if (mDocumentViewer || parent) {
7894 nsCOMPtr<nsIDocumentViewer> oldViewer;
7895 if (mDocumentViewer) {
7896 // Get any interesting state from old content viewer
7897 // XXX: it would be far better to just reuse the document viewer ,
7898 // since we know we're just displaying the same document as before
7899 oldViewer = mDocumentViewer;
7900
7901 // Tell the old content viewer to hibernate in session history when
7902 // it is destroyed.
7903
7904 if (mSavingOldViewer && NS_FAILED(CaptureState())((bool)(__builtin_expect(!!(NS_FAILED_impl(CaptureState())), 0
)))
) {
7905 if (mOSHE) {
7906 mOSHE->SyncPresentationState();
7907 }
7908 mSavingOldViewer = false;
7909 }
7910 } else {
7911 // No old content viewer, so get state from parent's content viewer
7912 parent->GetDocViewer(getter_AddRefs(oldViewer));
7913 }
7914
7915 if (oldViewer) {
7916 newViewer = aNewViewer;
7917 if (newViewer) {
7918 reloadEncoding =
7919 oldViewer->GetReloadEncodingAndSource(&reloadEncodingSource);
7920 }
7921 }
7922 }
7923
7924 nscolor bgcolor = NS_RGBA(0, 0, 0, 0)((nscolor)(((0) << 24) | ((0) << 16) | ((0) <<
8) | (0)))
;
7925 bool isUnderHiddenEmbedderElement = false;
7926 // Ensure that the content viewer is destroyed *after* the GC - bug 71515
7927 nsCOMPtr<nsIDocumentViewer> viewer = mDocumentViewer;
7928 if (viewer) {
7929 // Stop any activity that may be happening in the old document before
7930 // releasing it...
7931 viewer->Stop();
7932
7933 // Try to extract the canvas background color from the old
7934 // presentation shell, so we can use it for the next document.
7935 if (PresShell* presShell = viewer->GetPresShell()) {
7936 bgcolor = presShell->GetCanvasBackground();
7937 isUnderHiddenEmbedderElement = presShell->IsUnderHiddenEmbedderElement();
7938 }
7939
7940 viewer->Close(mSavingOldViewer ? mOSHE.get() : nullptr);
7941 aNewViewer->SetPreviousViewer(viewer);
7942 }
7943 if (mOSHE && (!mDocumentViewer || !mSavingOldViewer)) {
7944 // We don't plan to save a viewer in mOSHE; tell it to drop
7945 // any other state it's holding.
7946 mOSHE->SyncPresentationState();
7947 }
7948
7949 mDocumentViewer = nullptr;
7950
7951 // Now that we're about to switch documents, forget all of our children.
7952 // Note that we cached them as needed up in CaptureState above.
7953 DestroyChildren();
7954
7955 mDocumentViewer = aNewViewer;
7956
7957 nsCOMPtr<nsIWidget> widget;
7958 NS_ENSURE_SUCCESS(GetMainWidget(getter_AddRefs(widget)), NS_ERROR_FAILURE)do { nsresult __rv = GetMainWidget(getter_AddRefs(widget)); 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", "GetMainWidget(getter_AddRefs(widget))"
, "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/docshell/base/nsDocShell.cpp"
, 7958); return NS_ERROR_FAILURE; } } while (false)
;
7959
7960 nsIntRect bounds(x, y, cx, cy);
7961
7962 mDocumentViewer->SetNavigationTiming(mTiming);
7963
7964 if (NS_FAILED(mDocumentViewer->Init(widget, bounds, aWindowActor))((bool)(__builtin_expect(!!(NS_FAILED_impl(mDocumentViewer->
Init(widget, bounds, aWindowActor))), 0)))
) {
7965 nsCOMPtr<nsIDocumentViewer> viewer = mDocumentViewer;
7966 viewer->Close(nullptr);
7967 viewer->Destroy();
7968 mDocumentViewer = nullptr;
7969 SetCurrentURIInternal(nullptr);
7970 NS_WARNING("ContentViewer Initialization failed")NS_DebugBreak(NS_DEBUG_WARNING, "ContentViewer Initialization failed"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 7970)
;
7971 return NS_ERROR_FAILURE;
7972 }
7973
7974 // If we have old state to copy, set the old state onto the new content
7975 // viewer
7976 if (newViewer) {
7977 newViewer->SetReloadEncodingAndSource(reloadEncoding, reloadEncodingSource);
7978 }
7979
7980 NS_ENSURE_TRUE(mDocumentViewer, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(mDocumentViewer)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "mDocumentViewer" ") failed"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 7980); return NS_ERROR_FAILURE; } } while (false)
;
7981
7982 // Stuff the bgcolor from the old pres shell into the new
7983 // pres shell. This improves page load continuity.
7984 if (RefPtr<PresShell> presShell = mDocumentViewer->GetPresShell()) {
7985 presShell->SetCanvasBackground(bgcolor);
7986 presShell->ActivenessMaybeChanged();
7987 if (isUnderHiddenEmbedderElement) {
7988 presShell->SetIsUnderHiddenEmbedderElement(isUnderHiddenEmbedderElement);
7989 }
7990 }
7991
7992 // XXX: It looks like the LayoutState gets restored again in Embed()
7993 // right after the call to SetupNewViewer(...)
7994
7995 // We don't show the mDocumentViewer yet, since we want to draw the old page
7996 // until we have enough of the new page to show. Just return with the new
7997 // viewer still set to hidden.
7998
7999 return NS_OK;
8000}
8001
8002void nsDocShell::SetDocCurrentStateObj(nsISHEntry* aShEntry,
8003 SessionHistoryInfo* aInfo) {
8004 NS_ENSURE_TRUE_VOID(mDocumentViewer)do { if ((__builtin_expect(!!(!(mDocumentViewer)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "mDocumentViewer" ") failed"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 8004); return; } } while (false)
;
8005
8006 RefPtr<Document> document = GetDocument();
8007 NS_ENSURE_TRUE_VOID(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/docshell/base/nsDocShell.cpp"
, 8007); return; } } while (false)
;
8008
8009 nsCOMPtr<nsIStructuredCloneContainer> scContainer;
8010 if (mozilla::SessionHistoryInParent()) {
8011 // If aInfo is null, just set the document's state object to null.
8012 if (aInfo) {
8013 scContainer = aInfo->GetStateData();
8014 }
8015 MOZ_LOG(gSHLog, LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = gSHLog; if
((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "nsDocShell %p SetCurrentDocState %p", this
, scContainer.get()); } } while (0)
8016 ("nsDocShell %p SetCurrentDocState %p", this, scContainer.get()))do { const ::mozilla::LogModule* moz_real_module = gSHLog; if
((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "nsDocShell %p SetCurrentDocState %p", this
, scContainer.get()); } } while (0)
;
8017 } else {
8018 if (aShEntry) {
8019 scContainer = aShEntry->GetStateData();
8020
8021 // If aShEntry is null, just set the document's state object to null.
8022 }
8023 }
8024
8025 // It's OK for scContainer too be null here; that just means there's no
8026 // state data associated with this history entry.
8027 document->SetStateObject(scContainer);
8028}
8029
8030nsresult nsDocShell::CheckLoadingPermissions() {
8031 // This method checks whether the caller may load content into
8032 // this docshell. Even though we've done our best to hide windows
8033 // from code that doesn't have the right to access them, it's
8034 // still possible for an evil site to open a window and access
8035 // frames in the new window through window.frames[] (which is
8036 // allAccess for historic reasons), so we still need to do this
8037 // check on load.
8038 nsresult rv = NS_OK;
8039
8040 if (!IsSubframe()) {
8041 // We're not a frame. Permit all loads.
8042 return rv;
8043 }
8044
8045 // Note - The check for a current JSContext here isn't necessarily sensical.
8046 // It's just designed to preserve the old semantics during a mass-conversion
8047 // patch.
8048 if (!nsContentUtils::GetCurrentJSContext()) {
8049 return NS_OK;
8050 }
8051
8052 // Check if the caller is from the same origin as this docshell,
8053 // or any of its ancestors.
8054 for (RefPtr<BrowsingContext> bc = mBrowsingContext; bc;
8055 bc = bc->GetParent()) {
8056 // If the BrowsingContext is not in process, then it
8057 // is true by construction that its principal will not
8058 // subsume the current docshell principal.
8059 if (!bc->IsInProcess()) {
8060 continue;
8061 }
8062
8063 nsCOMPtr<nsIScriptGlobalObject> sgo =
8064 bc->GetDocShell()->GetScriptGlobalObject();
8065 nsCOMPtr<nsIScriptObjectPrincipal> sop(do_QueryInterface(sgo));
8066
8067 nsIPrincipal* p;
8068 if (!sop || !(p = sop->GetPrincipal())) {
8069 return NS_ERROR_UNEXPECTED;
8070 }
8071
8072 if (nsContentUtils::SubjectPrincipal()->Subsumes(p)) {
8073 // Same origin, permit load
8074 return NS_OK;
8075 }
8076 }
8077
8078 return NS_ERROR_DOM_PROP_ACCESS_DENIED;
8079}
8080
8081//*****************************************************************************
8082// nsDocShell: Site Loading
8083//*****************************************************************************
8084
8085void nsDocShell::CopyFavicon(nsIURI* aOldURI, nsIURI* aNewURI,
8086 bool aInPrivateBrowsing) {
8087 if (XRE_IsContentProcess()) {
8088 dom::ContentChild* contentChild = dom::ContentChild::GetSingleton();
8089 if (contentChild) {
8090 contentChild->SendCopyFavicon(aOldURI, aNewURI, aInPrivateBrowsing);
8091 }
8092 return;
8093 }
8094
8095#ifdef MOZ_PLACES1
8096 nsCOMPtr<nsIFaviconService> favSvc =
8097 do_GetService("@mozilla.org/browser/favicon-service;1");
8098 if (favSvc) {
8099 favSvc->CopyFavicons(aOldURI, aNewURI,
8100 aInPrivateBrowsing
8101 ? nsIFaviconService::FAVICON_LOAD_PRIVATE
8102 : nsIFaviconService::FAVICON_LOAD_NON_PRIVATE,
8103 nullptr);
8104 }
8105#endif
8106}
8107
8108class InternalLoadEvent : public Runnable {
8109 public:
8110 InternalLoadEvent(nsDocShell* aDocShell, nsDocShellLoadState* aLoadState)
8111 : mozilla::Runnable("InternalLoadEvent"),
8112 mDocShell(aDocShell),
8113 mLoadState(aLoadState) {
8114 // For events, both target and filename should be the version of "null" they
8115 // expect. By the time the event is fired, both window targeting and file
8116 // downloading have been handled, so we should never have an internal load
8117 // event that retargets or had a download.
8118 mLoadState->SetTarget(u""_ns);
8119 mLoadState->SetFileName(VoidString());
8120 }
8121
8122 NS_IMETHODvirtual nsresult
8123 Run() override {
8124#ifndef ANDROID
8125 MOZ_ASSERT(mLoadState->TriggeringPrincipal(),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mLoadState->TriggeringPrincipal())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mLoadState->TriggeringPrincipal
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("mLoadState->TriggeringPrincipal()" " (" "InternalLoadEvent: Should always have a principal here"
")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 8126); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mLoadState->TriggeringPrincipal()"
") (" "InternalLoadEvent: Should always have a principal here"
")"); do { *((volatile int*)__null) = 8126; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
8126 "InternalLoadEvent: Should always have a principal here")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mLoadState->TriggeringPrincipal())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mLoadState->TriggeringPrincipal
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("mLoadState->TriggeringPrincipal()" " (" "InternalLoadEvent: Should always have a principal here"
")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 8126); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mLoadState->TriggeringPrincipal()"
") (" "InternalLoadEvent: Should always have a principal here"
")"); do { *((volatile int*)__null) = 8126; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8127#endif
8128 return mDocShell->InternalLoad(mLoadState);
8129 }
8130
8131 private:
8132 RefPtr<nsDocShell> mDocShell;
8133 RefPtr<nsDocShellLoadState> mLoadState;
8134};
8135
8136/**
8137 * Returns true if we started an asynchronous load (i.e., from the network), but
8138 * the document we're loading there hasn't yet become this docshell's active
8139 * document.
8140 *
8141 * When JustStartedNetworkLoad is true, you should be careful about modifying
8142 * mLoadType and mLSHE. These are both set when the asynchronous load first
8143 * starts, and the load expects that, when it eventually runs InternalLoad,
8144 * mLoadType and mLSHE will have their original values.
8145 */
8146bool nsDocShell::JustStartedNetworkLoad() {
8147 return mDocumentRequest && mDocumentRequest != GetCurrentDocChannel();
8148}
8149
8150// The contentType will be INTERNAL_(I)FRAME if this docshell is for a
8151// non-toplevel browsing context in spec terms. (frame, iframe, <object>,
8152// <embed>, etc)
8153//
8154// This return value will be used when we call NS_CheckContentLoadPolicy, and
8155// later when we call DoURILoad.
8156nsContentPolicyType nsDocShell::DetermineContentType() {
8157 if (!IsSubframe()) {
8158 return nsIContentPolicy::TYPE_DOCUMENT;
8159 }
8160
8161 const auto& maybeEmbedderElementType =
8162 GetBrowsingContext()->GetEmbedderElementType();
8163 if (!maybeEmbedderElementType) {
8164 // If the EmbedderElementType hasn't been set yet, just assume we're
8165 // an iframe since that's more common.
8166 return nsIContentPolicy::TYPE_INTERNAL_IFRAME;
8167 }
8168
8169 return maybeEmbedderElementType->EqualsLiteral("iframe")
8170 ? nsIContentPolicy::TYPE_INTERNAL_IFRAME
8171 : nsIContentPolicy::TYPE_INTERNAL_FRAME;
8172}
8173
8174bool nsDocShell::NoopenerForceEnabled() {
8175 // If current's top-level browsing context's active document's
8176 // cross-origin-opener-policy is "same-origin" or "same-origin + COEP" then
8177 // if currentDoc's origin is not same origin with currentDoc's top-level
8178 // origin, noopener is force enabled, and name is cleared to "_blank".
8179 auto topPolicy = mBrowsingContext->Top()->GetOpenerPolicy();
8180 return (topPolicy == nsILoadInfo::OPENER_POLICY_SAME_ORIGIN ||
8181 topPolicy ==
8182 nsILoadInfo::
8183 OPENER_POLICY_SAME_ORIGIN_EMBEDDER_POLICY_REQUIRE_CORP) &&
8184 !mBrowsingContext->SameOriginWithTop();
8185}
8186
8187nsresult nsDocShell::PerformRetargeting(nsDocShellLoadState* aLoadState) {
8188 MOZ_ASSERT(aLoadState, "need a load state!")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aLoadState)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aLoadState))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("aLoadState" " (" "need a load state!"
")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 8188); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState"
") (" "need a load state!" ")"); do { *((volatile int*)__null
) = 8188; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
;
8189 MOZ_ASSERT(!aLoadState->Target().IsEmpty(), "should have a target here!")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aLoadState->Target().IsEmpty())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!aLoadState->Target().IsEmpty
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!aLoadState->Target().IsEmpty()" " (" "should have a target here!"
")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 8189); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aLoadState->Target().IsEmpty()"
") (" "should have a target here!" ")"); do { *((volatile int
*)__null) = 8189; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
8190 MOZ_ASSERT(aLoadState->TargetBrowsingContext().IsNull(),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aLoadState->TargetBrowsingContext().IsNull())>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(aLoadState->TargetBrowsingContext().IsNull()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("aLoadState->TargetBrowsingContext().IsNull()"
" (" "should not have picked target yet" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 8191); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->TargetBrowsingContext().IsNull()"
") (" "should not have picked target yet" ")"); do { *((volatile
int*)__null) = 8191; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
8191 "should not have picked target yet")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aLoadState->TargetBrowsingContext().IsNull())>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(aLoadState->TargetBrowsingContext().IsNull()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("aLoadState->TargetBrowsingContext().IsNull()"
" (" "should not have picked target yet" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 8191); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->TargetBrowsingContext().IsNull()"
") (" "should not have picked target yet" ")"); do { *((volatile
int*)__null) = 8191; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
8192
8193 nsresult rv = NS_OK;
8194 RefPtr<BrowsingContext> targetContext;
8195
8196 // Only _self, _parent, and _top are supported in noopener case. But we
8197 // have to be careful to not apply that to the noreferrer case. See bug
8198 // 1358469.
8199 bool allowNamedTarget =
8200 !aLoadState->HasInternalLoadFlags(INTERNAL_LOAD_FLAGS_NO_OPENER) ||
8201 aLoadState->HasInternalLoadFlags(INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER);
8202 if (allowNamedTarget ||
8203 aLoadState->Target().LowerCaseEqualsLiteral("_self") ||
8204 aLoadState->Target().LowerCaseEqualsLiteral("_parent") ||
8205 aLoadState->Target().LowerCaseEqualsLiteral("_top")) {
8206 Document* document = GetDocument();
8207 NS_ENSURE_TRUE(document, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(document)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "document" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 8207); return NS_ERROR_FAILURE; } } while (false)
;
8208 WindowGlobalChild* wgc = document->GetWindowGlobalChild();
8209 NS_ENSURE_TRUE(wgc, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(wgc)), 0))) { NS_DebugBreak(NS_DEBUG_WARNING
, "NS_ENSURE_TRUE(" "wgc" ") failed", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 8209); return NS_ERROR_FAILURE; } } while (false)
;
8210 targetContext = wgc->FindBrowsingContextWithName(
8211 aLoadState->Target(), /* aUseEntryGlobalForAccessCheck */ false);
8212 }
8213
8214 if (!targetContext) {
8215 // If the targetContext doesn't exist, then this is a new docShell and we
8216 // should consider this a TYPE_DOCUMENT load
8217 //
8218 // For example, when target="_blank"
8219
8220 // If there's no targetContext, that means we are about to create a new
8221 // window. Perform a content policy check before creating the window. Please
8222 // note for all other docshell loads content policy checks are performed
8223 // within the contentSecurityManager when the channel is about to be
8224 // openend.
8225 nsISupports* requestingContext = nullptr;
8226 if (XRE_IsContentProcess()) {
8227 // In e10s the child process doesn't have access to the element that
8228 // contains the browsing context (because that element is in the chrome
8229 // process). So we just pass mScriptGlobal.
8230 requestingContext = ToSupports(mScriptGlobal);
8231 } else {
8232 // This is for loading non-e10s tabs and toplevel windows of various
8233 // sorts.
8234 // For the toplevel window cases, requestingElement will be null.
8235 nsCOMPtr<Element> requestingElement =
8236 mScriptGlobal->GetFrameElementInternal();
8237 requestingContext = requestingElement;
8238 }
8239
8240 // Ideally we should use the same loadinfo as within DoURILoad which
8241 // should match this one when both are applicable.
8242 nsCOMPtr<nsILoadInfo> secCheckLoadInfo =
8243 new LoadInfo(mScriptGlobal, aLoadState->URI(),
8244 aLoadState->TriggeringPrincipal(), requestingContext,
8245 nsILoadInfo::SEC_ONLY_FOR_EXPLICIT_CONTENTSEC_CHECK, 0);
8246
8247 // Since Content Policy checks are performed within docShell as well as
8248 // the ContentSecurityManager we need a reliable way to let certain
8249 // nsIContentPolicy consumers ignore duplicate calls.
8250 secCheckLoadInfo->SetSkipContentPolicyCheckForWebRequest(true);
8251
8252 int16_t shouldLoad = nsIContentPolicy::ACCEPT;
8253 rv = NS_CheckContentLoadPolicy(aLoadState->URI(), secCheckLoadInfo,
8254 &shouldLoad);
8255
8256 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) || NS_CP_REJECTED(shouldLoad)((shouldLoad) != nsIContentPolicy::ACCEPT)) {
8257 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
8258 if (shouldLoad == nsIContentPolicy::REJECT_TYPE) {
8259 return NS_ERROR_CONTENT_BLOCKED_SHOW_ALT;
8260 }
8261 if (shouldLoad == nsIContentPolicy::REJECT_POLICY) {
8262 return NS_ERROR_BLOCKED_BY_POLICY;
8263 }
8264 }
8265
8266 return NS_ERROR_CONTENT_BLOCKED;
8267 }
8268 }
8269
8270 //
8271 // Resolve the window target before going any further...
8272 // If the load has been targeted to another DocShell, then transfer the
8273 // load to it...
8274 //
8275
8276 // We've already done our owner-inheriting. Mask out that bit, so we
8277 // don't try inheriting an owner from the target window if we came up
8278 // with a null owner above.
8279 aLoadState->UnsetInternalLoadFlag(INTERNAL_LOAD_FLAGS_INHERIT_PRINCIPAL);
8280
8281 if (!targetContext) {
8282 // If the docshell's document is sandboxed, only open a new window
8283 // if the document's SANDBOXED_AUXILLARY_NAVIGATION flag is not set.
8284 // (i.e. if allow-popups is specified)
8285 NS_ENSURE_TRUE(mDocumentViewer, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(mDocumentViewer)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "mDocumentViewer" ") failed"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 8285); return NS_ERROR_FAILURE; } } while (false)
;
8286 Document* doc = mDocumentViewer->GetDocument();
8287
8288 const bool isDocumentAuxSandboxed =
8289 doc && (doc->GetSandboxFlags() & SANDBOXED_AUXILIARY_NAVIGATION);
8290
8291 if (isDocumentAuxSandboxed) {
8292 return NS_ERROR_DOM_INVALID_ACCESS_ERR;
8293 }
8294
8295 nsCOMPtr<nsPIDOMWindowOuter> win = GetWindow();
8296 NS_ENSURE_TRUE(win, NS_ERROR_NOT_AVAILABLE)do { if ((__builtin_expect(!!(!(win)), 0))) { NS_DebugBreak(NS_DEBUG_WARNING
, "NS_ENSURE_TRUE(" "win" ") failed", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 8296); return NS_ERROR_NOT_AVAILABLE; } } while (false)
;
8297
8298 RefPtr<BrowsingContext> newBC;
8299 nsAutoCString spec;
8300 aLoadState->URI()->GetSpec(spec);
8301
8302 // If we are a noopener load, we just hand the whole thing over to our
8303 // window.
8304 if (aLoadState->HasInternalLoadFlags(INTERNAL_LOAD_FLAGS_NO_OPENER) ||
8305 NoopenerForceEnabled()) {
8306 // Various asserts that we know to hold because NO_OPENER loads can only
8307 // happen for links.
8308 MOZ_ASSERT(!aLoadState->LoadReplace())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aLoadState->LoadReplace())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!aLoadState->LoadReplace(
)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!aLoadState->LoadReplace()", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 8308); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aLoadState->LoadReplace()"
")"); do { *((volatile int*)__null) = 8308; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8309 MOZ_ASSERT(aLoadState->PrincipalToInherit() ==do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aLoadState->PrincipalToInherit() == aLoadState->
TriggeringPrincipal())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aLoadState->PrincipalToInherit
() == aLoadState->TriggeringPrincipal()))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aLoadState->PrincipalToInherit() == aLoadState->TriggeringPrincipal()"
, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 8310); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->PrincipalToInherit() == aLoadState->TriggeringPrincipal()"
")"); do { *((volatile int*)__null) = 8310; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
8310 aLoadState->TriggeringPrincipal())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aLoadState->PrincipalToInherit() == aLoadState->
TriggeringPrincipal())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aLoadState->PrincipalToInherit
() == aLoadState->TriggeringPrincipal()))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aLoadState->PrincipalToInherit() == aLoadState->TriggeringPrincipal()"
, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 8310); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->PrincipalToInherit() == aLoadState->TriggeringPrincipal()"
")"); do { *((volatile int*)__null) = 8310; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8311 MOZ_ASSERT(!(aLoadState->InternalLoadFlags() &do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!(aLoadState->InternalLoadFlags() & ~(INTERNAL_LOAD_FLAGS_NO_OPENER
| INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER)))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!(aLoadState->InternalLoadFlags
() & ~(INTERNAL_LOAD_FLAGS_NO_OPENER | INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER
))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!(aLoadState->InternalLoadFlags() & ~(INTERNAL_LOAD_FLAGS_NO_OPENER | INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER))"
" (" "Only INTERNAL_LOAD_FLAGS_NO_OPENER and " "INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER can be set"
")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 8315); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!(aLoadState->InternalLoadFlags() & ~(INTERNAL_LOAD_FLAGS_NO_OPENER | INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER))"
") (" "Only INTERNAL_LOAD_FLAGS_NO_OPENER and " "INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER can be set"
")"); do { *((volatile int*)__null) = 8315; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
8312 ~(INTERNAL_LOAD_FLAGS_NO_OPENER |do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!(aLoadState->InternalLoadFlags() & ~(INTERNAL_LOAD_FLAGS_NO_OPENER
| INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER)))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!(aLoadState->InternalLoadFlags
() & ~(INTERNAL_LOAD_FLAGS_NO_OPENER | INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER
))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!(aLoadState->InternalLoadFlags() & ~(INTERNAL_LOAD_FLAGS_NO_OPENER | INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER))"
" (" "Only INTERNAL_LOAD_FLAGS_NO_OPENER and " "INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER can be set"
")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 8315); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!(aLoadState->InternalLoadFlags() & ~(INTERNAL_LOAD_FLAGS_NO_OPENER | INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER))"
") (" "Only INTERNAL_LOAD_FLAGS_NO_OPENER and " "INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER can be set"
")"); do { *((volatile int*)__null) = 8315; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
8313 INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER)),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!(aLoadState->InternalLoadFlags() & ~(INTERNAL_LOAD_FLAGS_NO_OPENER
| INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER)))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!(aLoadState->InternalLoadFlags
() & ~(INTERNAL_LOAD_FLAGS_NO_OPENER | INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER
))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!(aLoadState->InternalLoadFlags() & ~(INTERNAL_LOAD_FLAGS_NO_OPENER | INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER))"
" (" "Only INTERNAL_LOAD_FLAGS_NO_OPENER and " "INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER can be set"
")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 8315); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!(aLoadState->InternalLoadFlags() & ~(INTERNAL_LOAD_FLAGS_NO_OPENER | INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER))"
") (" "Only INTERNAL_LOAD_FLAGS_NO_OPENER and " "INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER can be set"
")"); do { *((volatile int*)__null) = 8315; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
8314 "Only INTERNAL_LOAD_FLAGS_NO_OPENER and "do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!(aLoadState->InternalLoadFlags() & ~(INTERNAL_LOAD_FLAGS_NO_OPENER
| INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER)))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!(aLoadState->InternalLoadFlags
() & ~(INTERNAL_LOAD_FLAGS_NO_OPENER | INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER
))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!(aLoadState->InternalLoadFlags() & ~(INTERNAL_LOAD_FLAGS_NO_OPENER | INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER))"
" (" "Only INTERNAL_LOAD_FLAGS_NO_OPENER and " "INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER can be set"
")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 8315); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!(aLoadState->InternalLoadFlags() & ~(INTERNAL_LOAD_FLAGS_NO_OPENER | INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER))"
") (" "Only INTERNAL_LOAD_FLAGS_NO_OPENER and " "INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER can be set"
")"); do { *((volatile int*)__null) = 8315; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
8315 "INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER can be set")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!(aLoadState->InternalLoadFlags() & ~(INTERNAL_LOAD_FLAGS_NO_OPENER
| INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER)))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!(aLoadState->InternalLoadFlags
() & ~(INTERNAL_LOAD_FLAGS_NO_OPENER | INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER
))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!(aLoadState->InternalLoadFlags() & ~(INTERNAL_LOAD_FLAGS_NO_OPENER | INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER))"
" (" "Only INTERNAL_LOAD_FLAGS_NO_OPENER and " "INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER can be set"
")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 8315); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!(aLoadState->InternalLoadFlags() & ~(INTERNAL_LOAD_FLAGS_NO_OPENER | INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER))"
") (" "Only INTERNAL_LOAD_FLAGS_NO_OPENER and " "INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER can be set"
")"); do { *((volatile int*)__null) = 8315; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8316 MOZ_ASSERT_IF(aLoadState->PostDataStream(),do { if (aLoadState->PostDataStream()) { do { static_assert
( mozilla::detail::AssertionConditionType<decltype(aLoadState
->IsFormSubmission())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aLoadState->IsFormSubmission
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("aLoadState->IsFormSubmission()", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 8317); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->IsFormSubmission()"
")"); do { *((volatile int*)__null) = 8317; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
8317 aLoadState->IsFormSubmission())do { if (aLoadState->PostDataStream()) { do { static_assert
( mozilla::detail::AssertionConditionType<decltype(aLoadState
->IsFormSubmission())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aLoadState->IsFormSubmission
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("aLoadState->IsFormSubmission()", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 8317); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->IsFormSubmission()"
")"); do { *((volatile int*)__null) = 8317; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
8318 MOZ_ASSERT(!aLoadState->HeadersStream())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aLoadState->HeadersStream())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!aLoadState->HeadersStream
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!aLoadState->HeadersStream()", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 8318); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aLoadState->HeadersStream()"
")"); do { *((volatile int*)__null) = 8318; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8319 // If OnLinkClickSync was invoked inside the onload handler, the load
8320 // type would be set to LOAD_NORMAL_REPLACE; otherwise it should be
8321 // LOAD_LINK.
8322 MOZ_ASSERT(aLoadState->LoadType() == LOAD_LINK ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aLoadState->LoadType() == LOAD_LINK || aLoadState
->LoadType() == LOAD_NORMAL_REPLACE)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aLoadState->LoadType() ==
LOAD_LINK || aLoadState->LoadType() == LOAD_NORMAL_REPLACE
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"aLoadState->LoadType() == LOAD_LINK || aLoadState->LoadType() == LOAD_NORMAL_REPLACE"
, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 8323); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->LoadType() == LOAD_LINK || aLoadState->LoadType() == LOAD_NORMAL_REPLACE"
")"); do { *((volatile int*)__null) = 8323; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
8323 aLoadState->LoadType() == LOAD_NORMAL_REPLACE)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aLoadState->LoadType() == LOAD_LINK || aLoadState
->LoadType() == LOAD_NORMAL_REPLACE)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aLoadState->LoadType() ==
LOAD_LINK || aLoadState->LoadType() == LOAD_NORMAL_REPLACE
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"aLoadState->LoadType() == LOAD_LINK || aLoadState->LoadType() == LOAD_NORMAL_REPLACE"
, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 8323); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->LoadType() == LOAD_LINK || aLoadState->LoadType() == LOAD_NORMAL_REPLACE"
")"); do { *((volatile int*)__null) = 8323; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8324 MOZ_ASSERT(!aLoadState->LoadIsFromSessionHistory())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aLoadState->LoadIsFromSessionHistory())>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(!aLoadState->LoadIsFromSessionHistory()))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("!aLoadState->LoadIsFromSessionHistory()"
, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 8324); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aLoadState->LoadIsFromSessionHistory()"
")"); do { *((volatile int*)__null) = 8324; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8325 MOZ_ASSERT(aLoadState->FirstParty())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aLoadState->FirstParty())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aLoadState->FirstParty())
)), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aLoadState->FirstParty()"
, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 8325); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->FirstParty()"
")"); do { *((volatile int*)__null) = 8325; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
; // Windowwatcher will assume this.
8326
8327 RefPtr<nsDocShellLoadState> loadState =
8328 new nsDocShellLoadState(aLoadState->URI());
8329
8330 // Set up our loadinfo so it will do the load as much like we would have
8331 // as possible.
8332 loadState->SetReferrerInfo(aLoadState->GetReferrerInfo());
8333 loadState->SetOriginalURI(aLoadState->OriginalURI());
8334
8335 Maybe<nsCOMPtr<nsIURI>> resultPrincipalURI;
8336 aLoadState->GetMaybeResultPrincipalURI(resultPrincipalURI);
8337
8338 loadState->SetMaybeResultPrincipalURI(resultPrincipalURI);
8339 loadState->SetKeepResultPrincipalURIIfSet(
8340 aLoadState->KeepResultPrincipalURIIfSet());
8341 // LoadReplace will always be false due to asserts above, skip setting
8342 // it.
8343 loadState->SetTriggeringPrincipal(aLoadState->TriggeringPrincipal());
8344 loadState->SetTriggeringSandboxFlags(
8345 aLoadState->TriggeringSandboxFlags());
8346 loadState->SetTriggeringWindowId(aLoadState->TriggeringWindowId());
8347 loadState->SetTriggeringStorageAccess(
8348 aLoadState->TriggeringStorageAccess());
8349 loadState->SetCsp(aLoadState->Csp());
8350 loadState->SetInheritPrincipal(aLoadState->HasInternalLoadFlags(
8351 INTERNAL_LOAD_FLAGS_INHERIT_PRINCIPAL));
8352 // Explicit principal because we do not want any guesses as to what the
8353 // principal to inherit is: it should be aTriggeringPrincipal.
8354 loadState->SetPrincipalIsExplicit(true);
8355 loadState->SetLoadType(aLoadState->LoadType());
8356 loadState->SetForceAllowDataURI(aLoadState->HasInternalLoadFlags(
8357 INTERNAL_LOAD_FLAGS_FORCE_ALLOW_DATA_URI));
8358
8359 loadState->SetHasValidUserGestureActivation(
8360 aLoadState->HasValidUserGestureActivation());
8361
8362 loadState->SetTextDirectiveUserActivation(
8363 aLoadState->GetTextDirectiveUserActivation());
8364
8365 // Propagate POST data to the new load.
8366 loadState->SetPostDataStream(aLoadState->PostDataStream());
8367 loadState->SetIsFormSubmission(aLoadState->IsFormSubmission());
8368
8369 rv = win->Open(spec,
8370 aLoadState->Target(), // window name
8371 u""_ns, // Features
8372 loadState,
8373 true, // aForceNoOpener
8374 getter_AddRefs(newBC));
8375 MOZ_ASSERT(!newBC)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!newBC)>::isValid, "invalid assertion condition")
; if ((__builtin_expect(!!(!(!!(!newBC))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("!newBC", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 8375); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!newBC" ")"
); do { *((volatile int*)__null) = 8375; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8376 return rv;
8377 }
8378
8379 rv = win->OpenNoNavigate(spec,
8380 aLoadState->Target(), // window name
8381 u""_ns, // Features
8382 getter_AddRefs(newBC));
8383
8384 // In some cases the Open call doesn't actually result in a new
8385 // window being opened. We can detect these cases by examining the
8386 // document in |newBC|, if any.
8387 nsCOMPtr<nsPIDOMWindowOuter> piNewWin =
8388 newBC ? newBC->GetDOMWindow() : nullptr;
8389 if (piNewWin) {
8390 RefPtr<Document> newDoc = piNewWin->GetExtantDoc();
8391 if (!newDoc || newDoc->IsInitialDocument()) {
8392 aLoadState->SetInternalLoadFlag(INTERNAL_LOAD_FLAGS_FIRST_LOAD);
8393 }
8394 }
8395
8396 if (newBC) {
8397 targetContext = newBC;
8398 }
8399 }
8400 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/docshell/base/nsDocShell.cpp"
, 8400); return rv; } } while (false)
;
8401 NS_ENSURE_TRUE(targetContext, rv)do { if ((__builtin_expect(!!(!(targetContext)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "targetContext" ") failed"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 8401); return rv; } } while (false)
;
8402
8403 // If our target BrowsingContext is still pending initialization, ignore the
8404 // navigation request targeting it.
8405 if (NS_WARN_IF(targetContext->GetPendingInitialization())NS_warn_if_impl(targetContext->GetPendingInitialization(),
"targetContext->GetPendingInitialization()", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 8405)
) {
8406 return NS_OK;
8407 }
8408
8409 aLoadState->SetTargetBrowsingContext(targetContext);
8410 if (aLoadState->IsFormSubmission()) {
8411 aLoadState->SetLoadType(
8412 GetLoadTypeForFormSubmission(targetContext, aLoadState));
8413 }
8414
8415 //
8416 // Transfer the load to the target BrowsingContext... Clear the window target
8417 // name to the empty string to prevent recursive retargeting!
8418 //
8419 // No window target
8420 aLoadState->SetTarget(u""_ns);
8421 // No forced download
8422 aLoadState->SetFileName(VoidString());
8423 return targetContext->InternalLoad(aLoadState);
8424}
8425
8426static nsAutoCString RefMaybeNull(nsIURI* aURI) {
8427 nsAutoCString result;
8428 if (NS_FAILED(aURI->GetRef(result))((bool)(__builtin_expect(!!(NS_FAILED_impl(aURI->GetRef(result
))), 0)))
) {
8429 result.SetIsVoid(true);
8430 }
8431 return result;
8432}
8433
8434uint32_t nsDocShell::GetSameDocumentNavigationFlags(nsIURI* aNewURI) {
8435 uint32_t flags = LOCATION_CHANGE_SAME_DOCUMENT;
8436
8437 bool equal = false;
8438 if (mCurrentURI &&
8439 NS_SUCCEEDED(mCurrentURI->EqualsExceptRef(aNewURI, &equal))((bool)(__builtin_expect(!!(!NS_FAILED_impl(mCurrentURI->EqualsExceptRef
(aNewURI, &equal))), 1)))
&& equal &&
8440 RefMaybeNull(mCurrentURI) != RefMaybeNull(aNewURI)) {
8441 flags |= LOCATION_CHANGE_HASHCHANGE;
8442 }
8443
8444 return flags;
8445}
8446
8447struct SameDocumentNavigationState {
8448 nsAutoCString mCurrentHash;
8449 nsAutoCString mNewHash;
8450 nsTArray<TextDirective> mTextDirectives;
8451 bool mCurrentURIHasRef = false;
8452 bool mNewURIHasRef = false;
8453 bool mSameExceptHashes = false;
8454 bool mSecureUpgradeURI = false;
8455 bool mHistoryNavBetweenSameDoc = false;
8456};
8457
8458bool nsDocShell::IsSameDocumentNavigation(nsDocShellLoadState* aLoadState,
8459 SameDocumentNavigationState& aState) {
8460 MOZ_ASSERT(aLoadState)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aLoadState)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aLoadState))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("aLoadState", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 8460); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState"
")"); do { *((volatile int*)__null) = 8460; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8461 if (!(aLoadState->LoadType() == LOAD_NORMAL ||
8462 aLoadState->LoadType() == LOAD_STOP_CONTENT ||
8463 LOAD_TYPE_HAS_FLAGS(aLoadState->LoadType(),((aLoadState->LoadType()) & ((LOAD_FLAGS_REPLACE_HISTORY
) << 16))
8464 LOAD_FLAGS_REPLACE_HISTORY)((aLoadState->LoadType()) & ((LOAD_FLAGS_REPLACE_HISTORY
) << 16))
||
8465 aLoadState->LoadType() == LOAD_HISTORY ||
8466 aLoadState->LoadType() == LOAD_LINK)) {
8467 return false;
8468 }
8469
8470 nsCOMPtr<nsIURI> currentURI = mCurrentURI;
8471
8472 nsresult rvURINew = aLoadState->URI()->GetRef(aState.mNewHash);
8473 if (NS_SUCCEEDED(rvURINew)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rvURINew)), 1)))) {
8474 rvURINew = aLoadState->URI()->GetHasRef(&aState.mNewURIHasRef);
8475 }
8476
8477 // A Fragment Directive must be removed from the new hash in order to allow
8478 // fallback element id scroll.
8479 FragmentDirective::ParseAndRemoveFragmentDirectiveFromFragmentString(
8480 aState.mNewHash, &aState.mTextDirectives, aLoadState->URI());
8481
8482 if (currentURI && NS_SUCCEEDED(rvURINew)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rvURINew)), 1)))) {
8483 nsresult rvURIOld = currentURI->GetRef(aState.mCurrentHash);
8484 if (NS_SUCCEEDED(rvURIOld)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rvURIOld)), 1)))) {
8485 rvURIOld = currentURI->GetHasRef(&aState.mCurrentURIHasRef);
8486 }
8487 if (NS_SUCCEEDED(rvURIOld)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rvURIOld)), 1)))) {
8488 if (NS_FAILED(currentURI->EqualsExceptRef(aLoadState->URI(),((bool)(__builtin_expect(!!(NS_FAILED_impl(currentURI->EqualsExceptRef
(aLoadState->URI(), &aState.mSameExceptHashes))), 0)))
8489 &aState.mSameExceptHashes))((bool)(__builtin_expect(!!(NS_FAILED_impl(currentURI->EqualsExceptRef
(aLoadState->URI(), &aState.mSameExceptHashes))), 0)))
) {
8490 aState.mSameExceptHashes = false;
8491 }
8492 }
8493 }
8494
8495 if (!aState.mSameExceptHashes && currentURI && NS_SUCCEEDED(rvURINew)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rvURINew)), 1)))) {
8496 // Maybe aLoadState->URI() came from the exposable form of currentURI?
8497 nsCOMPtr<nsIURI> currentExposableURI =
8498 nsIOService::CreateExposableURI(currentURI);
8499 nsresult rvURIOld = currentExposableURI->GetRef(aState.mCurrentHash);
8500 if (NS_SUCCEEDED(rvURIOld)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rvURIOld)), 1)))) {
8501 rvURIOld = currentExposableURI->GetHasRef(&aState.mCurrentURIHasRef);
8502 }
8503 if (NS_SUCCEEDED(rvURIOld)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rvURIOld)), 1)))) {
8504 if (NS_FAILED(currentExposableURI->EqualsExceptRef(((bool)(__builtin_expect(!!(NS_FAILED_impl(currentExposableURI
->EqualsExceptRef( aLoadState->URI(), &aState.mSameExceptHashes
))), 0)))
8505 aLoadState->URI(), &aState.mSameExceptHashes))((bool)(__builtin_expect(!!(NS_FAILED_impl(currentExposableURI
->EqualsExceptRef( aLoadState->URI(), &aState.mSameExceptHashes
))), 0)))
) {
8506 aState.mSameExceptHashes = false;
8507 }
8508 // HTTPS-Only Mode upgrades schemes from http to https in Necko, hence we
8509 // have to perform a special check here to avoid an actual navigation. If
8510 // HTTPS-Only Mode is enabled and the two URIs are same-origin (modulo the
8511 // fact that the new URI is currently http), then set mSameExceptHashes to
8512 // true and only perform a fragment navigation.
8513 if (!aState.mSameExceptHashes) {
8514 if (nsCOMPtr<nsIChannel> docChannel = GetCurrentDocChannel()) {
8515 nsCOMPtr<nsILoadInfo> docLoadInfo = docChannel->LoadInfo();
8516 if (!docLoadInfo->GetLoadErrorPage() &&
8517 nsHTTPSOnlyUtils::ShouldUpgradeConnection(docLoadInfo) &&
8518 nsHTTPSOnlyUtils::IsHttpDowngrade(currentExposableURI,
8519 aLoadState->URI())) {
8520 uint32_t status = docLoadInfo->GetHttpsOnlyStatus();
8521 if (status & (nsILoadInfo::HTTPS_ONLY_UPGRADED_LISTENER_REGISTERED |
8522 nsILoadInfo::HTTPS_ONLY_UPGRADED_HTTPS_FIRST)) {
8523 // At this point the requested URI is for sure a fragment
8524 // navigation via HTTP and HTTPS-Only mode or HTTPS-First is
8525 // enabled. Also it is not interfering the upgrade order of
8526 // https://searchfox.org/mozilla-central/source/netwerk/base/nsNetUtil.cpp#2948-2953.
8527 // Since we are on an HTTPS site the fragment
8528 // navigation should also be an HTTPS.
8529 // For that reason we should upgrade the URI to HTTPS.
8530 aState.mSecureUpgradeURI = true;
8531 aState.mSameExceptHashes = true;
8532 }
8533 }
8534 }
8535 }
8536 }
8537 }
8538
8539 if (mozilla::SessionHistoryInParent()) {
8540 if (mActiveEntry && aLoadState->LoadIsFromSessionHistory()) {
8541 aState.mHistoryNavBetweenSameDoc = mActiveEntry->SharesDocumentWith(
8542 aLoadState->GetLoadingSessionHistoryInfo()->mInfo);
8543 }
8544 MOZ_LOG(gSHLog, LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = gSHLog; if
((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "nsDocShell::IsSameDocumentNavigation %p NavBetweenSameDoc=%d"
, this, aState.mHistoryNavBetweenSameDoc); } } while (0)
8545 ("nsDocShell::IsSameDocumentNavigation %p NavBetweenSameDoc=%d",do { const ::mozilla::LogModule* moz_real_module = gSHLog; if
((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "nsDocShell::IsSameDocumentNavigation %p NavBetweenSameDoc=%d"
, this, aState.mHistoryNavBetweenSameDoc); } } while (0)
8546 this, aState.mHistoryNavBetweenSameDoc))do { const ::mozilla::LogModule* moz_real_module = gSHLog; if
((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "nsDocShell::IsSameDocumentNavigation %p NavBetweenSameDoc=%d"
, this, aState.mHistoryNavBetweenSameDoc); } } while (0)
;
8547 } else {
8548 if (mOSHE && aLoadState->LoadIsFromSessionHistory()) {
8549 // We're doing a history load.
8550
8551 mOSHE->SharesDocumentWith(aLoadState->SHEntry(),
8552 &aState.mHistoryNavBetweenSameDoc);
8553 }
8554 }
8555
8556 // A same document navigation happens when we navigate between two SHEntries
8557 // for the same document. We do a same document navigation under two
8558 // circumstances. Either
8559 //
8560 // a) we're navigating between two different SHEntries which share a
8561 // document, or
8562 //
8563 // b) we're navigating to a new shentry whose URI differs from the
8564 // current URI only in its hash, the new hash is non-empty, and
8565 // we're not doing a POST.
8566 //
8567 // The restriction that the SHEntries in (a) must be different ensures
8568 // that history.go(0) and the like trigger full refreshes, rather than
8569 // same document navigations.
8570 if (!mozilla::SessionHistoryInParent()) {
8571 bool doSameDocumentNavigation =
8572 (aState.mHistoryNavBetweenSameDoc && mOSHE != aLoadState->SHEntry()) ||
8573 (!aLoadState->SHEntry() && !aLoadState->PostDataStream() &&
8574 aState.mSameExceptHashes && aState.mNewURIHasRef);
8575 MOZ_LOG(gSHLog, LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = gSHLog; if
((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "nsDocShell %p NavBetweenSameDoc=%d is same doc = %d"
, this, aState.mHistoryNavBetweenSameDoc, doSameDocumentNavigation
); } } while (0)
8576 ("nsDocShell %p NavBetweenSameDoc=%d is same doc = %d", this,do { const ::mozilla::LogModule* moz_real_module = gSHLog; if
((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "nsDocShell %p NavBetweenSameDoc=%d is same doc = %d"
, this, aState.mHistoryNavBetweenSameDoc, doSameDocumentNavigation
); } } while (0)
8577 aState.mHistoryNavBetweenSameDoc, doSameDocumentNavigation))do { const ::mozilla::LogModule* moz_real_module = gSHLog; if
((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "nsDocShell %p NavBetweenSameDoc=%d is same doc = %d"
, this, aState.mHistoryNavBetweenSameDoc, doSameDocumentNavigation
); } } while (0)
;
8578 return doSameDocumentNavigation;
8579 }
8580
8581 if (aState.mHistoryNavBetweenSameDoc &&
8582 !aLoadState->GetLoadingSessionHistoryInfo()->mLoadingCurrentEntry) {
8583 return true;
8584 }
8585
8586 MOZ_LOG(do { const ::mozilla::LogModule* moz_real_module = gSHLog; if
((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "nsDocShell::IsSameDocumentNavigation %p !LoadIsFromSessionHistory=%s "
"!PostDataStream: %s mSameExceptHashes: %s mNewURIHasRef: %s"
, this, !aLoadState->LoadIsFromSessionHistory() ? "true" :
"false", !aLoadState->PostDataStream() ? "true" : "false"
, aState.mSameExceptHashes ? "true" : "false", aState.mNewURIHasRef
? "true" : "false"); } } while (0)
8587 gSHLog, LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = gSHLog; if
((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "nsDocShell::IsSameDocumentNavigation %p !LoadIsFromSessionHistory=%s "
"!PostDataStream: %s mSameExceptHashes: %s mNewURIHasRef: %s"
, this, !aLoadState->LoadIsFromSessionHistory() ? "true" :
"false", !aLoadState->PostDataStream() ? "true" : "false"
, aState.mSameExceptHashes ? "true" : "false", aState.mNewURIHasRef
? "true" : "false"); } } while (0)
8588 ("nsDocShell::IsSameDocumentNavigation %p !LoadIsFromSessionHistory=%s "do { const ::mozilla::LogModule* moz_real_module = gSHLog; if
((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "nsDocShell::IsSameDocumentNavigation %p !LoadIsFromSessionHistory=%s "
"!PostDataStream: %s mSameExceptHashes: %s mNewURIHasRef: %s"
, this, !aLoadState->LoadIsFromSessionHistory() ? "true" :
"false", !aLoadState->PostDataStream() ? "true" : "false"
, aState.mSameExceptHashes ? "true" : "false", aState.mNewURIHasRef
? "true" : "false"); } } while (0)
8589 "!PostDataStream: %s mSameExceptHashes: %s mNewURIHasRef: %s",do { const ::mozilla::LogModule* moz_real_module = gSHLog; if
((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "nsDocShell::IsSameDocumentNavigation %p !LoadIsFromSessionHistory=%s "
"!PostDataStream: %s mSameExceptHashes: %s mNewURIHasRef: %s"
, this, !aLoadState->LoadIsFromSessionHistory() ? "true" :
"false", !aLoadState->PostDataStream() ? "true" : "false"
, aState.mSameExceptHashes ? "true" : "false", aState.mNewURIHasRef
? "true" : "false"); } } while (0)
8590 this, !aLoadState->LoadIsFromSessionHistory() ? "true" : "false",do { const ::mozilla::LogModule* moz_real_module = gSHLog; if
((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "nsDocShell::IsSameDocumentNavigation %p !LoadIsFromSessionHistory=%s "
"!PostDataStream: %s mSameExceptHashes: %s mNewURIHasRef: %s"
, this, !aLoadState->LoadIsFromSessionHistory() ? "true" :
"false", !aLoadState->PostDataStream() ? "true" : "false"
, aState.mSameExceptHashes ? "true" : "false", aState.mNewURIHasRef
? "true" : "false"); } } while (0)
8591 !aLoadState->PostDataStream() ? "true" : "false",do { const ::mozilla::LogModule* moz_real_module = gSHLog; if
((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "nsDocShell::IsSameDocumentNavigation %p !LoadIsFromSessionHistory=%s "
"!PostDataStream: %s mSameExceptHashes: %s mNewURIHasRef: %s"
, this, !aLoadState->LoadIsFromSessionHistory() ? "true" :
"false", !aLoadState->PostDataStream() ? "true" : "false"
, aState.mSameExceptHashes ? "true" : "false", aState.mNewURIHasRef
? "true" : "false"); } } while (0)
8592 aState.mSameExceptHashes ? "true" : "false",do { const ::mozilla::LogModule* moz_real_module = gSHLog; if
((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "nsDocShell::IsSameDocumentNavigation %p !LoadIsFromSessionHistory=%s "
"!PostDataStream: %s mSameExceptHashes: %s mNewURIHasRef: %s"
, this, !aLoadState->LoadIsFromSessionHistory() ? "true" :
"false", !aLoadState->PostDataStream() ? "true" : "false"
, aState.mSameExceptHashes ? "true" : "false", aState.mNewURIHasRef
? "true" : "false"); } } while (0)
8593 aState.mNewURIHasRef ? "true" : "false"))do { const ::mozilla::LogModule* moz_real_module = gSHLog; if
((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "nsDocShell::IsSameDocumentNavigation %p !LoadIsFromSessionHistory=%s "
"!PostDataStream: %s mSameExceptHashes: %s mNewURIHasRef: %s"
, this, !aLoadState->LoadIsFromSessionHistory() ? "true" :
"false", !aLoadState->PostDataStream() ? "true" : "false"
, aState.mSameExceptHashes ? "true" : "false", aState.mNewURIHasRef
? "true" : "false"); } } while (0)
;
8594 return !aLoadState->LoadIsFromSessionHistory() &&
8595 !aLoadState->PostDataStream() && aState.mSameExceptHashes &&
8596 aState.mNewURIHasRef;
8597}
8598
8599nsresult nsDocShell::HandleSameDocumentNavigation(
8600 nsDocShellLoadState* aLoadState, SameDocumentNavigationState& aState,
8601 bool& aSameDocument) {
8602 aSameDocument = true;
8603#ifdef DEBUG1
8604 SameDocumentNavigationState state;
8605 MOZ_ASSERT(IsSameDocumentNavigation(aLoadState, state))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(IsSameDocumentNavigation(aLoadState, state))>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(IsSameDocumentNavigation(aLoadState, state)))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("IsSameDocumentNavigation(aLoadState, state)"
, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 8605); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsSameDocumentNavigation(aLoadState, state)"
")"); do { *((volatile int*)__null) = 8605; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8606#endif
8607
8608 MOZ_LOG(gSHLog, LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = gSHLog; if
((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "nsDocShell::HandleSameDocumentNavigation %p %s -> %s"
, this, mCurrentURI->GetSpecOrDefault().get(), aLoadState->
URI()->GetSpecOrDefault().get()); } } while (0)
8609 ("nsDocShell::HandleSameDocumentNavigation %p %s -> %s", this,do { const ::mozilla::LogModule* moz_real_module = gSHLog; if
((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "nsDocShell::HandleSameDocumentNavigation %p %s -> %s"
, this, mCurrentURI->GetSpecOrDefault().get(), aLoadState->
URI()->GetSpecOrDefault().get()); } } while (0)
8610 mCurrentURI->GetSpecOrDefault().get(),do { const ::mozilla::LogModule* moz_real_module = gSHLog; if
((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "nsDocShell::HandleSameDocumentNavigation %p %s -> %s"
, this, mCurrentURI->GetSpecOrDefault().get(), aLoadState->
URI()->GetSpecOrDefault().get()); } } while (0)
8611 aLoadState->URI()->GetSpecOrDefault().get()))do { const ::mozilla::LogModule* moz_real_module = gSHLog; if
((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "nsDocShell::HandleSameDocumentNavigation %p %s -> %s"
, this, mCurrentURI->GetSpecOrDefault().get(), aLoadState->
URI()->GetSpecOrDefault().get()); } } while (0)
;
8612
8613 RefPtr<Document> doc = GetDocument();
8614 NS_ENSURE_TRUE(doc, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(doc)), 0))) { NS_DebugBreak(NS_DEBUG_WARNING
, "NS_ENSURE_TRUE(" "doc" ") failed", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 8614); return NS_ERROR_FAILURE; } } while (false)
;
8615 doc->DoNotifyPossibleTitleChange();
8616
8617 // Store the pending uninvoked directives if it is a same document navigation.
8618 // We need to set it here, in case the navigation happens before the document
8619 // has actually finished loading.
8620 doc->FragmentDirective()->SetTextDirectives(
8621 std::move(aState.mTextDirectives));
8622
8623 nsCOMPtr<nsIURI> currentURI = mCurrentURI;
8624
8625 // We need to upgrade the new URI from http: to https:
8626 nsCOMPtr<nsIURI> newURI = aLoadState->URI();
8627 if (aState.mSecureUpgradeURI) {
8628 MOZ_TRY(NS_GetSecureUpgradedURI(aLoadState->URI(), getter_AddRefs(newURI)))do { auto mozTryTempResult_ = ::mozilla::ToResult(NS_GetSecureUpgradedURI
(aLoadState->URI(), getter_AddRefs(newURI))); if ((__builtin_expect
(!!(mozTryTempResult_.isErr()), 0))) { return mozTryTempResult_
.propagateErr(); } } while (0)
;
8629 MOZ_LOG(gSHLog, LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = gSHLog; if
((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "Upgraded URI to %s", newURI->GetSpecOrDefault
().get()); } } while (0)
8630 ("Upgraded URI to %s", newURI->GetSpecOrDefault().get()))do { const ::mozilla::LogModule* moz_real_module = gSHLog; if
((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "Upgraded URI to %s", newURI->GetSpecOrDefault
().get()); } } while (0)
;
8631 }
8632
8633 if (StaticPrefs::dom_security_setdocumenturi()) {
8634 // check if aLoadState->URI(), principalURI, mCurrentURI are same origin
8635 // skip handling otherwise
8636 nsCOMPtr<nsIPrincipal> origPrincipal = doc->NodePrincipal();
8637 nsCOMPtr<nsIURI> principalURI = origPrincipal->GetURI();
8638 if (origPrincipal->GetIsNullPrincipal()) {
8639 nsCOMPtr<nsIPrincipal> precursor = origPrincipal->GetPrecursorPrincipal();
8640 if (precursor) {
8641 principalURI = precursor->GetURI();
8642 }
8643 }
8644
8645 if (nsScriptSecurityManager::IsHttpOrHttpsAndCrossOrigin(principalURI,
8646 newURI) ||
8647 nsScriptSecurityManager::IsHttpOrHttpsAndCrossOrigin(principalURI,
8648 mCurrentURI) ||
8649 nsScriptSecurityManager::IsHttpOrHttpsAndCrossOrigin(mCurrentURI,
8650 newURI)) {
8651 aSameDocument = false;
8652 MOZ_LOG(gSHLog, LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = gSHLog; if
((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "nsDocShell[%p]: possible violation of the same origin policy "
"during same document navigation", this); } } while (0)
8653 ("nsDocShell[%p]: possible violation of the same origin policy "do { const ::mozilla::LogModule* moz_real_module = gSHLog; if
((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "nsDocShell[%p]: possible violation of the same origin policy "
"during same document navigation", this); } } while (0)
8654 "during same document navigation",do { const ::mozilla::LogModule* moz_real_module = gSHLog; if
((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "nsDocShell[%p]: possible violation of the same origin policy "
"during same document navigation", this); } } while (0)
8655 this))do { const ::mozilla::LogModule* moz_real_module = gSHLog; if
((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "nsDocShell[%p]: possible violation of the same origin policy "
"during same document navigation", this); } } while (0)
;
8656 return NS_OK;
8657 }
8658 }
8659
8660#ifdef DEBUG1
8661 if (aState.mSameExceptHashes) {
8662 bool sameExceptHashes = false;
8663 currentURI->EqualsExceptRef(newURI, &sameExceptHashes);
8664 MOZ_ASSERT(sameExceptHashes)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(sameExceptHashes)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(sameExceptHashes))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("sameExceptHashes"
, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 8664); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sameExceptHashes"
")"); do { *((volatile int*)__null) = 8664; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8665 }
8666#endif
8667 const nsCOMPtr<nsILoadInfo> loadInfo =
8668 doc->GetChannel() ? doc->GetChannel()->LoadInfo() : nullptr;
8669 if (loadInfo) {
8670 loadInfo->SetIsSameDocumentNavigation(true);
8671 }
8672 // Save the position of the scrollers.
8673 nsPoint scrollPos = GetCurScrollPos();
8674
8675 // Reset mLoadType to its original value once we exit this block, because this
8676 // same document navigation might have started after a normal, network load,
8677 // and we don't want to clobber its load type. See bug 737307.
8678 AutoRestore<uint32_t> loadTypeResetter(mLoadType);
8679
8680 // If a non-same-document-navigation (i.e., a network load) is pending, make
8681 // this a replacement load, so that we don't add a SHEntry here and the
8682 // network load goes into the SHEntry it expects to.
8683 if (JustStartedNetworkLoad() && (aLoadState->LoadType() & LOAD_CMD_NORMAL)) {
8684 mLoadType = LOAD_NORMAL_REPLACE;
8685 } else {
8686 mLoadType = aLoadState->LoadType();
8687 }
8688
8689 mURIResultedInDocument = true;
8690
8691 nsCOMPtr<nsISHEntry> oldLSHE = mLSHE;
8692
8693 // we need to assign aLoadState->SHEntry() to mLSHE right here, so that on
8694 // History loads, SetCurrentURI() called from OnNewURI() will send proper
8695 // onLocationChange() notifications to the browser to update back/forward
8696 // buttons.
8697 SetHistoryEntryAndUpdateBC(Some<nsISHEntry*>(aLoadState->SHEntry()),
8698 Nothing());
8699 UniquePtr<mozilla::dom::LoadingSessionHistoryInfo> oldLoadingEntry;
8700 mLoadingEntry.swap(oldLoadingEntry);
8701 if (aLoadState->GetLoadingSessionHistoryInfo()) {
8702 mLoadingEntry = MakeUnique<LoadingSessionHistoryInfo>(
8703 *aLoadState->GetLoadingSessionHistoryInfo());
8704 mNeedToReportActiveAfterLoadingBecomesActive = false;
8705 }
8706
8707 // Set the doc's URI according to the new history entry's URI.
8708 doc->SetDocumentURI(newURI);
8709
8710 /* This is a anchor traversal within the same page.
8711 * call OnNewURI() so that, this traversal will be
8712 * recorded in session and global history.
8713 */
8714 nsCOMPtr<nsIPrincipal> newURITriggeringPrincipal, newURIPrincipalToInherit,
8715 newURIPartitionedPrincipalToInherit;
8716 nsCOMPtr<nsIContentSecurityPolicy> newCsp;
8717 if (mozilla::SessionHistoryInParent() ? !!mActiveEntry : !!mOSHE) {
8718 if (mozilla::SessionHistoryInParent()) {
8719 newURITriggeringPrincipal = mActiveEntry->GetTriggeringPrincipal();
8720 newURIPrincipalToInherit = mActiveEntry->GetPrincipalToInherit();
8721 newURIPartitionedPrincipalToInherit =
8722 mActiveEntry->GetPartitionedPrincipalToInherit();
8723 newCsp = mActiveEntry->GetCsp();
8724 } else {
8725 newURITriggeringPrincipal = mOSHE->GetTriggeringPrincipal();
8726 newURIPrincipalToInherit = mOSHE->GetPrincipalToInherit();
8727 newURIPartitionedPrincipalToInherit =
8728 mOSHE->GetPartitionedPrincipalToInherit();
8729 newCsp = mOSHE->GetCsp();
8730 }
8731 } else {
8732 newURITriggeringPrincipal = aLoadState->TriggeringPrincipal();
8733 newURIPrincipalToInherit = doc->NodePrincipal();
8734 newURIPartitionedPrincipalToInherit = doc->PartitionedPrincipal();
8735 newCsp = doc->GetCsp();
8736 }
8737
8738 uint32_t locationChangeFlags = GetSameDocumentNavigationFlags(newURI);
8739
8740 // Pass true for aCloneSHChildren, since we're not
8741 // changing documents here, so all of our subframes are
8742 // still relevant to the new session history entry.
8743 //
8744 // It also makes OnNewURI(...) set LOCATION_CHANGE_SAME_DOCUMENT
8745 // flag on firing onLocationChange(...).
8746 // Anyway, aCloneSHChildren param is simply reflecting
8747 // doSameDocumentNavigation in this scope.
8748 //
8749 // Note: we'll actually fire onLocationChange later, in order to preserve
8750 // ordering of HistoryCommit() in the parent vs onLocationChange (bug
8751 // 1668126)
8752 bool locationChangeNeeded = OnNewURI(
8753 newURI, nullptr, newURITriggeringPrincipal, newURIPrincipalToInherit,
8754 newURIPartitionedPrincipalToInherit, newCsp, true, true);
8755
8756 nsCOMPtr<nsIInputStream> postData;
8757 nsCOMPtr<nsIReferrerInfo> referrerInfo;
8758 uint32_t cacheKey = 0;
8759
8760 bool scrollRestorationIsManual = false;
8761 if (!mozilla::SessionHistoryInParent()) {
8762 if (mOSHE) {
8763 /* save current position of scroller(s) (bug 59774) */
8764 mOSHE->SetScrollPosition(scrollPos.x, scrollPos.y);
8765 scrollRestorationIsManual = mOSHE->GetScrollRestorationIsManual();
8766 // Get the postdata, page ident and referrer info from the current page,
8767 // if the new load is being done via normal means. Note that "normal
8768 // means" can be checked for just by checking for LOAD_CMD_NORMAL, given
8769 // the loadType and allowScroll check above -- it filters out some
8770 // LOAD_CMD_NORMAL cases that we wouldn't want here.
8771 if (aLoadState->LoadType() & LOAD_CMD_NORMAL) {
8772 postData = mOSHE->GetPostData();
8773 cacheKey = mOSHE->GetCacheKey();
8774 referrerInfo = mOSHE->GetReferrerInfo();
8775 }
8776
8777 // Link our new SHEntry to the old SHEntry's back/forward
8778 // cache data, since the two SHEntries correspond to the
8779 // same document.
8780 if (mLSHE) {
8781 if (!aLoadState->LoadIsFromSessionHistory()) {
8782 // If we're not doing a history load, scroll restoration
8783 // should be inherited from the previous session history entry.
8784 SetScrollRestorationIsManualOnHistoryEntry(mLSHE,
8785 scrollRestorationIsManual);
8786 }
8787 mLSHE->AdoptBFCacheEntry(mOSHE);
8788 }
8789 }
8790 } else {
8791 if (mActiveEntry) {
8792 mActiveEntry->SetScrollPosition(scrollPos.x, scrollPos.y);
8793 if (mBrowsingContext) {
8794 CollectWireframe();
8795 if (XRE_IsParentProcess()) {
8796 SessionHistoryEntry* entry =
8797 mBrowsingContext->Canonical()->GetActiveSessionHistoryEntry();
8798 if (entry) {
8799 entry->SetScrollPosition(scrollPos.x, scrollPos.y);
8800 }
8801 } else {
8802 mozilla::Unused << ContentChild::GetSingleton()
8803 ->SendSessionHistoryEntryScrollPosition(
8804 mBrowsingContext, scrollPos.x,
8805 scrollPos.y);
8806 }
8807 }
8808 }
8809 if (mLoadingEntry) {
8810 if (!mLoadingEntry->mLoadIsFromSessionHistory) {
8811 // If we're not doing a history load, scroll restoration
8812 // should be inherited from the previous session history entry.
8813 // XXX This needs most probably tweaks once fragment navigation is
8814 // fixed to work with session-history-in-parent.
8815 SetScrollRestorationIsManualOnHistoryEntry(nullptr,
8816 scrollRestorationIsManual);
8817 }
8818 }
8819 }
8820
8821 // If we're doing a history load, use its scroll restoration state.
8822 if (aLoadState->LoadIsFromSessionHistory()) {
8823 if (mozilla::SessionHistoryInParent()) {
8824 scrollRestorationIsManual = aLoadState->GetLoadingSessionHistoryInfo()
8825 ->mInfo.GetScrollRestorationIsManual();
8826 } else {
8827 scrollRestorationIsManual =
8828 aLoadState->SHEntry()->GetScrollRestorationIsManual();
8829 }
8830 }
8831
8832 /* Assign mLSHE to mOSHE. This will either be a new entry created
8833 * by OnNewURI() for normal loads or aLoadState->SHEntry() for history
8834 * loads.
8835 */
8836 if (!mozilla::SessionHistoryInParent()) {
8837 if (mLSHE) {
8838 SetHistoryEntryAndUpdateBC(Nothing(), Some<nsISHEntry*>(mLSHE));
8839 // Save the postData obtained from the previous page
8840 // in to the session history entry created for the
8841 // anchor page, so that any history load of the anchor
8842 // page will restore the appropriate postData.
8843 if (postData) {
8844 mOSHE->SetPostData(postData);
8845 }
8846
8847 // Make sure we won't just repost without hitting the
8848 // cache first
8849 if (cacheKey != 0) {
8850 mOSHE->SetCacheKey(cacheKey);
8851 }
8852
8853 // As the document has not changed, the referrer info hasn't changed too,
8854 // so we can just copy it over.
8855 if (referrerInfo) {
8856 mOSHE->SetReferrerInfo(referrerInfo);
8857 }
8858 }
8859
8860 /* Set the title for the SH entry for this target url so that
8861 * SH menus in go/back/forward buttons won't be empty for this.
8862 * Note, this happens on mOSHE (and mActiveEntry in the future) because of
8863 * the code above.
8864 * Note, when session history lives in the parent process, this does not
8865 * update the title there.
8866 */
8867 SetTitleOnHistoryEntry(false);
8868 } else {
8869 if (aLoadState->LoadIsFromSessionHistory()) {
8870 MOZ_LOG(do { const ::mozilla::LogModule* moz_real_module = gSHLog; if
((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "Moving the loading entry to the active entry on nsDocShell %p to "
"%s", this, mLoadingEntry->mInfo.GetURI()->GetSpecOrDefault
().get()); } } while (0)
8871 gSHLog, LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = gSHLog; if
((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "Moving the loading entry to the active entry on nsDocShell %p to "
"%s", this, mLoadingEntry->mInfo.GetURI()->GetSpecOrDefault
().get()); } } while (0)
8872 ("Moving the loading entry to the active entry on nsDocShell %p to "do { const ::mozilla::LogModule* moz_real_module = gSHLog; if
((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "Moving the loading entry to the active entry on nsDocShell %p to "
"%s", this, mLoadingEntry->mInfo.GetURI()->GetSpecOrDefault
().get()); } } while (0)
8873 "%s",do { const ::mozilla::LogModule* moz_real_module = gSHLog; if
((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "Moving the loading entry to the active entry on nsDocShell %p to "
"%s", this, mLoadingEntry->mInfo.GetURI()->GetSpecOrDefault
().get()); } } while (0)
8874 this, mLoadingEntry->mInfo.GetURI()->GetSpecOrDefault().get()))do { const ::mozilla::LogModule* moz_real_module = gSHLog; if
((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "Moving the loading entry to the active entry on nsDocShell %p to "
"%s", this, mLoadingEntry->mInfo.GetURI()->GetSpecOrDefault
().get()); } } while (0)
;
8875
8876 nsCOMPtr<nsILayoutHistoryState> currentLayoutHistoryState;
8877 if (mActiveEntry) {
8878 currentLayoutHistoryState = mActiveEntry->GetLayoutHistoryState();
8879 }
8880
8881 UniquePtr<SessionHistoryInfo> previousActiveEntry(mActiveEntry.release());
8882 mActiveEntry = MakeUnique<SessionHistoryInfo>(mLoadingEntry->mInfo);
8883 if (currentLayoutHistoryState) {
8884 // Restore the existing nsILayoutHistoryState object, since it is
8885 // possibly being used by the layout. When doing a new load, the
8886 // shared state is copied from the existing active entry, so this
8887 // special case is needed only with the history loads.
8888 mActiveEntry->SetLayoutHistoryState(currentLayoutHistoryState);
8889 }
8890
8891 if (cacheKey != 0) {
8892 mActiveEntry->SetCacheKey(cacheKey);
8893 }
8894 // We're passing in mCurrentURI, which could be null. SessionHistoryCommit
8895 // does require a non-null uri if this is for a refresh load of the same
8896 // URI, but in that case mCurrentURI won't be null here.
8897 mBrowsingContext->SessionHistoryCommit(
8898 *mLoadingEntry, mLoadType, mCurrentURI, previousActiveEntry.get(),
8899 true, true,
8900 /* No expiration update on the same document loads*/
8901 false, cacheKey);
8902 // FIXME Need to set postdata.
8903
8904 // Set the title for the SH entry for this target url so that
8905 // SH menus in go/back/forward buttons won't be empty for this.
8906 // Note, when session history lives in the parent process, this does not
8907 // update the title there.
8908 SetTitleOnHistoryEntry(false);
8909 } else {
8910 Maybe<bool> scrollRestorationIsManual;
8911 if (mActiveEntry) {
8912 scrollRestorationIsManual.emplace(
8913 mActiveEntry->GetScrollRestorationIsManual());
8914
8915 // Get the postdata, page ident and referrer info from the current page,
8916 // if the new load is being done via normal means. Note that "normal
8917 // means" can be checked for just by checking for LOAD_CMD_NORMAL, given
8918 // the loadType and allowScroll check above -- it filters out some
8919 // LOAD_CMD_NORMAL cases that we wouldn't want here.
8920 if (aLoadState->LoadType() & LOAD_CMD_NORMAL) {
8921 postData = mActiveEntry->GetPostData();
8922 cacheKey = mActiveEntry->GetCacheKey();
8923 referrerInfo = mActiveEntry->GetReferrerInfo();
8924 }
8925 }
8926
8927 MOZ_LOG(gSHLog, LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = gSHLog; if
((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "Creating an active entry on nsDocShell %p to %s"
, this, newURI->GetSpecOrDefault().get()); } } while (0)
8928 ("Creating an active entry on nsDocShell %p to %s", this,do { const ::mozilla::LogModule* moz_real_module = gSHLog; if
((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "Creating an active entry on nsDocShell %p to %s"
, this, newURI->GetSpecOrDefault().get()); } } while (0)
8929 newURI->GetSpecOrDefault().get()))do { const ::mozilla::LogModule* moz_real_module = gSHLog; if
((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "Creating an active entry on nsDocShell %p to %s"
, this, newURI->GetSpecOrDefault().get()); } } while (0)
;
8930 if (mActiveEntry) {
8931 mActiveEntry = MakeUnique<SessionHistoryInfo>(*mActiveEntry, newURI);
8932 } else {
8933 mActiveEntry = MakeUnique<SessionHistoryInfo>(
8934 newURI, newURITriggeringPrincipal, newURIPrincipalToInherit,
8935 newURIPartitionedPrincipalToInherit, newCsp, mContentTypeHint);
8936 }
8937
8938 // Save the postData obtained from the previous page in to the session
8939 // history entry created for the anchor page, so that any history load of
8940 // the anchor page will restore the appropriate postData.
8941 if (postData) {
8942 mActiveEntry->SetPostData(postData);
8943 }
8944
8945 // Make sure we won't just repost without hitting the
8946 // cache first
8947 if (cacheKey != 0) {
8948 mActiveEntry->SetCacheKey(cacheKey);
8949 }
8950
8951 // As the document has not changed, the referrer info hasn't changed too,
8952 // so we can just copy it over.
8953 if (referrerInfo) {
8954 mActiveEntry->SetReferrerInfo(referrerInfo);
8955 }
8956
8957 // Set the title for the SH entry for this target url so that
8958 // SH menus in go/back/forward buttons won't be empty for this.
8959 mActiveEntry->SetTitle(mTitle);
8960
8961 if (scrollRestorationIsManual.isSome()) {
8962 mActiveEntry->SetScrollRestorationIsManual(
8963 scrollRestorationIsManual.value());
8964 }
8965
8966 if (LOAD_TYPE_HAS_FLAGS(mLoadType, LOAD_FLAGS_REPLACE_HISTORY)((mLoadType) & ((LOAD_FLAGS_REPLACE_HISTORY) << 16)
)
) {
8967 mBrowsingContext->ReplaceActiveSessionHistoryEntry(mActiveEntry.get());
8968 } else {
8969 mBrowsingContext->IncrementHistoryEntryCountForBrowsingContext();
8970 // FIXME We should probably just compute mChildOffset in the parent
8971 // instead of passing it over IPC here.
8972 mBrowsingContext->SetActiveSessionHistoryEntry(
8973 Some(scrollPos), mActiveEntry.get(), mLoadType, cacheKey);
8974 // FIXME Do we need to update mPreviousEntryIndex and mLoadedEntryIndex?
8975 }
8976 }
8977 }
8978
8979 if (locationChangeNeeded) {
8980 FireOnLocationChange(this, nullptr, newURI, locationChangeFlags);
8981 }
8982
8983 /* Restore the original LSHE if we were loading something
8984 * while same document navigation was initiated.
8985 */
8986 SetHistoryEntryAndUpdateBC(Some<nsISHEntry*>(oldLSHE), Nothing());
8987 mLoadingEntry.swap(oldLoadingEntry);
8988
8989 /* Set the title for the Global History entry for this anchor url.
8990 */
8991 UpdateGlobalHistoryTitle(newURI);
8992
8993 SetDocCurrentStateObj(mOSHE, mActiveEntry.get());
8994
8995 // Inform the favicon service that the favicon for oldURI also
8996 // applies to newURI.
8997 CopyFavicon(currentURI, newURI, UsePrivateBrowsing());
8998
8999 RefPtr<nsGlobalWindowOuter> scriptGlobal = mScriptGlobal;
9000 nsCOMPtr<nsPIDOMWindowInner> win =
9001 scriptGlobal ? scriptGlobal->GetCurrentInnerWindow() : nullptr;
9002
9003 // ScrollToAnchor doesn't necessarily cause us to scroll the window;
9004 // the function decides whether a scroll is appropriate based on the
9005 // arguments it receives. But even if we don't end up scrolling,
9006 // ScrollToAnchor performs other important tasks, such as informing
9007 // the presShell that we have a new hash. See bug 680257.
9008 nsresult rv = ScrollToAnchor(aState.mCurrentURIHasRef, aState.mNewURIHasRef,
9009 aState.mNewHash, aLoadState->LoadType());
9010 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/docshell/base/nsDocShell.cpp"
, 9010); return rv; } } while (false)
;
9011
9012 /* restore previous position of scroller(s), if we're moving
9013 * back in history (bug 59774)
9014 */
9015 nscoord bx = 0;
9016 nscoord by = 0;
9017 bool needsScrollPosUpdate = false;
9018 if ((mozilla::SessionHistoryInParent() ? !!mActiveEntry : !!mOSHE) &&
9019 (aLoadState->LoadType() == LOAD_HISTORY ||
9020 aLoadState->LoadType() == LOAD_RELOAD_NORMAL) &&
9021 !scrollRestorationIsManual) {
9022 needsScrollPosUpdate = true;
9023 if (mozilla::SessionHistoryInParent()) {
9024 mActiveEntry->GetScrollPosition(&bx, &by);
9025 } else {
9026 mOSHE->GetScrollPosition(&bx, &by);
9027 }
9028 }
9029
9030 // Dispatch the popstate and hashchange events, as appropriate.
9031 //
9032 // The event dispatch below can cause us to re-enter script and
9033 // destroy the docshell, nulling out mScriptGlobal. Hold a stack
9034 // reference to avoid null derefs. See bug 914521.
9035 if (win) {
9036 // Fire a hashchange event URIs differ, and only in their hashes.
9037 bool doHashchange = aState.mSameExceptHashes &&
9038 (aState.mCurrentURIHasRef != aState.mNewURIHasRef ||
9039 !aState.mCurrentHash.Equals(aState.mNewHash));
9040
9041 if (aState.mHistoryNavBetweenSameDoc || doHashchange) {
9042 win->DispatchSyncPopState();
9043 }
9044
9045 if (needsScrollPosUpdate && win->HasActiveDocument()) {
9046 SetCurScrollPosEx(bx, by);
9047 }
9048
9049 if (doHashchange) {
9050 // Note that currentURI hasn't changed because it's on the
9051 // stack, so we can just use it directly as the old URI.
9052 win->DispatchAsyncHashchange(currentURI, newURI);
9053 }
9054 }
9055
9056 return NS_OK;
9057}
9058
9059static bool NavigationShouldTakeFocus(nsDocShell* aDocShell,
9060 nsDocShellLoadState* aLoadState) {
9061 if (!aLoadState->AllowFocusMove()) {
9062 return false;
9063 }
9064 if (!aLoadState->HasValidUserGestureActivation()) {
9065 return false;
9066 }
9067 const auto& sourceBC = aLoadState->SourceBrowsingContext();
9068 if (!sourceBC || !sourceBC->IsActive()) {
9069 // If the navigation didn't come from a foreground tab, then we don't steal
9070 // focus.
9071 return false;
9072 }
9073 auto* bc = aDocShell->GetBrowsingContext();
9074 if (sourceBC.get() == bc) {
9075 // If it comes from the same tab / frame, don't steal focus either.
9076 return false;
9077 }
9078 auto* fm = nsFocusManager::GetFocusManager();
9079 if (fm && bc->IsActive() && fm->IsInActiveWindow(bc)) {
9080 // If we're already on the foreground tab of the foreground window, then we
9081 // don't need to do this. This helps to e.g. not steal focus from the
9082 // browser chrome unnecessarily.
9083 return false;
9084 }
9085 if (auto* doc = aDocShell->GetExtantDocument()) {
9086 if (doc->IsInitialDocument()) {
9087 // If we're the initial load for the browsing context, the browser
9088 // chrome determines what to focus. This is important because the
9089 // browser chrome may want to e.g focus the url-bar
9090 return false;
9091 }
9092 }
9093 // Take loadDivertedInBackground into account so the behavior would be the
9094 // same as how the tab first opened.
9095 return !Preferences::GetBool("browser.tabs.loadDivertedInBackground", false);
9096}
9097
9098uint32_t nsDocShell::GetLoadTypeForFormSubmission(
9099 BrowsingContext* aTargetBC, nsDocShellLoadState* aLoadState) {
9100 MOZ_ASSERT(aLoadState->IsFormSubmission())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aLoadState->IsFormSubmission())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aLoadState->IsFormSubmission
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("aLoadState->IsFormSubmission()", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 9100); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->IsFormSubmission()"
")"); do { *((volatile int*)__null) = 9100; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9101
9102 // https://html.spec.whatwg.org/#form-submission-algorithm
9103 // 22. Let historyHandling be "push".
9104 // 23. If form document equals targetNavigable's active document, and
9105 // form document has not yet completely loaded, then set
9106 // historyHandling to "replace".
9107 return GetBrowsingContext() == aTargetBC && !mEODForCurrentDocument
9108 ? LOAD_NORMAL_REPLACE
9109 : LOAD_LINK;
9110}
9111
9112nsresult nsDocShell::InternalLoad(nsDocShellLoadState* aLoadState,
9113 Maybe<uint32_t> aCacheKey) {
9114 MOZ_ASSERT(aLoadState, "need a load state!")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aLoadState)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aLoadState))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("aLoadState" " (" "need a load state!"
")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 9114); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState"
") (" "need a load state!" ")"); do { *((volatile int*)__null
) = 9114; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
;
9115 MOZ_ASSERT(aLoadState->TriggeringPrincipal(),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aLoadState->TriggeringPrincipal())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aLoadState->TriggeringPrincipal
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("aLoadState->TriggeringPrincipal()" " (" "need a valid TriggeringPrincipal"
")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 9116); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->TriggeringPrincipal()"
") (" "need a valid TriggeringPrincipal" ")"); do { *((volatile
int*)__null) = 9116; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
9116 "need a valid TriggeringPrincipal")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aLoadState->TriggeringPrincipal())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aLoadState->TriggeringPrincipal
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("aLoadState->TriggeringPrincipal()" " (" "need a valid TriggeringPrincipal"
")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 9116); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->TriggeringPrincipal()"
") (" "need a valid TriggeringPrincipal" ")"); do { *((volatile
int*)__null) = 9116; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
9117
9118 if (!aLoadState->TriggeringPrincipal()) {
9119 MOZ_ASSERT(false, "InternalLoad needs a valid triggeringPrincipal")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "InternalLoad needs a valid triggeringPrincipal"
")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 9119); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"InternalLoad needs a valid triggeringPrincipal" ")"); do { *
((volatile int*)__null) = 9119; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
;
9120 return NS_ERROR_FAILURE;
9121 }
9122 if (NS_WARN_IF(mBrowsingContext->GetPendingInitialization())NS_warn_if_impl(mBrowsingContext->GetPendingInitialization
(), "mBrowsingContext->GetPendingInitialization()", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 9122)
) {
9123 return NS_ERROR_NOT_AVAILABLE;
9124 }
9125
9126 const bool shouldTakeFocus = NavigationShouldTakeFocus(this, aLoadState);
9127
9128 mOriginalUriString.Truncate();
9129
9130 MOZ_LOG(gDocShellLeakLog, LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = gDocShellLeakLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "DOCSHELL %p InternalLoad %s\n", this, aLoadState
->URI()->GetSpecOrDefault().get()); } } while (0)
9131 ("DOCSHELL %p InternalLoad %s\n", this,do { const ::mozilla::LogModule* moz_real_module = gDocShellLeakLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "DOCSHELL %p InternalLoad %s\n", this, aLoadState
->URI()->GetSpecOrDefault().get()); } } while (0)
9132 aLoadState->URI()->GetSpecOrDefault().get()))do { const ::mozilla::LogModule* moz_real_module = gDocShellLeakLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "DOCSHELL %p InternalLoad %s\n", this, aLoadState
->URI()->GetSpecOrDefault().get()); } } while (0)
;
9133
9134 NS_ENSURE_TRUE(IsValidLoadType(aLoadState->LoadType()), NS_ERROR_INVALID_ARG)do { if ((__builtin_expect(!!(!(IsValidLoadType(aLoadState->
LoadType()))), 0))) { NS_DebugBreak(NS_DEBUG_WARNING, "NS_ENSURE_TRUE("
"IsValidLoadType(aLoadState->LoadType())" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 9134); return NS_ERROR_INVALID_ARG; } } while (false)
;
9135
9136 // Cancel loads coming from Docshells that are being destroyed.
9137 if (mIsBeingDestroyed) {
9138 return NS_ERROR_NOT_AVAILABLE;
9139 }
9140
9141 nsresult rv = EnsureScriptEnvironment();
9142 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
9143 return rv;
9144 }
9145
9146 // If we have a target to move to, do that now.
9147 if (!aLoadState->Target().IsEmpty()) {
9148 return PerformRetargeting(aLoadState);
9149 }
9150
9151 // This is the non-retargeting load path, we've already set the right loadtype
9152 // for form submissions in nsDocShell::OnLinkClickSync.
9153 if (aLoadState->TargetBrowsingContext().IsNull()) {
9154 aLoadState->SetTargetBrowsingContext(GetBrowsingContext());
9155 }
9156
9157 MOZ_DIAGNOSTIC_ASSERT(do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aLoadState->TargetBrowsingContext() == GetBrowsingContext
())>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(aLoadState->TargetBrowsingContext() == GetBrowsingContext
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("aLoadState->TargetBrowsingContext() == GetBrowsingContext()"
" (" "Load must be targeting this BrowsingContext" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 9159); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "aLoadState->TargetBrowsingContext() == GetBrowsingContext()"
") (" "Load must be targeting this BrowsingContext" ")"); do
{ *((volatile int*)__null) = 9159; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
9158 aLoadState->TargetBrowsingContext() == GetBrowsingContext(),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aLoadState->TargetBrowsingContext() == GetBrowsingContext
())>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(aLoadState->TargetBrowsingContext() == GetBrowsingContext
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("aLoadState->TargetBrowsingContext() == GetBrowsingContext()"
" (" "Load must be targeting this BrowsingContext" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 9159); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "aLoadState->TargetBrowsingContext() == GetBrowsingContext()"
") (" "Load must be targeting this BrowsingContext" ")"); do
{ *((volatile int*)__null) = 9159; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
9159 "Load must be targeting this BrowsingContext")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aLoadState->TargetBrowsingContext() == GetBrowsingContext
())>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(aLoadState->TargetBrowsingContext() == GetBrowsingContext
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("aLoadState->TargetBrowsingContext() == GetBrowsingContext()"
" (" "Load must be targeting this BrowsingContext" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 9159); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "aLoadState->TargetBrowsingContext() == GetBrowsingContext()"
") (" "Load must be targeting this BrowsingContext" ")"); do
{ *((volatile int*)__null) = 9159; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
9160
9161 MOZ_TRY(CheckDisallowedJavascriptLoad(aLoadState))do { auto mozTryTempResult_ = ::mozilla::ToResult(CheckDisallowedJavascriptLoad
(aLoadState)); if ((__builtin_expect(!!(mozTryTempResult_.isErr
()), 0))) { return mozTryTempResult_.propagateErr(); } } while
(0)
;
9162
9163 // If we don't have a target, we're loading into ourselves, and our load
9164 // delegate may want to intercept that load.
9165 SameDocumentNavigationState sameDocumentNavigationState;
9166 bool sameDocument =
9167 IsSameDocumentNavigation(aLoadState, sameDocumentNavigationState) &&
9168 !aLoadState->GetPendingRedirectedChannel();
9169
9170 // Note: We do this check both here and in BrowsingContext::
9171 // LoadURI/InternalLoad, since document-specific sandbox flags are only
9172 // available in the process triggering the load, and we don't want the target
9173 // process to have to trust the triggering process to do the appropriate
9174 // checks for the BrowsingContext's sandbox flags.
9175 MOZ_TRY(mBrowsingContext->CheckSandboxFlags(aLoadState))do { auto mozTryTempResult_ = ::mozilla::ToResult(mBrowsingContext
->CheckSandboxFlags(aLoadState)); if ((__builtin_expect(!!
(mozTryTempResult_.isErr()), 0))) { return mozTryTempResult_.
propagateErr(); } } while (0)
;
9176
9177 NS_ENSURE_STATE(!HasUnloadedParent())do { if ((__builtin_expect(!!(!(!HasUnloadedParent())), 0))) {
NS_DebugBreak(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "!HasUnloadedParent()"
") failed", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 9177); return NS_ERROR_UNEXPECTED; } } while (false)
;
9178
9179 rv = CheckLoadingPermissions();
9180 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
9181 return rv;
9182 }
9183
9184 if (mFiredUnloadEvent) {
9185 if (IsOKToLoadURI(aLoadState->URI())) {
9186 MOZ_ASSERT(aLoadState->Target().IsEmpty(),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aLoadState->Target().IsEmpty())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aLoadState->Target().IsEmpty
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("aLoadState->Target().IsEmpty()" " (" "Shouldn't have a window target here!"
")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 9187); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->Target().IsEmpty()"
") (" "Shouldn't have a window target here!" ")"); do { *((volatile
int*)__null) = 9187; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
9187 "Shouldn't have a window target here!")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aLoadState->Target().IsEmpty())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aLoadState->Target().IsEmpty
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("aLoadState->Target().IsEmpty()" " (" "Shouldn't have a window target here!"
")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 9187); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->Target().IsEmpty()"
") (" "Shouldn't have a window target here!" ")"); do { *((volatile
int*)__null) = 9187; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
9188
9189 // If this is a replace load, make whatever load triggered
9190 // the unload event also a replace load, so we don't
9191 // create extra history entries.
9192 if (LOAD_TYPE_HAS_FLAGS(aLoadState->LoadType(),((aLoadState->LoadType()) & ((LOAD_FLAGS_REPLACE_HISTORY
) << 16))
9193 LOAD_FLAGS_REPLACE_HISTORY)((aLoadState->LoadType()) & ((LOAD_FLAGS_REPLACE_HISTORY
) << 16))
) {
9194 mLoadType = LOAD_NORMAL_REPLACE;
9195 }
9196
9197 // Do this asynchronously
9198 nsCOMPtr<nsIRunnable> ev = new InternalLoadEvent(this, aLoadState);
9199 return Dispatch(ev.forget());
9200 }
9201
9202 // Just ignore this load attempt
9203 return NS_OK;
9204 }
9205
9206 // If we are loading a URI that should inherit a security context (basically
9207 // javascript: at this point), and the caller has said that principal
9208 // inheritance is allowed, there are a few possible cases:
9209 //
9210 // 1) We are provided with the principal to inherit. In that case, we just use
9211 // it.
9212 //
9213 // 2) The load is coming from some other application. In this case we don't
9214 // want to inherit from whatever document we have loaded now, since the
9215 // load is unrelated to it.
9216 //
9217 // 3) It's a load from our application, but does not provide an explicit
9218 // principal to inherit. In that case, we want to inherit the principal of
9219 // our current document, or of our parent document (if any) if we don't
9220 // have a current document.
9221 {
9222 bool inherits;
9223
9224 if (!aLoadState->HasLoadFlags(LOAD_FLAGS_FROM_EXTERNAL) &&
9225 !aLoadState->PrincipalToInherit() &&
9226 (aLoadState->HasInternalLoadFlags(
9227 INTERNAL_LOAD_FLAGS_INHERIT_PRINCIPAL)) &&
9228 NS_SUCCEEDED(nsContentUtils::URIInheritsSecurityContext(((bool)(__builtin_expect(!!(!NS_FAILED_impl(nsContentUtils::URIInheritsSecurityContext
( aLoadState->URI(), &inherits))), 1)))
9229 aLoadState->URI(), &inherits))((bool)(__builtin_expect(!!(!NS_FAILED_impl(nsContentUtils::URIInheritsSecurityContext
( aLoadState->URI(), &inherits))), 1)))
&&
9230 inherits) {
9231 aLoadState->SetPrincipalToInherit(GetInheritedPrincipal(true));
9232 }
9233 // If principalToInherit is still null (e.g. if some of the conditions of
9234 // were not satisfied), then no inheritance of any sort will happen: the
9235 // load will just get a principal based on the URI being loaded.
9236 }
9237
9238 // If this docshell is owned by a frameloader, make sure to cancel
9239 // possible frameloader initialization before loading a new page.
9240 nsCOMPtr<nsIDocShellTreeItem> parent = GetInProcessParentDocshell();
9241 if (parent) {
9242 RefPtr<Document> doc = parent->GetDocument();
9243 if (doc) {
9244 doc->TryCancelFrameLoaderInitialization(this);
9245 }
9246 }
9247
9248 // Before going any further vet loads initiated by external programs.
9249 if (aLoadState->HasLoadFlags(LOAD_FLAGS_FROM_EXTERNAL)) {
9250 MOZ_DIAGNOSTIC_ASSERT(aLoadState->LoadType() == LOAD_NORMAL)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aLoadState->LoadType() == LOAD_NORMAL)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(aLoadState->LoadType() == LOAD_NORMAL))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("aLoadState->LoadType() == LOAD_NORMAL"
, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 9250); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "aLoadState->LoadType() == LOAD_NORMAL"
")"); do { *((volatile int*)__null) = 9250; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9251
9252 // Disallow external chrome: loads targetted at content windows
9253 if (SchemeIsChrome(aLoadState->URI())) {
9254 NS_WARNING("blocked external chrome: url -- use '--chrome' option")NS_DebugBreak(NS_DEBUG_WARNING, "blocked external chrome: url -- use '--chrome' option"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 9254)
;
9255 return NS_ERROR_FAILURE;
9256 }
9257
9258 // clear the decks to prevent context bleed-through (bug 298255)
9259 rv = CreateAboutBlankDocumentViewer(nullptr, nullptr, nullptr, nullptr,
9260 /* aIsInitialDocument */ false);
9261 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
9262 return NS_ERROR_FAILURE;
9263 }
9264 }
9265
9266 mAllowKeywordFixup = aLoadState->HasInternalLoadFlags(
9267 INTERNAL_LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP);
9268 mURIResultedInDocument = false; // reset the clock...
9269
9270 // See if this is actually a load between two history entries for the same
9271 // document. If the process fails, or if we successfully navigate within the
9272 // same document, return.
9273 if (sameDocument) {
9274 nsresult rv = HandleSameDocumentNavigation(
9275 aLoadState, sameDocumentNavigationState, sameDocument);
9276 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/docshell/base/nsDocShell.cpp"
, 9276); return rv; } } while (false)
;
9277 if (shouldTakeFocus) {
9278 mBrowsingContext->Focus(CallerType::System, IgnoreErrors());
9279 }
9280 if (sameDocument) {
9281 return rv;
9282 }
9283 }
9284
9285 // mDocumentViewer->PermitUnload can destroy |this| docShell, which
9286 // causes the next call of CanSavePresentation to crash.
9287 // Hold onto |this| until we return, to prevent a crash from happening.
9288 // (bug#331040)
9289 nsCOMPtr<nsIDocShell> kungFuDeathGrip(this);
9290
9291 // Don't init timing for javascript:, since it generally doesn't
9292 // actually start a load or anything. If it does, we'll init
9293 // timing then, from OnStateChange.
9294
9295 // XXXbz mTiming should know what channel it's for, so we don't
9296 // need this hackery.
9297 const bool isJavaScript = SchemeIsJavascript(aLoadState->URI());
9298 const bool isExternalProtocol =
9299 nsContentUtils::IsExternalProtocol(aLoadState->URI());
9300 const bool isDownload = !aLoadState->FileName().IsVoid();
9301 const bool toBeReset = !isJavaScript && MaybeInitTiming();
9302
9303 // FIXME(emilio): Should this be done by javascript: uris? What about external
9304 // protocols?
9305 if (mTiming && !isDownload) {
9306 mTiming->NotifyBeforeUnload();
9307 }
9308 // Check if the page doesn't want to be unloaded. The javascript:
9309 // protocol handler deals with this for javascript: URLs.
9310 // NOTE(emilio): As of this writing, other browsers fire beforeunload for
9311 // external protocols, so keep doing that even though they don't return data
9312 // and thus we won't really unload this...
9313 if (!isJavaScript && !isDownload &&
9314 !aLoadState->NotifiedBeforeUnloadListeners() && mDocumentViewer) {
9315 // Check if request is exempted from HTTPSOnlyMode and if https-first is
9316 // enabled, if so it means:
9317 // * https-first failed to upgrade request to https
9318 // * we already asked for permission to unload and the user accepted
9319 // otherwise we wouldn't be here.
9320 const bool isPrivateWin = GetOriginAttributes().IsPrivateBrowsing();
9321 const uint32_t loadType = aLoadState->LoadType();
9322
9323 // Check if request is a reload.
9324 const bool isHistoryOrReload =
9325 loadType == LOAD_RELOAD_NORMAL ||
9326 loadType == LOAD_RELOAD_BYPASS_CACHE ||
9327 loadType == LOAD_RELOAD_BYPASS_PROXY ||
9328 loadType == LOAD_RELOAD_BYPASS_PROXY_AND_CACHE ||
9329 loadType == LOAD_HISTORY;
9330
9331 // If it isn't a reload, the request already failed to be upgraded and
9332 // https-first is enabled then don't ask the user again for permission to
9333 // unload and just unload.
9334 bool okToUnload;
9335 if (!isHistoryOrReload && aLoadState->IsExemptFromHTTPSFirstMode() &&
9336 nsHTTPSOnlyUtils::IsHttpsFirstModeEnabled(isPrivateWin)) {
9337 rv = mDocumentViewer->PermitUnload(
9338 nsIDocumentViewer::PermitUnloadAction::eDontPromptAndUnload,
9339 &okToUnload);
9340 } else {
9341 rv = mDocumentViewer->PermitUnload(&okToUnload);
9342 }
9343
9344 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && !okToUnload) {
9345 // The user chose not to unload the page, interrupt the
9346 // load.
9347 MaybeResetInitTiming(toBeReset);
9348 return NS_OK;
9349 }
9350 }
9351
9352 if (mTiming && !isDownload) {
9353 mTiming->NotifyUnloadAccepted(mCurrentURI);
9354 }
9355
9356 // In e10s, in the parent process, we refuse to load anything other than
9357 // "safe" resources that we ship or trust enough to give "special" URLs.
9358 // Similar check will be performed by the ParentProcessDocumentChannel if in
9359 // use.
9360 if (XRE_IsE10sParentProcess() &&
9361 !DocumentChannel::CanUseDocumentChannel(aLoadState->URI()) &&
9362 !CanLoadInParentProcess(aLoadState->URI())) {
9363 return NS_ERROR_FAILURE;
9364 }
9365
9366 // Whenever a top-level browsing context is navigated, the user agent MUST
9367 // lock the orientation of the document to the document's default
9368 // orientation. We don't explicitly check for a top-level browsing context
9369 // here because orientation is only set on top-level browsing contexts.
9370 if (mBrowsingContext->GetOrientationLock() != hal::ScreenOrientation::None) {
9371 MOZ_ASSERT(mBrowsingContext->IsTop())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mBrowsingContext->IsTop())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mBrowsingContext->IsTop()
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"mBrowsingContext->IsTop()", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 9371); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mBrowsingContext->IsTop()"
")"); do { *((volatile int*)__null) = 9371; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9372 MOZ_ALWAYS_SUCCEEDS(do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(mBrowsingContext->SetOrientationLock(hal::ScreenOrientation
::None))), 1)))), 1))) { } else { do { static_assert( mozilla
::detail::AssertionConditionType<decltype(false)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(false))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("false" " (" "NS_SUCCEEDED(mBrowsingContext->SetOrientationLock(hal::ScreenOrientation::None))"
")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 9373); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "false"
") (" "NS_SUCCEEDED(mBrowsingContext->SetOrientationLock(hal::ScreenOrientation::None))"
")"); do { *((volatile int*)__null) = 9373; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
9373 mBrowsingContext->SetOrientationLock(hal::ScreenOrientation::None))do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(mBrowsingContext->SetOrientationLock(hal::ScreenOrientation
::None))), 1)))), 1))) { } else { do { static_assert( mozilla
::detail::AssertionConditionType<decltype(false)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(false))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("false" " (" "NS_SUCCEEDED(mBrowsingContext->SetOrientationLock(hal::ScreenOrientation::None))"
")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 9373); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "false"
") (" "NS_SUCCEEDED(mBrowsingContext->SetOrientationLock(hal::ScreenOrientation::None))"
")"); do { *((volatile int*)__null) = 9373; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
9374 if (mBrowsingContext->IsActive()) {
9375 ScreenOrientation::UpdateActiveOrientationLock(
9376 hal::ScreenOrientation::None);
9377 }
9378 }
9379
9380 // Check for saving the presentation here, before calling Stop().
9381 // This is necessary so that we can catch any pending requests.
9382 // Since the new request has not been created yet, we pass null for the
9383 // new request parameter.
9384 // Also pass nullptr for the document, since it doesn't affect the return
9385 // value for our purposes here.
9386 const bool savePresentation =
9387 CanSavePresentation(aLoadState->LoadType(), nullptr, nullptr,
9388 /* aReportBFCacheComboTelemetry */ true);
9389
9390 // nsDocShell::CanSavePresentation is for non-SHIP version only. Do a
9391 // separate check for SHIP so that we know if there are ongoing requests
9392 // before calling Stop() below.
9393 if (mozilla::SessionHistoryInParent()) {
9394 Document* document = GetDocument();
9395 uint32_t flags = 0;
9396 if (document && !document->CanSavePresentation(nullptr, flags, true)) {
9397 // This forces some flags into the WindowGlobalParent's mBFCacheStatus,
9398 // which we'll then use in CanonicalBrowsingContext::AllowedInBFCache,
9399 // and in particular we'll store BFCacheStatus::REQUEST if needed.
9400 // Also, we want to report all the flags to the parent process here (and
9401 // not just BFCacheStatus::NOT_ALLOWED), so that it can update the
9402 // telemetry data correctly.
9403 document->DisallowBFCaching(flags);
9404 }
9405 }
9406
9407 // Don't stop current network activity for javascript: URL's since they might
9408 // not result in any data, and thus nothing should be stopped in those cases.
9409 // In the case where they do result in data, the javascript: URL channel takes
9410 // care of stopping current network activity. Similarly, downloads don't
9411 // unload this document...
9412 if (!isJavaScript && !isDownload && !isExternalProtocol) {
9413 // Stop any current network activity.
9414 // Also stop content if this is a zombie doc. otherwise
9415 // the onload will be delayed by other loads initiated in the
9416 // background by the first document that
9417 // didn't fully load before the next load was initiated.
9418 // If not a zombie, don't stop content until data
9419 // starts arriving from the new URI...
9420 if ((mDocumentViewer && mDocumentViewer->GetPreviousViewer()) ||
9421 LOAD_TYPE_HAS_FLAGS(aLoadState->LoadType(), LOAD_FLAGS_STOP_CONTENT)((aLoadState->LoadType()) & ((LOAD_FLAGS_STOP_CONTENT)
<< 16))
) {
9422 rv = Stop(nsIWebNavigation::STOP_ALL);
9423 } else {
9424 rv = Stop(nsIWebNavigation::STOP_NETWORK);
9425 }
9426
9427 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
9428 return rv;
9429 }
9430 }
9431
9432 mLoadType = aLoadState->LoadType();
9433
9434 // aLoadState->SHEntry() should be assigned to mLSHE, only after Stop() has
9435 // been called. But when loading an error page, do not clear the
9436 // mLSHE for the real page.
9437 if (mLoadType != LOAD_ERROR_PAGE) {
9438 SetHistoryEntryAndUpdateBC(Some<nsISHEntry*>(aLoadState->SHEntry()),
9439 Nothing());
9440 if (aLoadState->LoadIsFromSessionHistory() &&
9441 !mozilla::SessionHistoryInParent()) {
9442 // We're making history navigation or a reload. Make sure our history ID
9443 // points to the same ID as SHEntry's docshell ID.
9444 nsID historyID = {};
9445 aLoadState->SHEntry()->GetDocshellID(historyID);
9446
9447 Unused << mBrowsingContext->SetHistoryID(historyID);
9448 }
9449 }
9450
9451 mSavingOldViewer = savePresentation;
9452
9453 // If we have a saved content viewer in history, restore and show it now.
9454 if (aLoadState->LoadIsFromSessionHistory() &&
9455 (mLoadType & LOAD_CMD_HISTORY)) {
9456 // https://html.spec.whatwg.org/#history-traversal:
9457 // To traverse the history
9458 // "If entry has a different Document object than the current entry, then
9459 // run the following substeps: Remove any tasks queued by the history
9460 // traversal task source..."
9461 // Same document object case was handled already above with
9462 // HandleSameDocumentNavigation call.
9463 RefPtr<ChildSHistory> shistory = GetRootSessionHistory();
9464 if (shistory) {
9465 shistory->RemovePendingHistoryNavigations();
9466 }
9467 if (!mozilla::SessionHistoryInParent()) {
9468 // It's possible that the previous viewer of mDocumentViewer is the
9469 // viewer that will end up in aLoadState->SHEntry() when it gets closed.
9470 // If that's the case, we need to go ahead and force it into its shentry
9471 // so we can restore it.
9472 if (mDocumentViewer) {
9473 nsCOMPtr<nsIDocumentViewer> prevViewer =
9474 mDocumentViewer->GetPreviousViewer();
9475 if (prevViewer) {
9476#ifdef DEBUG1
9477 nsCOMPtr<nsIDocumentViewer> prevPrevViewer =
9478 prevViewer->GetPreviousViewer();
9479 NS_ASSERTION(!prevPrevViewer, "Should never have viewer chain here")do { if (!(!prevPrevViewer)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "Should never have viewer chain here", "!prevPrevViewer", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 9479); MOZ_PretendNoReturn(); } } while (0)
;
9480#endif
9481 nsCOMPtr<nsISHEntry> viewerEntry;
9482 prevViewer->GetHistoryEntry(getter_AddRefs(viewerEntry));
9483 if (viewerEntry == aLoadState->SHEntry()) {
9484 // Make sure this viewer ends up in the right place
9485 mDocumentViewer->SetPreviousViewer(nullptr);
9486 prevViewer->Destroy();
9487 }
9488 }
9489 }
9490 nsCOMPtr<nsISHEntry> oldEntry = mOSHE;
9491 bool restoring;
9492 rv = RestorePresentation(aLoadState->SHEntry(), &restoring);
9493 if (restoring) {
9494 Telemetry::Accumulate(Telemetry::BFCACHE_PAGE_RESTORED, true);
9495 return rv;
9496 }
9497 Telemetry::Accumulate(Telemetry::BFCACHE_PAGE_RESTORED, false);
9498
9499 // We failed to restore the presentation, so clean up.
9500 // Both the old and new history entries could potentially be in
9501 // an inconsistent state.
9502 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
9503 if (oldEntry) {
9504 oldEntry->SyncPresentationState();
9505 }
9506
9507 aLoadState->SHEntry()->SyncPresentationState();
9508 }
9509 }
9510 }
9511
9512 bool isTopLevelDoc = mBrowsingContext->IsTopContent();
9513
9514 OriginAttributes attrs = GetOriginAttributes();
9515 attrs.SetFirstPartyDomain(isTopLevelDoc, aLoadState->URI());
9516
9517 PredictorLearn(aLoadState->URI(), nullptr,
9518 nsINetworkPredictor::LEARN_LOAD_TOPLEVEL, attrs);
9519 PredictorPredict(aLoadState->URI(), nullptr,
9520 nsINetworkPredictor::PREDICT_LOAD, attrs, nullptr);
9521
9522 nsCOMPtr<nsIRequest> req;
9523 rv = DoURILoad(aLoadState, aCacheKey, getter_AddRefs(req));
9524
9525 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
9526 if (shouldTakeFocus) {
9527 mBrowsingContext->Focus(CallerType::System, IgnoreErrors());
9528 }
9529 }
9530
9531 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
9532 nsCOMPtr<nsIChannel> chan(do_QueryInterface(req));
9533 UnblockEmbedderLoadEventForFailure();
9534 nsCOMPtr<nsIURI> uri = aLoadState->URI();
9535 if (DisplayLoadError(rv, uri, nullptr, chan) &&
9536 // FIXME: At this point code was using internal load flags, but checking
9537 // non-internal load flags?
9538 aLoadState->HasLoadFlags(LOAD_FLAGS_ERROR_LOAD_CHANGES_RV)) {
9539 return NS_ERROR_LOAD_SHOWED_ERRORPAGE;
9540 }
9541
9542 // We won't report any error if this is an unknown protocol error. The
9543 // reason behind this is that it will allow enumeration of external
9544 // protocols if we report an error for each unknown protocol.
9545 if (NS_ERROR_UNKNOWN_PROTOCOL == rv) {
9546 return NS_OK;
9547 }
9548 }
9549
9550 return rv;
9551}
9552
9553/* static */
9554bool nsDocShell::CanLoadInParentProcess(nsIURI* aURI) {
9555 nsCOMPtr<nsIURI> uri = aURI;
9556 // In e10s, in the parent process, we refuse to load anything other than
9557 // "safe" resources that we ship or trust enough to give "special" URLs.
9558 bool canLoadInParent = false;
9559 if (NS_SUCCEEDED(NS_URIChainHasFlags(((bool)(__builtin_expect(!!(!NS_FAILED_impl(NS_URIChainHasFlags
( uri, nsIProtocolHandler::URI_IS_UI_RESOURCE, &canLoadInParent
))), 1)))
9560 uri, nsIProtocolHandler::URI_IS_UI_RESOURCE, &canLoadInParent))((bool)(__builtin_expect(!!(!NS_FAILED_impl(NS_URIChainHasFlags
( uri, nsIProtocolHandler::URI_IS_UI_RESOURCE, &canLoadInParent
))), 1)))
&&
9561 canLoadInParent) {
9562 // We allow UI resources.
9563 return true;
9564 }
9565 // For about: and extension-based URIs, which don't get
9566 // URI_IS_UI_RESOURCE, first remove layers of view-source:, if present.
9567 while (uri && uri->SchemeIs("view-source")) {
9568 nsCOMPtr<nsINestedURI> nested = do_QueryInterface(uri);
9569 if (nested) {
9570 nested->GetInnerURI(getter_AddRefs(uri));
9571 } else {
9572 break;
9573 }
9574 }
9575 // Allow about: URIs, and allow moz-extension ones if we're running
9576 // extension content in the parent process.
9577 if (!uri || uri->SchemeIs("about") ||
9578 (!StaticPrefs::extensions_webextensions_remote() &&
9579 uri->SchemeIs("moz-extension"))) {
9580 return true;
9581 }
9582#ifdef MOZ_THUNDERBIRD
9583 if (uri->SchemeIs("imap") || uri->SchemeIs("mailbox") ||
9584 uri->SchemeIs("news") || uri->SchemeIs("nntp") ||
9585 uri->SchemeIs("snews") || uri->SchemeIs("x-moz-ews")) {
9586 return true;
9587 }
9588#endif
9589 nsAutoCString scheme;
9590 uri->GetScheme(scheme);
9591 // Allow ext+foo URIs (extension-registered custom protocols). See
9592 // https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/protocol_handlers
9593 if (StringBeginsWith(scheme, "ext+"_ns) &&
9594 !StaticPrefs::extensions_webextensions_remote()) {
9595 return true;
9596 }
9597 // Final exception for some legacy automated tests:
9598 if (xpc::IsInAutomation() &&
9599 StaticPrefs::security_allow_unsafe_parent_loads()) {
9600 return true;
9601 }
9602 return false;
9603}
9604
9605nsIPrincipal* nsDocShell::GetInheritedPrincipal(
9606 bool aConsiderCurrentDocument, bool aConsiderPartitionedPrincipal) {
9607 RefPtr<Document> document;
9608 bool inheritedFromCurrent = false;
9609
9610 if (aConsiderCurrentDocument && mDocumentViewer) {
9611 document = mDocumentViewer->GetDocument();
9612 inheritedFromCurrent = true;
9613 }
9614
9615 if (!document) {
9616 nsCOMPtr<nsIDocShellTreeItem> parentItem;
9617 GetInProcessSameTypeParent(getter_AddRefs(parentItem));
9618 if (parentItem) {
9619 document = parentItem->GetDocument();
9620 }
9621 }
9622
9623 if (!document) {
9624 if (!aConsiderCurrentDocument) {
9625 return nullptr;
9626 }
9627
9628 // Make sure we end up with _something_ as the principal no matter
9629 // what.If this fails, we'll just get a null docViewer and bail.
9630 EnsureDocumentViewer();
9631 if (!mDocumentViewer) {
9632 return nullptr;
9633 }
9634 document = mDocumentViewer->GetDocument();
9635 }
9636
9637 //-- Get the document's principal
9638 if (document) {
9639 nsIPrincipal* docPrincipal = aConsiderPartitionedPrincipal
9640 ? document->PartitionedPrincipal()
9641 : document->NodePrincipal();
9642
9643 // Don't allow loads in typeContent docShells to inherit the system
9644 // principal from existing documents.
9645 if (inheritedFromCurrent && mItemType == typeContent &&
9646 docPrincipal->IsSystemPrincipal()) {
9647 return nullptr;
9648 }
9649
9650 return docPrincipal;
9651 }
9652
9653 return nullptr;
9654}
9655
9656/* static */ nsresult nsDocShell::CreateRealChannelForDocument(
9657 nsIChannel** aChannel, nsIURI* aURI, nsILoadInfo* aLoadInfo,
9658 nsIInterfaceRequestor* aCallbacks, nsLoadFlags aLoadFlags,
9659 const nsAString& aSrcdoc, nsIURI* aBaseURI) {
9660 nsCOMPtr<nsIChannel> channel;
9661 if (aSrcdoc.IsVoid()) {
9662 MOZ_TRY(NS_NewChannelInternal(getter_AddRefs(channel), aURI, aLoadInfo,do { auto mozTryTempResult_ = ::mozilla::ToResult(NS_NewChannelInternal
(getter_AddRefs(channel), aURI, aLoadInfo, nullptr, nullptr, aCallbacks
, aLoadFlags)); if ((__builtin_expect(!!(mozTryTempResult_.isErr
()), 0))) { return mozTryTempResult_.propagateErr(); } } while
(0)
9663 nullptr, // PerformanceStoragedo { auto mozTryTempResult_ = ::mozilla::ToResult(NS_NewChannelInternal
(getter_AddRefs(channel), aURI, aLoadInfo, nullptr, nullptr, aCallbacks
, aLoadFlags)); if ((__builtin_expect(!!(mozTryTempResult_.isErr
()), 0))) { return mozTryTempResult_.propagateErr(); } } while
(0)
9664 nullptr, // loadGroupdo { auto mozTryTempResult_ = ::mozilla::ToResult(NS_NewChannelInternal
(getter_AddRefs(channel), aURI, aLoadInfo, nullptr, nullptr, aCallbacks
, aLoadFlags)); if ((__builtin_expect(!!(mozTryTempResult_.isErr
()), 0))) { return mozTryTempResult_.propagateErr(); } } while
(0)
9665 aCallbacks, aLoadFlags))do { auto mozTryTempResult_ = ::mozilla::ToResult(NS_NewChannelInternal
(getter_AddRefs(channel), aURI, aLoadInfo, nullptr, nullptr, aCallbacks
, aLoadFlags)); if ((__builtin_expect(!!(mozTryTempResult_.isErr
()), 0))) { return mozTryTempResult_.propagateErr(); } } while
(0)
;
9666
9667 if (aBaseURI) {
9668 nsCOMPtr<nsIViewSourceChannel> vsc = do_QueryInterface(channel);
9669 if (vsc) {
9670 MOZ_ALWAYS_SUCCEEDS(vsc->SetBaseURI(aBaseURI))do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(vsc->SetBaseURI(aBaseURI))), 1)))), 1))) { } else { do { static_assert
( mozilla::detail::AssertionConditionType<decltype(false)>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(false))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("false" " (" "NS_SUCCEEDED(vsc->SetBaseURI(aBaseURI))" ")"
, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 9670); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "false"
") (" "NS_SUCCEEDED(vsc->SetBaseURI(aBaseURI))" ")"); do {
*((volatile int*)__null) = 9670; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false); } } while (false
)
;
9671 }
9672 }
9673 } else if (SchemeIsViewSource(aURI)) {
9674 // Instantiate view source handler protocol, if it doesn't exist already.
9675 nsCOMPtr<nsIIOService> io(do_GetIOService());
9676 MOZ_ASSERT(io)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(io)>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(io))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("io", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 9676); AnnotateMozCrashReason("MOZ_ASSERT" "(" "io" ")"); do
{ *((volatile int*)__null) = 9676; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
9677 nsCOMPtr<nsIProtocolHandler> handler;
9678 nsresult rv =
9679 io->GetProtocolHandler("view-source", getter_AddRefs(handler));
9680 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
9681 return rv;
9682 }
9683
9684 nsViewSourceHandler* vsh = nsViewSourceHandler::GetInstance();
9685 if (!vsh) {
9686 return NS_ERROR_FAILURE;
9687 }
9688
9689 MOZ_TRY(vsh->NewSrcdocChannel(aURI, aBaseURI, aSrcdoc, aLoadInfo,do { auto mozTryTempResult_ = ::mozilla::ToResult(vsh->NewSrcdocChannel
(aURI, aBaseURI, aSrcdoc, aLoadInfo, getter_AddRefs(channel))
); if ((__builtin_expect(!!(mozTryTempResult_.isErr()), 0))) {
return mozTryTempResult_.propagateErr(); } } while (0)
9690 getter_AddRefs(channel)))do { auto mozTryTempResult_ = ::mozilla::ToResult(vsh->NewSrcdocChannel
(aURI, aBaseURI, aSrcdoc, aLoadInfo, getter_AddRefs(channel))
); if ((__builtin_expect(!!(mozTryTempResult_.isErr()), 0))) {
return mozTryTempResult_.propagateErr(); } } while (0)
;
9691 } else {
9692 MOZ_TRY(NS_NewInputStreamChannelInternal(getter_AddRefs(channel), aURI,do { auto mozTryTempResult_ = ::mozilla::ToResult(NS_NewInputStreamChannelInternal
(getter_AddRefs(channel), aURI, aSrcdoc, "text/html"_ns, aLoadInfo
, true)); if ((__builtin_expect(!!(mozTryTempResult_.isErr())
, 0))) { return mozTryTempResult_.propagateErr(); } } while (
0)
9693 aSrcdoc, "text/html"_ns, aLoadInfo,do { auto mozTryTempResult_ = ::mozilla::ToResult(NS_NewInputStreamChannelInternal
(getter_AddRefs(channel), aURI, aSrcdoc, "text/html"_ns, aLoadInfo
, true)); if ((__builtin_expect(!!(mozTryTempResult_.isErr())
, 0))) { return mozTryTempResult_.propagateErr(); } } while (
0)
9694 true))do { auto mozTryTempResult_ = ::mozilla::ToResult(NS_NewInputStreamChannelInternal
(getter_AddRefs(channel), aURI, aSrcdoc, "text/html"_ns, aLoadInfo
, true)); if ((__builtin_expect(!!(mozTryTempResult_.isErr())
, 0))) { return mozTryTempResult_.propagateErr(); } } while (
0)
;
9695 nsCOMPtr<nsIInputStreamChannel> isc = do_QueryInterface(channel);
9696 MOZ_ASSERT(isc)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(isc)>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(isc))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("isc", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 9696); AnnotateMozCrashReason("MOZ_ASSERT" "(" "isc" ")"); do
{ *((volatile int*)__null) = 9696; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
9697 isc->SetBaseURI(aBaseURI);
9698 }
9699
9700 if (aLoadFlags != nsIRequest::LOAD_NORMAL) {
9701 nsresult rv = channel->SetLoadFlags(aLoadFlags);
9702 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/docshell/base/nsDocShell.cpp"
, 9702); return rv; } } while (false)
;
9703 }
9704
9705 channel.forget(aChannel);
9706 return NS_OK;
9707}
9708
9709/* static */ bool nsDocShell::CreateAndConfigureRealChannelForLoadState(
9710 BrowsingContext* aBrowsingContext, nsDocShellLoadState* aLoadState,
9711 LoadInfo* aLoadInfo, nsIInterfaceRequestor* aCallbacks,
9712 nsDocShell* aDocShell, const OriginAttributes& aOriginAttributes,
9713 nsLoadFlags aLoadFlags, uint32_t aCacheKey, nsresult& aRv,
9714 nsIChannel** aChannel) {
9715 MOZ_ASSERT(aLoadInfo)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aLoadInfo)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aLoadInfo))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aLoadInfo", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 9715); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadInfo" ")"
); do { *((volatile int*)__null) = 9715; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9716
9717 nsString srcdoc = VoidString();
9718 bool isSrcdoc =
9719 aLoadState->HasInternalLoadFlags(INTERNAL_LOAD_FLAGS_IS_SRCDOC);
9720 if (isSrcdoc) {
9721 srcdoc = aLoadState->SrcdocData();
9722 }
9723
9724 aLoadInfo->SetTriggeringRemoteType(
9725 aLoadState->GetEffectiveTriggeringRemoteType());
9726
9727 if (aLoadState->PrincipalToInherit()) {
9728 aLoadInfo->SetPrincipalToInherit(aLoadState->PrincipalToInherit());
9729 }
9730 aLoadInfo->SetLoadTriggeredFromExternal(
9731 aLoadState->HasLoadFlags(LOAD_FLAGS_FROM_EXTERNAL));
9732 aLoadInfo->SetForceAllowDataURI(aLoadState->HasInternalLoadFlags(
9733 INTERNAL_LOAD_FLAGS_FORCE_ALLOW_DATA_URI));
9734 aLoadInfo->SetOriginalFrameSrcLoad(
9735 aLoadState->HasInternalLoadFlags(INTERNAL_LOAD_FLAGS_ORIGINAL_FRAME_SRC));
9736 aLoadInfo->SetIsNewWindowTarget(
9737 aLoadState->HasInternalLoadFlags(INTERNAL_LOAD_FLAGS_FIRST_LOAD));
9738
9739 bool inheritAttrs = false;
9740 if (aLoadState->PrincipalToInherit()) {
9741 inheritAttrs = nsContentUtils::ChannelShouldInheritPrincipal(
9742 aLoadState->PrincipalToInherit(), aLoadState->URI(),
9743 true, // aInheritForAboutBlank
9744 isSrcdoc);
9745 }
9746
9747 // Strip the target query parameters before creating the channel.
9748 aLoadState->MaybeStripTrackerQueryStrings(aBrowsingContext);
9749
9750 OriginAttributes attrs;
9751
9752 // Inherit origin attributes from PrincipalToInherit if inheritAttrs is
9753 // true. Otherwise we just use the origin attributes from docshell.
9754 if (inheritAttrs) {
9755 MOZ_ASSERT(aLoadState->PrincipalToInherit(),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aLoadState->PrincipalToInherit())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aLoadState->PrincipalToInherit
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("aLoadState->PrincipalToInherit()" " (" "We should have PrincipalToInherit here."
")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 9756); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->PrincipalToInherit()"
") (" "We should have PrincipalToInherit here." ")"); do { *
((volatile int*)__null) = 9756; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
9756 "We should have PrincipalToInherit here.")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aLoadState->PrincipalToInherit())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aLoadState->PrincipalToInherit
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("aLoadState->PrincipalToInherit()" " (" "We should have PrincipalToInherit here."
")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 9756); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->PrincipalToInherit()"
") (" "We should have PrincipalToInherit here." ")"); do { *
((volatile int*)__null) = 9756; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
;
9757 attrs = aLoadState->PrincipalToInherit()->OriginAttributesRef();
9758 // If firstPartyIsolation is not enabled, then PrincipalToInherit should
9759 // have the same origin attributes with docshell.
9760 MOZ_ASSERT_IF(!OriginAttributes::IsFirstPartyEnabled(),do { if (!OriginAttributes::IsFirstPartyEnabled()) { do { static_assert
( mozilla::detail::AssertionConditionType<decltype(attrs ==
aOriginAttributes)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(attrs == aOriginAttributes))
), 0))) { do { } while (false); MOZ_ReportAssertionFailure("attrs == aOriginAttributes"
, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 9761); AnnotateMozCrashReason("MOZ_ASSERT" "(" "attrs == aOriginAttributes"
")"); do { *((volatile int*)__null) = 9761; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
9761 attrs == aOriginAttributes)do { if (!OriginAttributes::IsFirstPartyEnabled()) { do { static_assert
( mozilla::detail::AssertionConditionType<decltype(attrs ==
aOriginAttributes)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(attrs == aOriginAttributes))
), 0))) { do { } while (false); MOZ_ReportAssertionFailure("attrs == aOriginAttributes"
, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 9761); AnnotateMozCrashReason("MOZ_ASSERT" "(" "attrs == aOriginAttributes"
")"); do { *((volatile int*)__null) = 9761; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
9762 } else {
9763 attrs = aOriginAttributes;
9764 attrs.SetFirstPartyDomain(IsTopLevelDoc(aBrowsingContext, aLoadInfo),
9765 aLoadState->URI());
9766 }
9767
9768 aRv = aLoadInfo->SetOriginAttributes(attrs);
9769 if (NS_WARN_IF(NS_FAILED(aRv))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(aRv
)), 0))), "NS_FAILED(aRv)", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 9769)
) {
9770 return false;
9771 }
9772
9773 if (aLoadState->GetIsFromProcessingFrameAttributes()) {
9774 aLoadInfo->SetIsFromProcessingFrameAttributes();
9775 }
9776
9777 // Propagate the IsFormSubmission flag to the loadInfo.
9778 if (aLoadState->IsFormSubmission()) {
9779 aLoadInfo->SetIsFormSubmission(true);
9780 }
9781
9782 aLoadInfo->SetUnstrippedURI(aLoadState->GetUnstrippedURI());
9783
9784 nsCOMPtr<nsIChannel> channel;
9785 aRv = CreateRealChannelForDocument(getter_AddRefs(channel), aLoadState->URI(),
9786 aLoadInfo, aCallbacks, aLoadFlags, srcdoc,
9787 aLoadState->BaseURI());
9788 NS_ENSURE_SUCCESS(aRv, false)do { nsresult __rv = aRv; 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", "aRv", "false", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 9788); return false; } } while (false)
;
9789
9790 if (!channel) {
9791 return false;
9792 }
9793
9794 // If the HTTPS-Only mode is enabled, every insecure request gets upgraded to
9795 // HTTPS by default. This behavior can be disabled through the loadinfo flag
9796 // HTTPS_ONLY_EXEMPT.
9797 nsHTTPSOnlyUtils::TestSitePermissionAndPotentiallyAddExemption(channel);
9798
9799 // hack
9800 nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(channel));
9801 nsCOMPtr<nsIHttpChannelInternal> httpChannelInternal(
9802 do_QueryInterface(channel));
9803 nsCOMPtr<nsIURI> referrer;
9804 nsIReferrerInfo* referrerInfo = aLoadState->GetReferrerInfo();
9805 if (referrerInfo) {
9806 referrerInfo->GetOriginalReferrer(getter_AddRefs(referrer));
9807 }
9808 if (httpChannelInternal) {
9809 if (aLoadState->HasInternalLoadFlags(
9810 INTERNAL_LOAD_FLAGS_FORCE_ALLOW_COOKIES)) {
9811 aRv = httpChannelInternal->SetThirdPartyFlags(
9812 nsIHttpChannelInternal::THIRD_PARTY_FORCE_ALLOW);
9813 MOZ_ASSERT(NS_SUCCEEDED(aRv))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(((bool)(__builtin_expect(!!(!NS_FAILED_impl(aRv)), 1
))))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(aRv)), 1
)))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("((bool)(__builtin_expect(!!(!NS_FAILED_impl(aRv)), 1)))", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 9813); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(aRv)), 1)))"
")"); do { *((volatile int*)__null) = 9813; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9814 }
9815 if (aLoadState->FirstParty()) {
9816 aRv = httpChannelInternal->SetDocumentURI(aLoadState->URI());
9817 MOZ_ASSERT(NS_SUCCEEDED(aRv))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(((bool)(__builtin_expect(!!(!NS_FAILED_impl(aRv)), 1
))))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(aRv)), 1
)))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("((bool)(__builtin_expect(!!(!NS_FAILED_impl(aRv)), 1)))", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 9817); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(aRv)), 1)))"
")"); do { *((volatile int*)__null) = 9817; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9818 } else {
9819 aRv = httpChannelInternal->SetDocumentURI(referrer);
9820 MOZ_ASSERT(NS_SUCCEEDED(aRv))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(((bool)(__builtin_expect(!!(!NS_FAILED_impl(aRv)), 1
))))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(aRv)), 1
)))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("((bool)(__builtin_expect(!!(!NS_FAILED_impl(aRv)), 1)))", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 9820); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(aRv)), 1)))"
")"); do { *((volatile int*)__null) = 9820; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9821 }
9822 aRv = httpChannelInternal->SetRedirectMode(
9823 nsIHttpChannelInternal::REDIRECT_MODE_MANUAL);
9824 MOZ_ASSERT(NS_SUCCEEDED(aRv))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(((bool)(__builtin_expect(!!(!NS_FAILED_impl(aRv)), 1
))))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(aRv)), 1
)))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("((bool)(__builtin_expect(!!(!NS_FAILED_impl(aRv)), 1)))", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 9824); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(aRv)), 1)))"
")"); do { *((volatile int*)__null) = 9824; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9825 }
9826
9827 if (httpChannel) {
9828 if (aLoadState->HeadersStream()) {
9829 aRv = AddHeadersToChannel(aLoadState->HeadersStream(), httpChannel);
9830 }
9831 // Set the referrer explicitly
9832 // Referrer is currenly only set for link clicks here.
9833 if (referrerInfo) {
9834 aRv = httpChannel->SetReferrerInfo(referrerInfo);
9835 MOZ_ASSERT(NS_SUCCEEDED(aRv))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(((bool)(__builtin_expect(!!(!NS_FAILED_impl(aRv)), 1
))))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(aRv)), 1
)))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("((bool)(__builtin_expect(!!(!NS_FAILED_impl(aRv)), 1)))", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 9835); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(aRv)), 1)))"
")"); do { *((volatile int*)__null) = 9835; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9836 }
9837
9838 // Mark the http channel as UrgentStart for top level document loading in
9839 // active tab.
9840 if (IsUrgentStart(aBrowsingContext, aLoadInfo, aLoadState->LoadType())) {
9841 nsCOMPtr<nsIClassOfService> cos(do_QueryInterface(channel));
9842 if (cos) {
9843 cos->AddClassFlags(nsIClassOfService::UrgentStart);
9844 if (StaticPrefs::dom_document_priority_incremental()) {
9845 cos->SetIncremental(true);
9846 }
9847 }
9848 }
9849 }
9850
9851 channel->SetOriginalURI(aLoadState->OriginalURI() ? aLoadState->OriginalURI()
9852 : aLoadState->URI());
9853
9854 const nsACString& typeHint = aLoadState->TypeHint();
9855 if (!typeHint.IsVoid()) {
9856 channel->SetContentType(typeHint);
9857 }
9858
9859 const nsAString& fileName = aLoadState->FileName();
9860 if (!fileName.IsVoid()) {
9861 aRv = channel->SetContentDisposition(nsIChannel::DISPOSITION_ATTACHMENT);
9862 NS_ENSURE_SUCCESS(aRv, false)do { nsresult __rv = aRv; 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", "aRv", "false", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 9862); return false; } } while (false)
;
9863 if (!fileName.IsEmpty()) {
9864 aRv = channel->SetContentDispositionFilename(fileName);
9865 NS_ENSURE_SUCCESS(aRv, false)do { nsresult __rv = aRv; 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", "aRv", "false", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 9865); return false; } } while (false)
;
9866 }
9867 }
9868
9869 if (nsCOMPtr<nsIWritablePropertyBag2> props = do_QueryInterface(channel)) {
9870 nsCOMPtr<nsIURI> referrer;
9871 nsIReferrerInfo* referrerInfo = aLoadState->GetReferrerInfo();
9872 if (referrerInfo) {
9873 referrerInfo->GetOriginalReferrer(getter_AddRefs(referrer));
9874 }
9875 // save true referrer for those who need it (e.g. xpinstall whitelisting)
9876 // Currently only http and ftp channels support this.
9877 props->SetPropertyAsInterface(u"docshell.internalReferrer"_ns, referrer);
9878 }
9879
9880 nsCOMPtr<nsICacheInfoChannel> cacheChannel(do_QueryInterface(channel));
9881 auto loadType = aLoadState->LoadType();
9882
9883 if (loadType == LOAD_RELOAD_NORMAL &&
9884 StaticPrefs::
9885 browser_soft_reload_only_force_validate_top_level_document()) {
9886 nsCOMPtr<nsICacheInfoChannel> cachingChannel = do_QueryInterface(channel);
9887 if (cachingChannel) {
9888 cachingChannel->SetForceValidateCacheContent(true);
9889 }
9890 }
9891
9892 // figure out if we need to set the post data stream on the channel...
9893 if (aLoadState->PostDataStream()) {
9894 if (nsCOMPtr<nsIFormPOSTActionChannel> postChannel =
9895 do_QueryInterface(channel)) {
9896 // XXX it's a bit of a hack to rewind the postdata stream here but
9897 // it has to be done in case the post data is being reused multiple
9898 // times.
9899 nsCOMPtr<nsISeekableStream> postDataSeekable =
9900 do_QueryInterface(aLoadState->PostDataStream());
9901 if (postDataSeekable) {
9902 aRv = postDataSeekable->Seek(nsISeekableStream::NS_SEEK_SET, 0);
9903 NS_ENSURE_SUCCESS(aRv, false)do { nsresult __rv = aRv; 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", "aRv", "false", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 9903); return false; } } while (false)
;
9904 }
9905
9906 // we really need to have a content type associated with this stream!!
9907 postChannel->SetUploadStream(aLoadState->PostDataStream(), ""_ns, -1);
9908
9909 // Ownership of the stream has transferred to the channel, clear our
9910 // reference.
9911 aLoadState->SetPostDataStream(nullptr);
9912 }
9913
9914 /* If there is a valid postdata *and* it is a History Load,
9915 * set up the cache key on the channel, to retrieve the
9916 * data *only* from the cache. If it is a normal reload, the
9917 * cache is free to go to the server for updated postdata.
9918 */
9919 if (cacheChannel && aCacheKey != 0) {
9920 if (loadType == LOAD_HISTORY || loadType == LOAD_RELOAD_CHARSET_CHANGE) {
9921 cacheChannel->SetCacheKey(aCacheKey);
9922 uint32_t loadFlags;
9923 if (NS_SUCCEEDED(channel->GetLoadFlags(&loadFlags))((bool)(__builtin_expect(!!(!NS_FAILED_impl(channel->GetLoadFlags
(&loadFlags))), 1)))
) {
9924 channel->SetLoadFlags(loadFlags |
9925 nsICachingChannel::LOAD_ONLY_FROM_CACHE);
9926 }
9927 } else if (loadType == LOAD_RELOAD_NORMAL) {
9928 cacheChannel->SetCacheKey(aCacheKey);
9929 }
9930 }
9931 } else {
9932 /* If there is no postdata, set the cache key on the channel, and
9933 * do not set the LOAD_ONLY_FROM_CACHE flag, so that the channel
9934 * will be free to get it from net if it is not found in cache.
9935 * New cache may use it creatively on CGI pages with GET
9936 * method and even on those that say "no-cache"
9937 */
9938 if (loadType == LOAD_HISTORY || loadType == LOAD_RELOAD_NORMAL ||
9939 loadType == LOAD_RELOAD_CHARSET_CHANGE ||
9940 loadType == LOAD_RELOAD_CHARSET_CHANGE_BYPASS_CACHE ||
9941 loadType == LOAD_RELOAD_CHARSET_CHANGE_BYPASS_PROXY_AND_CACHE) {
9942 if (cacheChannel && aCacheKey != 0) {
9943 cacheChannel->SetCacheKey(aCacheKey);
9944 }
9945 }
9946 }
9947
9948 if (nsCOMPtr<nsIScriptChannel> scriptChannel = do_QueryInterface(channel)) {
9949 // Allow execution against our context if the principals match
9950 scriptChannel->SetExecutionPolicy(nsIScriptChannel::EXECUTE_NORMAL);
9951 }
9952
9953 if (nsCOMPtr<nsITimedChannel> timedChannel = do_QueryInterface(channel)) {
9954 timedChannel->SetTimingEnabled(true);
9955
9956 nsString initiatorType;
9957 switch (aLoadInfo->InternalContentPolicyType()) {
9958 case nsIContentPolicy::TYPE_INTERNAL_EMBED:
9959 initiatorType = u"embed"_ns;
9960 break;
9961 case nsIContentPolicy::TYPE_INTERNAL_OBJECT:
9962 initiatorType = u"object"_ns;
9963 break;
9964 default: {
9965 const auto& embedderElementType =
9966 aBrowsingContext->GetEmbedderElementType();
9967 if (embedderElementType) {
9968 initiatorType = *embedderElementType;
9969 }
9970 break;
9971 }
9972 }
9973
9974 if (!initiatorType.IsEmpty()) {
9975 timedChannel->SetInitiatorType(initiatorType);
9976 }
9977 }
9978
9979 nsCOMPtr<nsIURI> rpURI;
9980 aLoadInfo->GetResultPrincipalURI(getter_AddRefs(rpURI));
9981 Maybe<nsCOMPtr<nsIURI>> originalResultPrincipalURI;
9982 aLoadState->GetMaybeResultPrincipalURI(originalResultPrincipalURI);
9983 if (originalResultPrincipalURI &&
9984 (!aLoadState->KeepResultPrincipalURIIfSet() || !rpURI)) {
9985 // Unconditionally override, we want the replay to be equal to what has
9986 // been captured.
9987 aLoadInfo->SetResultPrincipalURI(originalResultPrincipalURI.ref());
9988 }
9989
9990 if (aLoadState->OriginalURI() && aLoadState->LoadReplace()) {
9991 // The LOAD_REPLACE flag and its handling here will be removed as part
9992 // of bug 1319110. For now preserve its restoration here to not break
9993 // any code expecting it being set specially on redirected channels.
9994 // If the flag has originally been set to change result of
9995 // NS_GetFinalChannelURI it won't have any effect and also won't cause
9996 // any harm.
9997 uint32_t loadFlags;
9998 aRv = channel->GetLoadFlags(&loadFlags);
9999 NS_ENSURE_SUCCESS(aRv, false)do { nsresult __rv = aRv; 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", "aRv", "false", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 9999); return false; } } while (false)
;
10000 channel->SetLoadFlags(loadFlags | nsIChannel::LOAD_REPLACE);
10001 }
10002
10003 nsCOMPtr<nsIContentSecurityPolicy> csp = aLoadState->Csp();
10004 if (csp) {
10005 // Navigational requests that are same origin need to be upgraded in case
10006 // upgrade-insecure-requests is present. Please note that for document
10007 // navigations that bit is re-computed in case we encounter a server
10008 // side redirect so the navigation is not same-origin anymore.
10009 bool upgradeInsecureRequests = false;
10010 csp->GetUpgradeInsecureRequests(&upgradeInsecureRequests);
10011 if (upgradeInsecureRequests) {
10012 // only upgrade if the navigation is same origin
10013 nsCOMPtr<nsIPrincipal> resultPrincipal;
10014 aRv = nsContentUtils::GetSecurityManager()->GetChannelResultPrincipal(
10015 channel, getter_AddRefs(resultPrincipal));
10016 NS_ENSURE_SUCCESS(aRv, false)do { nsresult __rv = aRv; 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", "aRv", "false", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 10016); return false; } } while (false)
;
10017 if (nsContentSecurityUtils::IsConsideredSameOriginForUIR(
10018 aLoadState->TriggeringPrincipal(), resultPrincipal)) {
10019 aLoadInfo->SetUpgradeInsecureRequests(true);
10020 }
10021 }
10022
10023 // For document loads we store the CSP that potentially needs to
10024 // be inherited by the new document, e.g. in case we are loading
10025 // an opaque origin like a data: URI. The actual inheritance
10026 // check happens within Document::InitCSP().
10027 // Please create an actual copy of the CSP (do not share the same
10028 // reference) otherwise a Meta CSP of an opaque origin will
10029 // incorrectly be propagated to the embedding document.
10030 RefPtr<nsCSPContext> cspToInherit = new nsCSPContext();
10031 cspToInherit->InitFromOther(static_cast<nsCSPContext*>(csp.get()));
10032 aLoadInfo->SetCSPToInherit(cspToInherit);
10033 }
10034
10035 channel.forget(aChannel);
10036 return true;
10037}
10038
10039bool nsDocShell::IsAboutBlankLoadOntoInitialAboutBlank(
10040 nsIURI* aURI, bool aInheritPrincipal, nsIPrincipal* aPrincipalToInherit) {
10041 return NS_IsAboutBlankAllowQueryAndFragment(aURI) && aInheritPrincipal &&
10042 (aPrincipalToInherit == GetInheritedPrincipal(false)) &&
10043 (!mDocumentViewer || !mDocumentViewer->GetDocument() ||
10044 mDocumentViewer->GetDocument()->IsInitialDocument());
10045}
10046
10047nsresult nsDocShell::DoURILoad(nsDocShellLoadState* aLoadState,
10048 Maybe<uint32_t> aCacheKey,
10049 nsIRequest** aRequest) {
10050 // Double-check that we're still around to load this URI.
10051 if (mIsBeingDestroyed) {
10052 // Return NS_OK despite not doing anything to avoid throwing exceptions
10053 // from nsLocation::SetHref if the unload handler of the existing page
10054 // tears us down.
10055 return NS_OK;
10056 }
10057
10058 nsCOMPtr<nsIURILoader> uriLoader = components::URILoader::Service();
10059 if (NS_WARN_IF(!uriLoader)NS_warn_if_impl(!uriLoader, "!uriLoader", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 10059)
) {
10060 return NS_ERROR_UNEXPECTED;
10061 }
10062
10063 // Persist and sync layout history state before we load a new uri, as this
10064 // might be our last chance to do so, in the content process.
10065 PersistLayoutHistoryState();
10066 SynchronizeLayoutHistoryState();
10067
10068 nsresult rv;
10069 nsContentPolicyType contentPolicyType = DetermineContentType();
10070
10071 if (IsSubframe()) {
10072 MOZ_ASSERT(contentPolicyType == nsIContentPolicy::TYPE_INTERNAL_IFRAME ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(contentPolicyType == nsIContentPolicy::TYPE_INTERNAL_IFRAME
|| contentPolicyType == nsIContentPolicy::TYPE_INTERNAL_FRAME
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(contentPolicyType == nsIContentPolicy::TYPE_INTERNAL_IFRAME
|| contentPolicyType == nsIContentPolicy::TYPE_INTERNAL_FRAME
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"contentPolicyType == nsIContentPolicy::TYPE_INTERNAL_IFRAME || contentPolicyType == nsIContentPolicy::TYPE_INTERNAL_FRAME"
" (" "DoURILoad thinks this is a frame and InternalLoad does not"
")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 10074); AnnotateMozCrashReason("MOZ_ASSERT" "(" "contentPolicyType == nsIContentPolicy::TYPE_INTERNAL_IFRAME || contentPolicyType == nsIContentPolicy::TYPE_INTERNAL_FRAME"
") (" "DoURILoad thinks this is a frame and InternalLoad does not"
")"); do { *((volatile int*)__null) = 10074; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
10073 contentPolicyType == nsIContentPolicy::TYPE_INTERNAL_FRAME,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(contentPolicyType == nsIContentPolicy::TYPE_INTERNAL_IFRAME
|| contentPolicyType == nsIContentPolicy::TYPE_INTERNAL_FRAME
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(contentPolicyType == nsIContentPolicy::TYPE_INTERNAL_IFRAME
|| contentPolicyType == nsIContentPolicy::TYPE_INTERNAL_FRAME
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"contentPolicyType == nsIContentPolicy::TYPE_INTERNAL_IFRAME || contentPolicyType == nsIContentPolicy::TYPE_INTERNAL_FRAME"
" (" "DoURILoad thinks this is a frame and InternalLoad does not"
")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 10074); AnnotateMozCrashReason("MOZ_ASSERT" "(" "contentPolicyType == nsIContentPolicy::TYPE_INTERNAL_IFRAME || contentPolicyType == nsIContentPolicy::TYPE_INTERNAL_FRAME"
") (" "DoURILoad thinks this is a frame and InternalLoad does not"
")"); do { *((volatile int*)__null) = 10074; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
10074 "DoURILoad thinks this is a frame and InternalLoad does not")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(contentPolicyType == nsIContentPolicy::TYPE_INTERNAL_IFRAME
|| contentPolicyType == nsIContentPolicy::TYPE_INTERNAL_FRAME
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(contentPolicyType == nsIContentPolicy::TYPE_INTERNAL_IFRAME
|| contentPolicyType == nsIContentPolicy::TYPE_INTERNAL_FRAME
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"contentPolicyType == nsIContentPolicy::TYPE_INTERNAL_IFRAME || contentPolicyType == nsIContentPolicy::TYPE_INTERNAL_FRAME"
" (" "DoURILoad thinks this is a frame and InternalLoad does not"
")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 10074); AnnotateMozCrashReason("MOZ_ASSERT" "(" "contentPolicyType == nsIContentPolicy::TYPE_INTERNAL_IFRAME || contentPolicyType == nsIContentPolicy::TYPE_INTERNAL_FRAME"
") (" "DoURILoad thinks this is a frame and InternalLoad does not"
")"); do { *((volatile int*)__null) = 10074; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10075
10076 if (auto* iframe = HTMLIFrameElement::FromNodeOrNull(
10077 mBrowsingContext->GetEmbedderElement())) {
10078 // Per spec, reload doesn't cacel lazy loading iframes.
10079 if (!(aLoadState->LoadType() & LOAD_RELOAD_NORMAL)) {
10080 iframe->CancelLazyLoading(true /* aClearLazyLoadState */);
10081 }
10082 }
10083
10084 if (StaticPrefs::dom_block_external_protocol_in_iframes()) {
10085 // Only allow URLs able to return data in iframes.
10086 if (nsContentUtils::IsExternalProtocol(aLoadState->URI())) {
10087 // The context to check user-interaction with for the purposes of
10088 // popup-blocking.
10089 //
10090 // We generally want to check the context that initiated the navigation.
10091 WindowContext* sourceWindowContext = [&] {
10092 const MaybeDiscardedBrowsingContext& sourceBC =
10093 aLoadState->SourceBrowsingContext();
10094 if (!sourceBC.IsNullOrDiscarded()) {
10095 if (WindowContext* wc = sourceBC.get()->GetCurrentWindowContext()) {
10096 return wc;
10097 }
10098 }
10099 return mBrowsingContext->GetParentWindowContext();
10100 }();
10101
10102 MOZ_ASSERT(sourceWindowContext)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(sourceWindowContext)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(sourceWindowContext))), 0)))
{ do { } while (false); MOZ_ReportAssertionFailure("sourceWindowContext"
, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 10102); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sourceWindowContext"
")"); do { *((volatile int*)__null) = 10102; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10103 // FIXME: We can't check user-interaction against an OOP window. This is
10104 // the next best thing we can really do. The load state keeps whether
10105 // the navigation had a user interaction in process
10106 // (aLoadState->HasValidUserGestureActivation()), but we can't really
10107 // consume it, which we want to prevent popup-spamming from the same
10108 // click event.
10109 WindowContext* context =
10110 sourceWindowContext->IsInProcess()
10111 ? sourceWindowContext
10112 : mBrowsingContext->GetCurrentWindowContext();
10113 const bool popupBlocked = [&] {
10114 const bool active = mBrowsingContext->IsActive();
10115
10116 // For same-origin-with-top windows, we grant a single free popup
10117 // without user activation, see bug 1680721.
10118 //
10119 // We consume the flag now even if there's no user activation.
10120 const bool hasFreePass = [&] {
10121 if (!active ||
10122 !(context->IsInProcess() && context->SameOriginWithTop())) {
10123 return false;
10124 }
10125 nsGlobalWindowInner* win =
10126 context->TopWindowContext()->GetInnerWindow();
10127 return win && win->TryOpenExternalProtocolIframe();
10128 }();
10129
10130 if (context->IsInProcess() &&
10131 context->ConsumeTransientUserGestureActivation()) {
10132 // If the user has interacted with the page, consume it.
10133 return false;
10134 }
10135
10136 // TODO(emilio): Can we remove this check? It seems like what prompted
10137 // this code (bug 1514547) should be covered by transient user
10138 // activation, see bug 1514547.
10139 if (active &&
10140 PopupBlocker::ConsumeTimerTokenForExternalProtocolIframe()) {
10141 return false;
10142 }
10143
10144 if (sourceWindowContext->CanShowPopup()) {
10145 return false;
10146 }
10147
10148 if (hasFreePass) {
10149 return false;
10150 }
10151
10152 return true;
10153 }();
10154
10155 // No error must be returned when iframes are blocked.
10156 if (popupBlocked) {
10157 nsAutoString message;
10158 nsresult rv = nsContentUtils::GetLocalizedString(
10159 nsContentUtils::eDOM_PROPERTIES,
10160 "ExternalProtocolFrameBlockedNoUserActivation", message);
10161 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
10162 nsContentUtils::ReportToConsoleByWindowID(
10163 message, nsIScriptError::warningFlag, "DOM"_ns,
10164 context->InnerWindowId());
10165 }
10166 return NS_OK;
10167 }
10168 }
10169 }
10170
10171 // Only allow view-source scheme in top-level docshells. view-source is
10172 // the only scheme to which this applies at the moment due to potential
10173 // timing attacks to read data from cross-origin iframes. If this widens
10174 // we should add a protocol flag for whether the scheme is allowed in
10175 // frames and use something like nsNetUtil::NS_URIChainHasFlags.
10176 nsCOMPtr<nsIURI> tempURI = aLoadState->URI();
10177 nsCOMPtr<nsINestedURI> nestedURI = do_QueryInterface(tempURI);
10178 while (nestedURI) {
10179 // view-source should always be an nsINestedURI, loop and check the
10180 // scheme on this and all inner URIs that are also nested URIs.
10181 if (SchemeIsViewSource(tempURI)) {
10182 return NS_ERROR_UNKNOWN_PROTOCOL;
10183 }
10184 nestedURI->GetInnerURI(getter_AddRefs(tempURI));
10185 nestedURI = do_QueryInterface(tempURI);
10186 }
10187 } else {
10188 MOZ_ASSERT(contentPolicyType == nsIContentPolicy::TYPE_DOCUMENT,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(contentPolicyType == nsIContentPolicy::TYPE_DOCUMENT
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(contentPolicyType == nsIContentPolicy::TYPE_DOCUMENT
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"contentPolicyType == nsIContentPolicy::TYPE_DOCUMENT" " (" "DoURILoad thinks this is a document and InternalLoad does not"
")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 10189); AnnotateMozCrashReason("MOZ_ASSERT" "(" "contentPolicyType == nsIContentPolicy::TYPE_DOCUMENT"
") (" "DoURILoad thinks this is a document and InternalLoad does not"
")"); do { *((volatile int*)__null) = 10189; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
10189 "DoURILoad thinks this is a document and InternalLoad does not")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(contentPolicyType == nsIContentPolicy::TYPE_DOCUMENT
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(contentPolicyType == nsIContentPolicy::TYPE_DOCUMENT
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"contentPolicyType == nsIContentPolicy::TYPE_DOCUMENT" " (" "DoURILoad thinks this is a document and InternalLoad does not"
")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 10189); AnnotateMozCrashReason("MOZ_ASSERT" "(" "contentPolicyType == nsIContentPolicy::TYPE_DOCUMENT"
") (" "DoURILoad thinks this is a document and InternalLoad does not"
")"); do { *((volatile int*)__null) = 10189; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10190 }
10191
10192 // We want to inherit aLoadState->PrincipalToInherit() when:
10193 // 1. ChannelShouldInheritPrincipal returns true.
10194 // 2. aLoadState->URI() is not data: URI, or data: URI is not
10195 // configured as unique opaque origin.
10196 bool inheritPrincipal = false;
10197
10198 if (aLoadState->PrincipalToInherit()) {
10199 bool isSrcdoc =
10200 aLoadState->HasInternalLoadFlags(INTERNAL_LOAD_FLAGS_IS_SRCDOC);
10201 bool inheritAttrs = nsContentUtils::ChannelShouldInheritPrincipal(
10202 aLoadState->PrincipalToInherit(), aLoadState->URI(),
10203 true, // aInheritForAboutBlank
10204 isSrcdoc);
10205
10206 inheritPrincipal = inheritAttrs && !SchemeIsData(aLoadState->URI());
10207 }
10208
10209 // See https://bugzilla.mozilla.org/show_bug.cgi?id=1736570
10210 const bool isAboutBlankLoadOntoInitialAboutBlank =
10211 IsAboutBlankLoadOntoInitialAboutBlank(aLoadState->URI(), inheritPrincipal,
10212 aLoadState->PrincipalToInherit());
10213
10214 // FIXME We still have a ton of codepaths that don't pass through
10215 // DocumentLoadListener, so probably need to create session history info
10216 // in more places.
10217 if (aLoadState->GetLoadingSessionHistoryInfo()) {
10218 SetLoadingSessionHistoryInfo(*aLoadState->GetLoadingSessionHistoryInfo());
10219 } else if (isAboutBlankLoadOntoInitialAboutBlank &&
10220 mozilla::SessionHistoryInParent()) {
10221 // Materialize LoadingSessionHistoryInfo here, because DocumentChannel
10222 // loads have it, and later history behavior depends on it existing.
10223 UniquePtr<SessionHistoryInfo> entry = MakeUnique<SessionHistoryInfo>(
10224 aLoadState->URI(), aLoadState->TriggeringPrincipal(),
10225 aLoadState->PrincipalToInherit(),
10226 aLoadState->PartitionedPrincipalToInherit(), aLoadState->Csp(),
10227 mContentTypeHint);
10228 mozilla::dom::LoadingSessionHistoryInfo info(*entry);
10229 SetLoadingSessionHistoryInfo(info, true);
10230 }
10231
10232 // open a channel for the url
10233
10234 // If we have a pending channel, use the channel we've already created here.
10235 // We don't need to set up load flags for our channel, as it has already been
10236 // created.
10237
10238 if (nsCOMPtr<nsIChannel> channel =
10239 aLoadState->GetPendingRedirectedChannel()) {
10240 // If we have a request outparameter, shove our channel into it.
10241 if (aRequest) {
10242 nsCOMPtr<nsIRequest> outRequest = channel;
10243 outRequest.forget(aRequest);
10244 }
10245
10246 return OpenRedirectedChannel(aLoadState);
10247 }
10248
10249 // There are two cases we care about:
10250 // * Top-level load: In this case, loadingNode is null, but loadingWindow
10251 // is our mScriptGlobal. We pass null for loadingPrincipal in this case.
10252 // * Subframe load: loadingWindow is null, but loadingNode is the frame
10253 // element for the load. loadingPrincipal is the NodePrincipal of the
10254 // frame element.
10255 nsCOMPtr<nsINode> loadingNode;
10256 nsCOMPtr<nsPIDOMWindowOuter> loadingWindow;
10257 nsCOMPtr<nsIPrincipal> loadingPrincipal;
10258 nsCOMPtr<nsISupports> topLevelLoadingContext;
10259
10260 if (contentPolicyType == nsIContentPolicy::TYPE_DOCUMENT) {
10261 loadingNode = nullptr;
10262 loadingPrincipal = nullptr;
10263 loadingWindow = mScriptGlobal;
10264 if (XRE_IsContentProcess()) {
10265 // In e10s the child process doesn't have access to the element that
10266 // contains the browsing context (because that element is in the chrome
10267 // process).
10268 nsCOMPtr<nsIBrowserChild> browserChild = GetBrowserChild();
10269 topLevelLoadingContext = ToSupports(browserChild);
10270 } else {
10271 // This is for loading non-e10s tabs and toplevel windows of various
10272 // sorts.
10273 // For the toplevel window cases, requestingElement will be null.
10274 nsCOMPtr<Element> requestingElement =
10275 loadingWindow->GetFrameElementInternal();
10276 topLevelLoadingContext = requestingElement;
10277 }
10278 } else {
10279 loadingWindow = nullptr;
10280 loadingNode = mScriptGlobal->GetFrameElementInternal();
10281 if (loadingNode) {
10282 // If we have a loading node, then use that as our loadingPrincipal.
10283 loadingPrincipal = loadingNode->NodePrincipal();
10284#ifdef DEBUG1
10285 // Get the docshell type for requestingElement.
10286 RefPtr<Document> requestingDoc = loadingNode->OwnerDoc();
10287 nsCOMPtr<nsIDocShell> elementDocShell = requestingDoc->GetDocShell();
10288 // requestingElement docshell type = current docshell type.
10289 MOZ_ASSERT(do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mItemType == elementDocShell->ItemType())>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(mItemType == elementDocShell->ItemType()))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("mItemType == elementDocShell->ItemType()"
" (" "subframes should have the same docshell type as their parent"
")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 10291); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mItemType == elementDocShell->ItemType()"
") (" "subframes should have the same docshell type as their parent"
")"); do { *((volatile int*)__null) = 10291; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
10290 mItemType == elementDocShell->ItemType(),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mItemType == elementDocShell->ItemType())>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(mItemType == elementDocShell->ItemType()))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("mItemType == elementDocShell->ItemType()"
" (" "subframes should have the same docshell type as their parent"
")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 10291); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mItemType == elementDocShell->ItemType()"
") (" "subframes should have the same docshell type as their parent"
")"); do { *((volatile int*)__null) = 10291; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
10291 "subframes should have the same docshell type as their parent")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mItemType == elementDocShell->ItemType())>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(mItemType == elementDocShell->ItemType()))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("mItemType == elementDocShell->ItemType()"
" (" "subframes should have the same docshell type as their parent"
")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 10291); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mItemType == elementDocShell->ItemType()"
") (" "subframes should have the same docshell type as their parent"
")"); do { *((volatile int*)__null) = 10291; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10292#endif
10293 } else {
10294 if (mIsBeingDestroyed) {
10295 // If this isn't a top-level load and mScriptGlobal's frame element is
10296 // null, then the element got removed from the DOM while we were trying
10297 // to load this resource. This docshell is scheduled for destruction
10298 // already, so bail out here.
10299 return NS_OK;
10300 }
10301 // If we are not being destroyed and we do not have access to the loading
10302 // node, then we are a remote subframe. Set the loading principal
10303 // to be a null principal and then set it correctly in the parent.
10304 loadingPrincipal = NullPrincipal::Create(GetOriginAttributes(), nullptr);
10305 }
10306 }
10307
10308 if (!aLoadState->TriggeringPrincipal()) {
10309 MOZ_ASSERT(false, "DoURILoad needs a valid triggeringPrincipal")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "DoURILoad needs a valid triggeringPrincipal"
")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 10309); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"DoURILoad needs a valid triggeringPrincipal" ")"); do { *((
volatile int*)__null) = 10309; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
;
10310 return NS_ERROR_FAILURE;
10311 }
10312
10313 uint32_t sandboxFlags = mBrowsingContext->GetSandboxFlags();
10314 nsSecurityFlags securityFlags =
10315 nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_SEC_CONTEXT_IS_NULL;
10316
10317 if (mLoadType == LOAD_ERROR_PAGE) {
10318 securityFlags |= nsILoadInfo::SEC_LOAD_ERROR_PAGE;
10319 }
10320
10321 if (inheritPrincipal) {
10322 securityFlags |= nsILoadInfo::SEC_FORCE_INHERIT_PRINCIPAL;
10323 }
10324
10325 // Must never have a parent for TYPE_DOCUMENT loads
10326 MOZ_ASSERT_IF(contentPolicyType == nsIContentPolicy::TYPE_DOCUMENT,do { if (contentPolicyType == nsIContentPolicy::TYPE_DOCUMENT
) { do { static_assert( mozilla::detail::AssertionConditionType
<decltype(!mBrowsingContext->GetParent())>::isValid,
"invalid assertion condition"); if ((__builtin_expect(!!(!(!
!(!mBrowsingContext->GetParent()))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("!mBrowsingContext->GetParent()"
, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 10327); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mBrowsingContext->GetParent()"
")"); do { *((volatile int*)__null) = 10327; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false); } } while
(false)
10327 !mBrowsingContext->GetParent())do { if (contentPolicyType == nsIContentPolicy::TYPE_DOCUMENT
) { do { static_assert( mozilla::detail::AssertionConditionType
<decltype(!mBrowsingContext->GetParent())>::isValid,
"invalid assertion condition"); if ((__builtin_expect(!!(!(!
!(!mBrowsingContext->GetParent()))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("!mBrowsingContext->GetParent()"
, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 10327); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mBrowsingContext->GetParent()"
")"); do { *((volatile int*)__null) = 10327; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false); } } while
(false)
;
10328 // Subdocuments must have a parent
10329 MOZ_ASSERT_IF(contentPolicyType == nsIContentPolicy::TYPE_SUBDOCUMENT,do { if (contentPolicyType == nsIContentPolicy::TYPE_SUBDOCUMENT
) { do { static_assert( mozilla::detail::AssertionConditionType
<decltype(mBrowsingContext->GetParent())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mBrowsingContext->GetParent
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("mBrowsingContext->GetParent()", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 10330); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mBrowsingContext->GetParent()"
")"); do { *((volatile int*)__null) = 10330; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false); } } while
(false)
10330 mBrowsingContext->GetParent())do { if (contentPolicyType == nsIContentPolicy::TYPE_SUBDOCUMENT
) { do { static_assert( mozilla::detail::AssertionConditionType
<decltype(mBrowsingContext->GetParent())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mBrowsingContext->GetParent
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("mBrowsingContext->GetParent()", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 10330); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mBrowsingContext->GetParent()"
")"); do { *((volatile int*)__null) = 10330; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false); } } while
(false)
;
10331 mBrowsingContext->SetTriggeringAndInheritPrincipals(
10332 aLoadState->TriggeringPrincipal(), aLoadState->PrincipalToInherit(),
10333 aLoadState->GetLoadIdentifier());
10334 RefPtr<LoadInfo> loadInfo =
10335 (contentPolicyType == nsIContentPolicy::TYPE_DOCUMENT)
10336 ? new LoadInfo(loadingWindow, aLoadState->URI(),
10337 aLoadState->TriggeringPrincipal(),
10338 topLevelLoadingContext, securityFlags, sandboxFlags)
10339 : new LoadInfo(loadingPrincipal, aLoadState->TriggeringPrincipal(),
10340 loadingNode, securityFlags, contentPolicyType,
10341 Maybe<mozilla::dom::ClientInfo>(),
10342 Maybe<mozilla::dom::ServiceWorkerDescriptor>(),
10343 sandboxFlags);
10344 RefPtr<WindowContext> context = mBrowsingContext->GetCurrentWindowContext();
10345
10346 if (isAboutBlankLoadOntoInitialAboutBlank) {
10347 // Match the DocumentChannel case where the default for third-partiness
10348 // differs from the default in LoadInfo construction here.
10349 // toolkit/components/antitracking/test/browser/browser_aboutblank.js
10350 // fails without this.
10351 BrowsingContext* top = mBrowsingContext->Top();
10352 if (top == mBrowsingContext) {
10353 // If we're at the top, this must be a window.open()ed
10354 // window, and we can't be third-party relative to ourselves.
10355 loadInfo->SetIsThirdPartyContextToTopWindow(false);
10356 } else {
10357 if (Document* topDoc = top->GetDocument()) {
10358 bool thirdParty = false;
10359 mozilla::Unused << topDoc->GetPrincipal()->IsThirdPartyPrincipal(
10360 aLoadState->PrincipalToInherit(), &thirdParty);
10361 loadInfo->SetIsThirdPartyContextToTopWindow(thirdParty);
10362 } else {
10363 // If top is in a different process, we have to be third-party relative
10364 // to it.
10365 loadInfo->SetIsThirdPartyContextToTopWindow(true);
10366 }
10367 }
10368 }
10369
10370 if (mLoadType != LOAD_ERROR_PAGE && context && context->IsInProcess()) {
10371 if (context->HasValidTransientUserGestureActivation()) {
10372 aLoadState->SetHasValidUserGestureActivation(true);
10373 aLoadState->SetTextDirectiveUserActivation(true);
10374 }
10375 if (!aLoadState->TriggeringWindowId()) {
10376 aLoadState->SetTriggeringWindowId(context->Id());
10377 }
10378 if (!aLoadState->TriggeringStorageAccess()) {
10379 Document* contextDoc = context->GetExtantDoc();
10380 if (contextDoc) {
10381 aLoadState->SetTriggeringStorageAccess(
10382 contextDoc->UsingStorageAccess());
10383 }
10384 }
10385 }
10386
10387 // in case this docshell load was triggered by a valid transient user gesture,
10388 // or also the load originates from external, then we pass that information on
10389 // to the loadinfo, which allows e.g. setting Sec-Fetch-User request headers.
10390 if (aLoadState->HasValidUserGestureActivation() ||
10391 aLoadState->HasLoadFlags(LOAD_FLAGS_FROM_EXTERNAL)) {
10392 loadInfo->SetHasValidUserGestureActivation(true);
10393 aLoadState->SetTextDirectiveUserActivation(true);
10394 }
10395
10396 loadInfo->SetTextDirectiveUserActivation(
10397 aLoadState->GetTextDirectiveUserActivation());
10398
10399 loadInfo->SetTriggeringWindowId(aLoadState->TriggeringWindowId());
10400 loadInfo->SetTriggeringStorageAccess(aLoadState->TriggeringStorageAccess());
10401 loadInfo->SetTriggeringSandboxFlags(aLoadState->TriggeringSandboxFlags());
10402 loadInfo->SetIsMetaRefresh(aLoadState->IsMetaRefresh());
10403
10404 uint32_t cacheKey = 0;
10405 if (aCacheKey) {
10406 cacheKey = *aCacheKey;
10407 } else if (mozilla::SessionHistoryInParent()) {
10408 if (mLoadingEntry) {
10409 cacheKey = mLoadingEntry->mInfo.GetCacheKey();
10410 } else if (mActiveEntry) { // for reload cases
10411 cacheKey = mActiveEntry->GetCacheKey();
10412 }
10413 } else {
10414 if (mLSHE) {
10415 cacheKey = mLSHE->GetCacheKey();
10416 } else if (mOSHE) { // for reload cases
10417 cacheKey = mOSHE->GetCacheKey();
10418 }
10419 }
10420
10421 bool uriModified;
10422 if (mLSHE || mLoadingEntry) {
10423 if (mLoadingEntry) {
10424 uriModified = mLoadingEntry->mInfo.GetURIWasModified();
10425 } else {
10426 uriModified = mLSHE->GetURIWasModified();
10427 }
10428 } else {
10429 uriModified = false;
10430 }
10431
10432 bool isEmbeddingBlockedError = false;
10433 if (mFailedChannel) {
10434 nsresult status;
10435 mFailedChannel->GetStatus(&status);
10436 isEmbeddingBlockedError = status == NS_ERROR_XFO_VIOLATION ||
10437 status == NS_ERROR_CSP_FRAME_ANCESTOR_VIOLATION;
10438 }
10439
10440 nsLoadFlags loadFlags = aLoadState->CalculateChannelLoadFlags(
10441 mBrowsingContext, Some(uriModified), Some(isEmbeddingBlockedError));
10442
10443 nsCOMPtr<nsIChannel> channel;
10444 if (DocumentChannel::CanUseDocumentChannel(aLoadState->URI()) &&
10445 !isAboutBlankLoadOntoInitialAboutBlank) {
10446 channel = DocumentChannel::CreateForDocument(
10447 aLoadState, loadInfo, loadFlags, this, cacheKey, uriModified,
10448 isEmbeddingBlockedError);
10449 MOZ_ASSERT(channel)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(channel)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(channel))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("channel", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 10449); AnnotateMozCrashReason("MOZ_ASSERT" "(" "channel" ")"
); do { *((volatile int*)__null) = 10449; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
10450
10451 // Disable keyword fixup when using DocumentChannel, since
10452 // DocumentLoadListener will handle this for us (in the parent process).
10453 mAllowKeywordFixup = false;
10454 } else if (!CreateAndConfigureRealChannelForLoadState(
10455 mBrowsingContext, aLoadState, loadInfo, this, this,
10456 GetOriginAttributes(), loadFlags, cacheKey, rv,
10457 getter_AddRefs(channel))) {
10458 return rv;
10459 }
10460
10461 // Make sure to give the caller a channel if we managed to create one
10462 // This is important for correct error page/session history interaction
10463 if (aRequest) {
10464 NS_ADDREF(*aRequest = channel)(*aRequest = channel)->AddRef();
10465 }
10466
10467 const nsACString& typeHint = aLoadState->TypeHint();
10468 if (!typeHint.IsVoid()) {
10469 mContentTypeHint = typeHint;
10470 } else {
10471 mContentTypeHint.Truncate();
10472 }
10473
10474 // Load attributes depend on load type...
10475 if (mLoadType == LOAD_RELOAD_CHARSET_CHANGE) {
10476 // Use SetAllowStaleCacheContent (not LOAD_FROM_CACHE flag) since we
10477 // only want to force cache load for this channel, not the whole
10478 // loadGroup.
10479 nsCOMPtr<nsICacheInfoChannel> cachingChannel = do_QueryInterface(channel);
10480 if (cachingChannel) {
10481 cachingChannel->SetAllowStaleCacheContent(true);
10482 }
10483 }
10484
10485 uint32_t openFlags =
10486 nsDocShell::ComputeURILoaderFlags(mBrowsingContext, mLoadType);
10487 return OpenInitializedChannel(channel, uriLoader, openFlags);
10488}
10489
10490static nsresult AppendSegmentToString(nsIInputStream* aIn, void* aClosure,
10491 const char* aFromRawSegment,
10492 uint32_t aToOffset, uint32_t aCount,
10493 uint32_t* aWriteCount) {
10494 // aFromSegment now contains aCount bytes of data.
10495
10496 nsAutoCString* buf = static_cast<nsAutoCString*>(aClosure);
10497 buf->Append(aFromRawSegment, aCount);
10498
10499 // Indicate that we have consumed all of aFromSegment
10500 *aWriteCount = aCount;
10501 return NS_OK;
10502}
10503
10504/* static */ nsresult nsDocShell::AddHeadersToChannel(
10505 nsIInputStream* aHeadersData, nsIChannel* aGenericChannel) {
10506 nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(aGenericChannel);
10507 NS_ENSURE_STATE(httpChannel)do { if ((__builtin_expect(!!(!(httpChannel)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "httpChannel" ") failed"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 10507); return NS_ERROR_UNEXPECTED; } } while (false)
;
10508
10509 uint32_t numRead;
10510 nsAutoCString headersString;
10511 nsresult rv = aHeadersData->ReadSegments(
10512 AppendSegmentToString, &headersString, UINT32_MAX(4294967295U), &numRead);
10513 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/docshell/base/nsDocShell.cpp"
, 10513); return rv; } } while (false)
;
10514
10515 // used during the manipulation of the String from the InputStream
10516 nsAutoCString headerName;
10517 nsAutoCString headerValue;
10518 int32_t crlf;
10519 int32_t colon;
10520
10521 //
10522 // Iterate over the headersString: for each "\r\n" delimited chunk,
10523 // add the value as a header to the nsIHttpChannel
10524 //
10525
10526 static const char kWhitespace[] = "\b\t\r\n ";
10527 while (true) {
10528 crlf = headersString.Find("\r\n");
10529 if (crlf == kNotFound) {
10530 return NS_OK;
10531 }
10532
10533 const nsACString& oneHeader = StringHead(headersString, crlf);
10534
10535 colon = oneHeader.FindChar(':');
10536 if (colon == kNotFound) {
10537 return NS_ERROR_UNEXPECTED;
10538 }
10539
10540 headerName = StringHead(oneHeader, colon);
10541 headerValue = Substring(oneHeader, colon + 1);
10542
10543 headerName.Trim(kWhitespace);
10544 headerValue.Trim(kWhitespace);
10545
10546 headersString.Cut(0, crlf + 2);
10547
10548 //
10549 // FINALLY: we can set the header!
10550 //
10551
10552 rv = httpChannel->SetRequestHeader(headerName, headerValue, true);
10553 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/docshell/base/nsDocShell.cpp"
, 10553); return rv; } } while (false)
;
10554 }
10555
10556 MOZ_ASSERT_UNREACHABLE("oops")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "MOZ_ASSERT_UNREACHABLE: "
"oops" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 10556); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "oops" ")"); do { *((volatile int
*)__null) = 10556; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
10557 return NS_ERROR_UNEXPECTED;
10558}
10559
10560/* static */ uint32_t nsDocShell::ComputeURILoaderFlags(
10561 BrowsingContext* aBrowsingContext, uint32_t aLoadType,
10562 bool aIsDocumentLoad) {
10563 MOZ_ASSERT(aBrowsingContext)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aBrowsingContext)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aBrowsingContext))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("aBrowsingContext"
, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 10563); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aBrowsingContext"
")"); do { *((volatile int*)__null) = 10563; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10564
10565 uint32_t openFlags = 0;
10566 if (aLoadType == LOAD_LINK) {
10567 openFlags |= nsIURILoader::IS_CONTENT_PREFERRED;
10568 }
10569 if (!aBrowsingContext->GetAllowContentRetargeting()) {
10570 openFlags |= nsIURILoader::DONT_RETARGET;
10571 }
10572
10573 // Unless the pref is set, object/embed loads always specify DONT_RETARGET.
10574 // See bug 1868001 for details.
10575 if (!aIsDocumentLoad &&
10576 !StaticPrefs::dom_navigation_object_embed_allow_retargeting()) {
10577 openFlags |= nsIURILoader::DONT_RETARGET;
10578 }
10579
10580 return openFlags;
10581}
10582
10583nsresult nsDocShell::OpenInitializedChannel(nsIChannel* aChannel,
10584 nsIURILoader* aURILoader,
10585 uint32_t aOpenFlags) {
10586 nsresult rv = NS_OK;
10587
10588 // If anything fails here, make sure to clear our initial ClientSource.
10589 auto cleanupInitialClient =
10590 MakeScopeExit([&] { mInitialClientSource.reset(); });
10591
10592 nsCOMPtr<nsPIDOMWindowOuter> win = GetWindow();
10593 NS_ENSURE_TRUE(win, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(win)), 0))) { NS_DebugBreak(NS_DEBUG_WARNING
, "NS_ENSURE_TRUE(" "win" ") failed", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 10593); return NS_ERROR_FAILURE; } } while (false)
;
10594
10595 MaybeCreateInitialClientSource();
10596
10597 // Let the client channel helper know if we are using DocumentChannel,
10598 // since redirects get handled in the parent process in that case.
10599 RefPtr<net::DocumentChannel> docChannel = do_QueryObject(aChannel);
10600 if (docChannel && XRE_IsContentProcess()) {
10601 // Tell the content process nsDocumentOpenInfo to not try to do
10602 // any sort of targeting.
10603 aOpenFlags |= nsIURILoader::DONT_RETARGET;
10604 }
10605
10606 // Since we are loading a document we need to make sure the proper reserved
10607 // and initial client data is stored on the nsILoadInfo. The
10608 // ClientChannelHelper does this and ensures that it is propagated properly
10609 // on redirects. We pass no reserved client here so that the helper will
10610 // create the reserved ClientSource if necessary.
10611 Maybe<ClientInfo> noReservedClient;
10612 if (docChannel) {
10613 // When using DocumentChannel, all redirect handling is done in the parent,
10614 // so we just need the child variant to watch for the internal redirect
10615 // to the final channel.
10616 rv = AddClientChannelHelperInChild(aChannel,
10617 GetMainThreadSerialEventTarget());
10618 docChannel->SetInitialClientInfo(GetInitialClientInfo());
10619 } else {
10620 rv = AddClientChannelHelper(aChannel, std::move(noReservedClient),
10621 GetInitialClientInfo(),
10622 GetMainThreadSerialEventTarget());
10623 }
10624 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/docshell/base/nsDocShell.cpp"
, 10624); return rv; } } while (false)
;
10625
10626 rv = aURILoader->OpenURI(aChannel, aOpenFlags, this);
10627 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/docshell/base/nsDocShell.cpp"
, 10627); return rv; } } while (false)
;
10628
10629 // We're about to load a new page and it may take time before necko
10630 // gives back any data, so main thread might have a chance to process a
10631 // collector slice
10632 nsJSContext::MaybeRunNextCollectorSlice(this, JS::GCReason::DOCSHELL);
10633
10634 // Success. Keep the initial ClientSource if it exists.
10635 cleanupInitialClient.release();
10636
10637 return NS_OK;
10638}
10639
10640nsresult nsDocShell::OpenRedirectedChannel(nsDocShellLoadState* aLoadState) {
10641 nsCOMPtr<nsIChannel> channel = aLoadState->GetPendingRedirectedChannel();
10642 MOZ_ASSERT(channel)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(channel)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(channel))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("channel", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 10642); AnnotateMozCrashReason("MOZ_ASSERT" "(" "channel" ")"
); do { *((volatile int*)__null) = 10642; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
10643
10644 // If anything fails here, make sure to clear our initial ClientSource.
10645 auto cleanupInitialClient =
10646 MakeScopeExit([&] { mInitialClientSource.reset(); });
10647
10648 nsCOMPtr<nsPIDOMWindowOuter> win = GetWindow();
10649 NS_ENSURE_TRUE(win, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(win)), 0))) { NS_DebugBreak(NS_DEBUG_WARNING
, "NS_ENSURE_TRUE(" "win" ") failed", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 10649); return NS_ERROR_FAILURE; } } while (false)
;
10650
10651 MaybeCreateInitialClientSource();
10652
10653 nsCOMPtr<nsILoadInfo> loadInfo = channel->LoadInfo();
10654
10655 LoadInfo* li = static_cast<LoadInfo*>(loadInfo.get());
10656 if (loadInfo->GetExternalContentPolicyType() ==
10657 ExtContentPolicy::TYPE_DOCUMENT) {
10658 li->UpdateBrowsingContextID(mBrowsingContext->Id());
10659 } else if (loadInfo->GetExternalContentPolicyType() ==
10660 ExtContentPolicy::TYPE_SUBDOCUMENT) {
10661 li->UpdateFrameBrowsingContextID(mBrowsingContext->Id());
10662 }
10663
10664 // If we did a process switch, then we should have an existing allocated
10665 // ClientInfo, so we just need to allocate a corresponding ClientSource.
10666 CreateReservedSourceIfNeeded(channel, GetMainThreadSerialEventTarget());
10667
10668 RefPtr<nsDocumentOpenInfo> loader =
10669 new nsDocumentOpenInfo(this, nsIURILoader::DONT_RETARGET, nullptr);
10670 channel->SetLoadGroup(mLoadGroup);
10671
10672 MOZ_ALWAYS_SUCCEEDS(loader->Prepare())do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(loader->Prepare())), 1)))), 1))) { } else { do { static_assert
( mozilla::detail::AssertionConditionType<decltype(false)>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(false))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("false" " (" "NS_SUCCEEDED(loader->Prepare())" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 10672); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "false"
") (" "NS_SUCCEEDED(loader->Prepare())" ")"); do { *((volatile
int*)__null) = 10672; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false); } } while (false)
;
10673
10674 nsresult rv = NS_OK;
10675 if (XRE_IsParentProcess()) {
10676 // If we're in the parent, the we don't have an nsIChildChannel, just
10677 // the original channel, which is already open in this process.
10678
10679 // DocumentLoadListener expects to get an nsIParentChannel, so
10680 // we create a wrapper around the channel and nsIStreamListener
10681 // that forwards functionality as needed, and then we register
10682 // it under the provided identifier.
10683 RefPtr<ParentChannelWrapper> wrapper =
10684 new ParentChannelWrapper(channel, loader);
10685 wrapper->Register(aLoadState->GetPendingRedirectChannelRegistrarId());
10686
10687 mLoadGroup->AddRequest(channel, nullptr);
10688 } else if (nsCOMPtr<nsIChildChannel> childChannel =
10689 do_QueryInterface(channel)) {
10690 // Our channel was redirected from another process, so doesn't need to
10691 // be opened again. However, it does need its listener hooked up
10692 // correctly.
10693 rv = childChannel->CompleteRedirectSetup(loader);
10694 } else {
10695 // It's possible for the redirected channel to not implement
10696 // nsIChildChannel and be entirely local (like srcdoc). In that case we
10697 // can just open the local instance and it will work.
10698 rv = channel->AsyncOpen(loader);
10699 }
10700 if (rv == NS_ERROR_NO_CONTENT) {
10701 return NS_OK;
10702 }
10703 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/docshell/base/nsDocShell.cpp"
, 10703); return rv; } } while (false)
;
10704
10705 // Success. Keep the initial ClientSource if it exists.
10706 cleanupInitialClient.release();
10707 return NS_OK;
10708}
10709
10710// https://html.spec.whatwg.org/#scrolling-to-a-fragment
10711nsresult nsDocShell::ScrollToAnchor(bool aCurHasRef, bool aNewHasRef,
10712 nsACString& aNewHash, uint32_t aLoadType) {
10713 if (!mCurrentURI) {
10714 return NS_OK;
10715 }
10716
10717 RefPtr<PresShell> presShell = GetPresShell();
10718 if (!presShell) {
10719 // If we failed to get the shell, or if there is no shell,
10720 // nothing left to do here.
10721 return NS_OK;
10722 }
10723
10724 ScrollContainerFrame* rootScroll = presShell->GetRootScrollContainerFrame();
10725 if (rootScroll) {
10726 rootScroll->ClearDidHistoryRestore();
10727 }
10728
10729 // If it's a load from history, we don't have any anchor jumping to do.
10730 // Scrollbar position will be restored by the caller based on positions stored
10731 // in session history.
10732 bool scroll = aLoadType != LOAD_HISTORY && aLoadType != LOAD_RELOAD_NORMAL;
10733 // If the load contains text directives, try to apply them. This may fail if
10734 // the load is a same-document load that was initiated before the document was
10735 // fully loaded and the target is not yet included in the DOM tree.
10736 // For this case, the `uninvokedTextDirectives` are not cleared, so that
10737 // `Document::ScrollToRef()` can re-apply the text directive.
10738 // `Document::ScrollToRef()` is (presumably) the second "async" call mentioned
10739 // in sec. 7.4.2.3.3 in the HTML spec, "Fragment navigations":
10740 // https://html.spec.whatwg.org/#scroll-to-fragid:~:text=This%20algorithm%20will%20be%20called%20twice
10741
10742 const RefPtr fragmentDirective = GetDocument()->FragmentDirective();
10743 const nsTArray<RefPtr<nsRange>> textDirectiveRanges =
10744 fragmentDirective->FindTextFragmentsInDocument();
10745 fragmentDirective->HighlightTextDirectives(textDirectiveRanges);
10746 const bool scrollToTextDirective =
10747 !textDirectiveRanges.IsEmpty() &&
10748 fragmentDirective->IsTextDirectiveAllowedToBeScrolledTo();
10749 const RefPtr<nsRange> textDirectiveToScroll =
10750 scrollToTextDirective ? textDirectiveRanges[0] : nullptr;
10751
10752 // If we have no new anchor, we do not want to scroll, unless there is a
10753 // current anchor and we are doing a history load. So return if we have no
10754 // new anchor, and there is no current anchor or the load is not a history
10755 // load.
10756 if ((!aCurHasRef || aLoadType != LOAD_HISTORY) && !aNewHasRef &&
10757 !scrollToTextDirective) {
10758 return NS_OK;
10759 }
10760
10761 // Both the new and current URIs refer to the same page. We can now
10762 // browse to the hash stored in the new URI.
10763
10764 if (aNewHash.IsEmpty() && !scrollToTextDirective) {
10765 // 2. If fragment is the empty string, then return the special value top of
10766 // the document.
10767 //
10768 // Tell the shell it's at an anchor without scrolling.
10769 presShell->GoToAnchor(u""_ns, nullptr, false);
10770
10771 if (scroll) {
10772 // Scroll to the top of the page. Ignore the return value; failure to
10773 // scroll here (e.g. if there is no root scrollframe) is not grounds for
10774 // canceling the load!
10775 SetCurScrollPosEx(0, 0);
10776 }
10777
10778 return NS_OK;
10779 }
10780
10781 // 3. Let potentialIndicatedElement be the result of finding a potential
10782 // indicated element given document and fragment.
10783 NS_ConvertUTF8toUTF16 uStr(aNewHash);
10784
10785 MOZ_ASSERT(!uStr.IsEmpty() || scrollToTextDirective)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!uStr.IsEmpty() || scrollToTextDirective)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(!uStr.IsEmpty() || scrollToTextDirective))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("!uStr.IsEmpty() || scrollToTextDirective"
, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 10785); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!uStr.IsEmpty() || scrollToTextDirective"
")"); do { *((volatile int*)__null) = 10785; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10786
10787 auto rv = presShell->GoToAnchor(uStr, textDirectiveToScroll, scroll,
10788 ScrollFlags::ScrollSmoothAuto);
10789
10790 // 4. If potentialIndicatedElement is not null, then return
10791 // potentialIndicatedElement.
10792 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
10793 return NS_OK;
10794 }
10795
10796 // 5. Let fragmentBytes be the result of percent-decoding fragment.
10797 nsAutoCString fragmentBytes;
10798 const bool unescaped = NS_UnescapeURL(aNewHash.Data(), aNewHash.Length(),
10799 /* aFlags = */ 0, fragmentBytes);
10800
10801 if (!unescaped) {
10802 // Another attempt is only necessary if characters were unescaped.
10803 return NS_OK;
10804 }
10805
10806 if (fragmentBytes.IsEmpty()) {
10807 // When aNewHash contains "%00", the unescaped string may be empty, and
10808 // GoToAnchor asserts if we ask it to scroll to an empty ref.
10809 presShell->GoToAnchor(u""_ns, nullptr, false);
10810 return NS_OK;
10811 }
10812
10813 // 6. Let decodedFragment be the result of running UTF-8 decode without BOM on
10814 // fragmentBytes.
10815 nsAutoString decodedFragment;
10816 rv = UTF_8_ENCODING->DecodeWithoutBOMHandling(fragmentBytes, decodedFragment);
10817 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/docshell/base/nsDocShell.cpp"
, 10817); return rv; } } while (false)
;
10818
10819 // 7. Set potentialIndicatedElement to the result of finding a potential
10820 // indicated element given document and decodedFragment.
10821 //
10822 // Ignore the return value of GoToAnchor, since it will return an error if
10823 // there is no such anchor in the document, which is actually a success
10824 // condition for us (we want to update the session history with the new URI no
10825 // matter whether we actually scrolled somewhere).
10826 presShell->GoToAnchor(decodedFragment, nullptr, scroll,
10827 ScrollFlags::ScrollSmoothAuto);
10828
10829 return NS_OK;
10830}
10831
10832bool nsDocShell::OnNewURI(nsIURI* aURI, nsIChannel* aChannel,
10833 nsIPrincipal* aTriggeringPrincipal,
10834 nsIPrincipal* aPrincipalToInherit,
10835 nsIPrincipal* aPartitionedPrincipalToInherit,
10836 nsIContentSecurityPolicy* aCsp,
10837 bool aAddToGlobalHistory, bool aCloneSHChildren) {
10838 MOZ_ASSERT(aURI, "uri is null")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aURI)>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(aURI))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("aURI" " (" "uri is null" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 10838); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aURI" ") ("
"uri is null" ")"); do { *((volatile int*)__null) = 10838; __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
;
10839 MOZ_ASSERT(!aChannel || !aTriggeringPrincipal, "Shouldn't have both set")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aChannel || !aTriggeringPrincipal)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!aChannel || !aTriggeringPrincipal
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"!aChannel || !aTriggeringPrincipal" " (" "Shouldn't have both set"
")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 10839); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aChannel || !aTriggeringPrincipal"
") (" "Shouldn't have both set" ")"); do { *((volatile int*)
__null) = 10839; __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
10840
10841 MOZ_ASSERT(!aPrincipalToInherit ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aPrincipalToInherit || (aPrincipalToInherit &&
aTriggeringPrincipal))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!aPrincipalToInherit || (aPrincipalToInherit
&& aTriggeringPrincipal)))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("!aPrincipalToInherit || (aPrincipalToInherit && aTriggeringPrincipal)"
, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 10842); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aPrincipalToInherit || (aPrincipalToInherit && aTriggeringPrincipal)"
")"); do { *((volatile int*)__null) = 10842; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
10842 (aPrincipalToInherit && aTriggeringPrincipal))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aPrincipalToInherit || (aPrincipalToInherit &&
aTriggeringPrincipal))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!aPrincipalToInherit || (aPrincipalToInherit
&& aTriggeringPrincipal)))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("!aPrincipalToInherit || (aPrincipalToInherit && aTriggeringPrincipal)"
, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 10842); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aPrincipalToInherit || (aPrincipalToInherit && aTriggeringPrincipal)"
")"); do { *((volatile int*)__null) = 10842; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10843
10844#if defined(DEBUG1)
10845 if (MOZ_LOG_TEST(gDocShellLog, LogLevel::Debug)(__builtin_expect(!!(mozilla::detail::log_test(gDocShellLog, LogLevel
::Debug)), 0))
) {
10846 nsAutoCString chanName;
10847 if (aChannel) {
10848 aChannel->GetName(chanName);
10849 } else {
10850 chanName.AssignLiteral("<no channel>");
10851 }
10852
10853 MOZ_LOG(gDocShellLog, LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = gDocShellLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "nsDocShell[%p]::OnNewURI(\"%s\", [%s], 0x%x)\n"
, this, aURI->GetSpecOrDefault().get(), chanName.get(), mLoadType
); } } while (0)
10854 ("nsDocShell[%p]::OnNewURI(\"%s\", [%s], 0x%x)\n", this,do { const ::mozilla::LogModule* moz_real_module = gDocShellLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "nsDocShell[%p]::OnNewURI(\"%s\", [%s], 0x%x)\n"
, this, aURI->GetSpecOrDefault().get(), chanName.get(), mLoadType
); } } while (0)
10855 aURI->GetSpecOrDefault().get(), chanName.get(), mLoadType))do { const ::mozilla::LogModule* moz_real_module = gDocShellLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "nsDocShell[%p]::OnNewURI(\"%s\", [%s], 0x%x)\n"
, this, aURI->GetSpecOrDefault().get(), chanName.get(), mLoadType
); } } while (0)
;
10856 }
10857#endif
10858
10859 bool equalUri = false;
10860
10861 // Get the post data and the HTTP response code from the channel.
10862 uint32_t responseStatus = 0;
10863 nsCOMPtr<nsIInputStream> inputStream;
10864 if (aChannel) {
10865 nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(aChannel));
10866
10867 // Check if the HTTPChannel is hiding under a multiPartChannel
10868 if (!httpChannel) {
10869 GetHttpChannel(aChannel, getter_AddRefs(httpChannel));
10870 }
10871
10872 if (httpChannel) {
10873 nsCOMPtr<nsIUploadChannel> uploadChannel(do_QueryInterface(httpChannel));
10874 if (uploadChannel) {
10875 uploadChannel->GetUploadStream(getter_AddRefs(inputStream));
10876 }
10877
10878 // If the response status indicates an error, unlink this session
10879 // history entry from any entries sharing its document.
10880 nsresult rv = httpChannel->GetResponseStatus(&responseStatus);
10881 if (mLSHE && NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && responseStatus >= 400) {
10882 mLSHE->AbandonBFCacheEntry();
10883 // FIXME Do the same for mLoadingEntry
10884 }
10885 }
10886 }
10887
10888 // Determine if this type of load should update history.
10889 bool updateGHistory = ShouldUpdateGlobalHistory(mLoadType);
10890
10891 // We don't update session history on reload unless we're loading
10892 // an iframe in shift-reload case.
10893 bool updateSHistory = mBrowsingContext->ShouldUpdateSessionHistory(mLoadType);
10894
10895 // Create SH Entry (mLSHE) only if there is a SessionHistory object in the
10896 // root browsing context.
10897 // FIXME If session history in the parent is enabled then we only do this if
10898 // the session history object is in process, otherwise we can't really
10899 // use the mLSHE anyway. Once session history is only stored in the
10900 // parent then this code will probably be removed anyway.
10901 RefPtr<ChildSHistory> rootSH = GetRootSessionHistory();
10902 if (!rootSH) {
10903 updateSHistory = false;
10904 updateGHistory = false; // XXX Why global history too?
10905 }
10906
10907 // Check if the url to be loaded is the same as the one already loaded.
10908 if (mCurrentURI) {
10909 aURI->Equals(mCurrentURI, &equalUri);
10910 }
10911
10912#ifdef DEBUG1
10913 bool shAvailable = (rootSH != nullptr);
10914
10915 // XXX This log message is almost useless because |updateSHistory|
10916 // and |updateGHistory| are not correct at this point.
10917
10918 MOZ_LOG(gDocShellLog, LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = gDocShellLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, " shAvailable=%i updateSHistory=%i updateGHistory=%i"
" equalURI=%i\n", shAvailable, updateSHistory, updateGHistory
, equalUri); } } while (0)
10919 (" shAvailable=%i updateSHistory=%i updateGHistory=%i"do { const ::mozilla::LogModule* moz_real_module = gDocShellLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, " shAvailable=%i updateSHistory=%i updateGHistory=%i"
" equalURI=%i\n", shAvailable, updateSHistory, updateGHistory
, equalUri); } } while (0)
10920 " equalURI=%i\n",do { const ::mozilla::LogModule* moz_real_module = gDocShellLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, " shAvailable=%i updateSHistory=%i updateGHistory=%i"
" equalURI=%i\n", shAvailable, updateSHistory, updateGHistory
, equalUri); } } while (0)
10921 shAvailable, updateSHistory, updateGHistory, equalUri))do { const ::mozilla::LogModule* moz_real_module = gDocShellLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, " shAvailable=%i updateSHistory=%i updateGHistory=%i"
" equalURI=%i\n", shAvailable, updateSHistory, updateGHistory
, equalUri); } } while (0)
;
10922#endif
10923
10924 /* If the url to be loaded is the same as the one already there,
10925 * and the original loadType is LOAD_NORMAL, LOAD_LINK, or
10926 * LOAD_STOP_CONTENT, set loadType to LOAD_NORMAL_REPLACE so that
10927 * AddToSessionHistory() won't mess with the current SHEntry and
10928 * if this page has any frame children, it also will be handled
10929 * properly. see bug 83684
10930 *
10931 * NB: If mOSHE is null but we have a current URI, then it probably
10932 * means that we must be at the transient about:blank content viewer;
10933 * we should let the normal load continue, since there's nothing to
10934 * replace. Sometimes this happens after a session restore (eg process
10935 * switch) and mCurrentURI is not about:blank; we assume we can let the load
10936 * continue (Bug 1301399).
10937 *
10938 * XXX Hopefully changing the loadType at this time will not hurt
10939 * anywhere. The other way to take care of sequentially repeating
10940 * frameset pages is to add new methods to nsIDocShellTreeItem.
10941 * Hopefully I don't have to do that.
10942 */
10943 if (equalUri &&
10944 (mozilla::SessionHistoryInParent() ? !!mActiveEntry : !!mOSHE) &&
10945 (mLoadType == LOAD_NORMAL || mLoadType == LOAD_LINK ||
10946 mLoadType == LOAD_STOP_CONTENT) &&
10947 !inputStream) {
10948 mLoadType = LOAD_NORMAL_REPLACE;
10949 }
10950
10951 // If this is a refresh to the currently loaded url, we don't
10952 // have to update session or global history.
10953 if (mLoadType == LOAD_REFRESH && !inputStream && equalUri) {
10954 SetHistoryEntryAndUpdateBC(Some<nsISHEntry*>(mOSHE), Nothing());
10955 }
10956
10957 /* If the user pressed shift-reload, cache will create a new cache key
10958 * for the page. Save the new cacheKey in Session History.
10959 * see bug 90098
10960 */
10961 if (aChannel && IsForceReloadType(mLoadType)) {
10962 MOZ_ASSERT(!updateSHistory || IsSubframe(),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!updateSHistory || IsSubframe())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!updateSHistory || IsSubframe
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!updateSHistory || IsSubframe()" " (" "We shouldn't be updating session history for forced"
" reloads unless we're in a newly created iframe!" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 10964); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!updateSHistory || IsSubframe()"
") (" "We shouldn't be updating session history for forced" " reloads unless we're in a newly created iframe!"
")"); do { *((volatile int*)__null) = 10964; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
10963 "We shouldn't be updating session history for forced"do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!updateSHistory || IsSubframe())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!updateSHistory || IsSubframe
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!updateSHistory || IsSubframe()" " (" "We shouldn't be updating session history for forced"
" reloads unless we're in a newly created iframe!" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 10964); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!updateSHistory || IsSubframe()"
") (" "We shouldn't be updating session history for forced" " reloads unless we're in a newly created iframe!"
")"); do { *((volatile int*)__null) = 10964; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
10964 " reloads unless we're in a newly created iframe!")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!updateSHistory || IsSubframe())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!updateSHistory || IsSubframe
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!updateSHistory || IsSubframe()" " (" "We shouldn't be updating session history for forced"
" reloads unless we're in a newly created iframe!" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 10964); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!updateSHistory || IsSubframe()"
") (" "We shouldn't be updating session history for forced" " reloads unless we're in a newly created iframe!"
")"); do { *((volatile int*)__null) = 10964; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10965
10966 nsCOMPtr<nsICacheInfoChannel> cacheChannel(do_QueryInterface(aChannel));
10967 uint32_t cacheKey = 0;
10968 // Get the Cache Key and store it in SH.
10969 if (cacheChannel) {
10970 cacheChannel->GetCacheKey(&cacheKey);
10971 }
10972 // If we already have a loading history entry, store the new cache key
10973 // in it. Otherwise, since we're doing a reload and won't be updating
10974 // our history entry, store the cache key in our current history entry.
10975 SetCacheKeyOnHistoryEntry(mLSHE ? mLSHE : mOSHE, cacheKey);
10976
10977 if (!mozilla::SessionHistoryInParent()) {
10978 // Since we're force-reloading, clear all the sub frame history.
10979 ClearFrameHistory(mLSHE);
10980 ClearFrameHistory(mOSHE);
10981 }
10982 }
10983
10984 if (!mozilla::SessionHistoryInParent()) {
10985 // Clear subframe history on refresh.
10986 // XXX: history.go(0) won't go this path as mLoadType is LOAD_HISTORY in
10987 // this case. One should re-validate after bug 1331865 fixed.
10988 if (mLoadType == LOAD_REFRESH) {
10989 ClearFrameHistory(mLSHE);
10990 ClearFrameHistory(mOSHE);
10991 }
10992
10993 if (updateSHistory) {
10994 // Update session history if necessary...
10995 if (!mLSHE && (mItemType == typeContent) && mURIResultedInDocument) {
10996 /* This is a fresh page getting loaded for the first time
10997 *.Create a Entry for it and add it to SH, if this is the
10998 * rootDocShell
10999 */
11000 (void)AddToSessionHistory(aURI, aChannel, aTriggeringPrincipal,
11001 aPrincipalToInherit,
11002 aPartitionedPrincipalToInherit, aCsp,
11003 aCloneSHChildren, getter_AddRefs(mLSHE));
11004 }
11005 } else if (GetSessionHistory() && mLSHE && mURIResultedInDocument) {
11006 // Even if we don't add anything to SHistory, ensure the current index
11007 // points to the same SHEntry as our mLSHE.
11008
11009 GetSessionHistory()->LegacySHistory()->EnsureCorrectEntryAtCurrIndex(
11010 mLSHE);
11011 }
11012 }
11013
11014 // If this is a POST request, we do not want to include this in global
11015 // history.
11016 if (ShouldAddURIVisit(aChannel) && updateGHistory && aAddToGlobalHistory &&
11017 !net::ChannelIsPost(aChannel)) {
11018 nsCOMPtr<nsIURI> previousURI;
11019 uint32_t previousFlags = 0;
11020
11021 if (mLoadType & LOAD_CMD_RELOAD) {
11022 // On a reload request, we don't set redirecting flags.
11023 previousURI = aURI;
11024 } else {
11025 ExtractLastVisit(aChannel, getter_AddRefs(previousURI), &previousFlags);
11026 }
11027
11028 AddURIVisit(aURI, previousURI, previousFlags, responseStatus);
11029 }
11030
11031 // If this was a history load or a refresh, or it was a history load but
11032 // later changed to LOAD_NORMAL_REPLACE due to redirection, update the index
11033 // in session history.
11034 if (!mozilla::SessionHistoryInParent() && rootSH &&
11035 ((mLoadType & (LOAD_CMD_HISTORY | LOAD_CMD_RELOAD)) ||
11036 mLoadType == LOAD_NORMAL_REPLACE || mLoadType == LOAD_REFRESH_REPLACE)) {
11037 mPreviousEntryIndex = rootSH->Index();
11038 if (!mozilla::SessionHistoryInParent()) {
11039 rootSH->LegacySHistory()->UpdateIndex();
11040 }
11041 mLoadedEntryIndex = rootSH->Index();
11042 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, "Previous index: %d, Loaded index: %d", mPreviousEntryIndex
, mLoadedEntryIndex); } } while (0)
11043 ("Previous index: %d, Loaded index: %d", mPreviousEntryIndex,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, "Previous index: %d, Loaded index: %d", mPreviousEntryIndex
, mLoadedEntryIndex); } } while (0)
11044 mLoadedEntryIndex))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, "Previous index: %d, Loaded index: %d", mPreviousEntryIndex
, mLoadedEntryIndex); } } while (0)
;
11045 }
11046
11047 // aCloneSHChildren exactly means "we are not loading a new document".
11048 uint32_t locationFlags =
11049 aCloneSHChildren ? uint32_t(LOCATION_CHANGE_SAME_DOCUMENT) : 0;
11050
11051 bool onLocationChangeNeeded =
11052 SetCurrentURI(aURI, aChannel, false,
11053 /* aIsInitialAboutBlank */ false, locationFlags);
11054 // Make sure to store the referrer from the channel, if any
11055 nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(aChannel));
11056 if (httpChannel) {
11057 mReferrerInfo = httpChannel->GetReferrerInfo();
11058 }
11059 return onLocationChangeNeeded;
11060}
11061
11062Maybe<Wireframe> nsDocShell::GetWireframe() {
11063 const bool collectWireFrame =
11064 mozilla::SessionHistoryInParent() &&
11065 StaticPrefs::browser_history_collectWireframes() &&
11066 mBrowsingContext->IsTopContent() && mActiveEntry;
11067
11068 if (!collectWireFrame) {
11069 return Nothing();
11070 }
11071
11072 RefPtr<Document> doc = mDocumentViewer->GetDocument();
11073 Nullable<Wireframe> wireframe;
11074 doc->GetWireframeWithoutFlushing(false, wireframe);
11075 if (wireframe.IsNull()) {
11076 return Nothing();
11077 }
11078 return Some(wireframe.Value());
11079}
11080
11081bool nsDocShell::CollectWireframe() {
11082 Maybe<Wireframe> wireframe = GetWireframe();
11083 if (wireframe.isNothing()) {
11084 return false;
11085 }
11086
11087 if (XRE_IsParentProcess()) {
11088 SessionHistoryEntry* entry =
11089 mBrowsingContext->Canonical()->GetActiveSessionHistoryEntry();
11090 if (entry) {
11091 entry->SetWireframe(wireframe);
11092 }
11093 } else {
11094 mozilla::Unused
11095 << ContentChild::GetSingleton()->SendSessionHistoryEntryWireframe(
11096 mBrowsingContext, wireframe.ref());
11097 }
11098
11099 return true;
11100}
11101
11102//*****************************************************************************
11103// nsDocShell: Session History
11104//*****************************************************************************
11105
11106NS_IMETHODIMPnsresult
11107nsDocShell::AddState(JS::Handle<JS::Value> aData, const nsAString& aTitle,
11108 const nsAString& aURL, bool aReplace, JSContext* aCx) {
11109 MOZ_LOG(gSHLog, LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = gSHLog; if
((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "nsDocShell[%p]: AddState(..., %s, %s, %d)"
, this, NS_ConvertUTF16toUTF8(aTitle).get(), NS_ConvertUTF16toUTF8
(aURL).get(), aReplace); } } while (0)
11110 ("nsDocShell[%p]: AddState(..., %s, %s, %d)", this,do { const ::mozilla::LogModule* moz_real_module = gSHLog; if
((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "nsDocShell[%p]: AddState(..., %s, %s, %d)"
, this, NS_ConvertUTF16toUTF8(aTitle).get(), NS_ConvertUTF16toUTF8
(aURL).get(), aReplace); } } while (0)
11111 NS_ConvertUTF16toUTF8(aTitle).get(),do { const ::mozilla::LogModule* moz_real_module = gSHLog; if
((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "nsDocShell[%p]: AddState(..., %s, %s, %d)"
, this, NS_ConvertUTF16toUTF8(aTitle).get(), NS_ConvertUTF16toUTF8
(aURL).get(), aReplace); } } while (0)
11112 NS_ConvertUTF16toUTF8(aURL).get(), aReplace))do { const ::mozilla::LogModule* moz_real_module = gSHLog; if
((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "nsDocShell[%p]: AddState(..., %s, %s, %d)"
, this, NS_ConvertUTF16toUTF8(aTitle).get(), NS_ConvertUTF16toUTF8
(aURL).get(), aReplace); } } while (0)
;
11113 // Implements History.pushState and History.replaceState
11114
11115 // Here's what we do, roughly in the order specified by HTML5. The specific
11116 // steps we are executing are at
11117 // <https://html.spec.whatwg.org/multipage/history.html#dom-history-pushstate>
11118 // and
11119 // <https://html.spec.whatwg.org/multipage/history.html#url-and-history-update-steps>.
11120 // This function basically implements #dom-history-pushstate and
11121 // UpdateURLAndHistory implements #url-and-history-update-steps.
11122 //
11123 // A. Serialize aData using structured clone. This is #dom-history-pushstate
11124 // step 5.
11125 // B. If the third argument is present, #dom-history-pushstate step 7.
11126 // 7.1. Resolve the url, relative to our document.
11127 // 7.2. If (a) fails, raise a SECURITY_ERR
11128 // 7.4. Compare the resulting absolute URL to the document's address. If
11129 // any part of the URLs difer other than the <path>, <query>, and
11130 // <fragment> components, raise a SECURITY_ERR and abort.
11131 // C. If !aReplace, #url-and-history-update-steps steps 2.1-2.3:
11132 // Remove from the session history all entries after the current entry,
11133 // as we would after a regular navigation, and save the current
11134 // entry's scroll position (bug 590573).
11135 // D. #url-and-history-update-steps step 2.4 or step 3. As apropriate,
11136 // either add a state object entry to the session history after the
11137 // current entry with the following properties, or modify the current
11138 // session history entry to set
11139 // a. cloned data as the state object,
11140 // b. if the third argument was present, the absolute URL found in
11141 // step 2
11142 // Also clear the new history entry's POST data (see bug 580069).
11143 // E. If aReplace is false (i.e. we're doing a pushState instead of a
11144 // replaceState), notify bfcache that we've navigated to a new page.
11145 // F. If the third argument is present, set the document's current address
11146 // to the absolute URL found in step B. This is
11147 // #url-and-history-update-steps step 4.
11148 //
11149 // It's important that this function not run arbitrary scripts after step A
11150 // and before completing step E. For example, if a script called
11151 // history.back() before we completed step E, bfcache might destroy an
11152 // active content viewer. Since EvictOutOfRangeDocumentViewers at the end of
11153 // step E might run script, we can't just put a script blocker around the
11154 // critical section.
11155 //
11156 // Note that we completely ignore the aTitle parameter.
11157
11158 nsresult rv;
11159
11160 // Don't clobber the load type of an existing network load.
11161 AutoRestore<uint32_t> loadTypeResetter(mLoadType);
11162
11163 // pushState effectively becomes replaceState when we've started a network
11164 // load but haven't adopted its document yet. This mirrors what we do with
11165 // changes to the hash at this stage of the game.
11166 if (JustStartedNetworkLoad()) {
11167 aReplace = true;
11168 }
11169
11170 RefPtr<Document> document = GetDocument();
11171 NS_ENSURE_TRUE(document, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(document)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "document" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 11171); return NS_ERROR_FAILURE; } } while (false)
;
11172
11173 // Step A: Serialize aData using structured clone.
11174 // https://html.spec.whatwg.org/multipage/history.html#dom-history-pushstate
11175 // step 5.
11176 nsCOMPtr<nsIStructuredCloneContainer> scContainer;
11177
11178 // scContainer->Init might cause arbitrary JS to run, and this code might
11179 // navigate the page we're on, potentially to a different origin! (bug
11180 // 634834) To protect against this, we abort if our principal changes due
11181 // to the InitFromJSVal() call.
11182 {
11183 RefPtr<Document> origDocument = GetDocument();
11184 if (!origDocument) {
11185 return NS_ERROR_DOM_SECURITY_ERR;
11186 }
11187 nsCOMPtr<nsIPrincipal> origPrincipal = origDocument->NodePrincipal();
11188
11189 scContainer = new nsStructuredCloneContainer();
11190 rv = scContainer->InitFromJSVal(aData, aCx);
11191 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/docshell/base/nsDocShell.cpp"
, 11191); return rv; } } while (false)
;
11192
11193 RefPtr<Document> newDocument = GetDocument();
11194 if (!newDocument) {
11195 return NS_ERROR_DOM_SECURITY_ERR;
11196 }
11197 nsCOMPtr<nsIPrincipal> newPrincipal = newDocument->NodePrincipal();
11198
11199 bool principalsEqual = false;
11200 origPrincipal->Equals(newPrincipal, &principalsEqual);
11201 NS_ENSURE_TRUE(principalsEqual, NS_ERROR_DOM_SECURITY_ERR)do { if ((__builtin_expect(!!(!(principalsEqual)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "principalsEqual" ") failed"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 11201); return NS_ERROR_DOM_SECURITY_ERR; } } while (false)
;
11202 }
11203
11204 // Check that the state object isn't too long.
11205 int32_t maxStateObjSize = StaticPrefs::browser_history_maxStateObjectSize();
11206 if (maxStateObjSize < 0) {
11207 maxStateObjSize = 0;
11208 }
11209
11210 uint64_t scSize;
11211 rv = scContainer->GetSerializedNBytes(&scSize);
11212 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/docshell/base/nsDocShell.cpp"
, 11212); return rv; } } while (false)
;
11213
11214 NS_ENSURE_TRUE(scSize <= (uint32_t)maxStateObjSize, NS_ERROR_ILLEGAL_VALUE)do { if ((__builtin_expect(!!(!(scSize <= (uint32_t)maxStateObjSize
)), 0))) { NS_DebugBreak(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "scSize <= (uint32_t)maxStateObjSize"
") failed", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 11214); return NS_ERROR_ILLEGAL_VALUE; } } while (false)
;
11215
11216 // Step B: Resolve aURL.
11217 // https://html.spec.whatwg.org/multipage/history.html#dom-history-pushstate
11218 // step 7.
11219 bool equalURIs = true;
11220 nsCOMPtr<nsIURI> currentURI;
11221 if (mCurrentURI) {
11222 currentURI = nsIOService::CreateExposableURI(mCurrentURI);
11223 } else {
11224 currentURI = mCurrentURI;
11225 }
11226 nsCOMPtr<nsIURI> newURI;
11227 if (aURL.Length() == 0) {
11228 newURI = currentURI;
11229 } else {
11230 // 7.1: Resolve aURL relative to mURI
11231
11232 nsIURI* docBaseURI = document->GetDocBaseURI();
11233 if (!docBaseURI) {
11234 return NS_ERROR_FAILURE;
11235 }
11236
11237 nsAutoCString spec;
11238 docBaseURI->GetSpec(spec);
11239
11240 rv = NS_NewURI(getter_AddRefs(newURI), aURL,
11241 document->GetDocumentCharacterSet(), docBaseURI);
11242
11243 // 7.2: If 2a fails, raise a SECURITY_ERR
11244 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
11245 return NS_ERROR_DOM_SECURITY_ERR;
11246 }
11247
11248 // 7.4 and 7.5: Same-origin check.
11249 if (!nsContentUtils::URIIsLocalFile(newURI)) {
11250 // In addition to checking that the security manager says that
11251 // the new URI has the same origin as our current URI, we also
11252 // check that the two URIs have the same userpass. (The
11253 // security manager says that |http://foo.com| and
11254 // |http://me@foo.com| have the same origin.) currentURI
11255 // won't contain the password part of the userpass, so this
11256 // means that it's never valid to specify a password in a
11257 // pushState or replaceState URI.
11258
11259 nsCOMPtr<nsIScriptSecurityManager> secMan =
11260 do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID"@mozilla.org/scriptsecuritymanager;1");
11261 NS_ENSURE_TRUE(secMan, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(secMan)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "secMan" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 11261); return NS_ERROR_FAILURE; } } while (false)
;
11262
11263 // It's very important that we check that newURI is of the same
11264 // origin as currentURI, not docBaseURI, because a page can
11265 // set docBaseURI arbitrarily to any domain.
11266 nsAutoCString currentUserPass, newUserPass;
11267 NS_ENSURE_SUCCESS(currentURI->GetUserPass(currentUserPass),do { nsresult __rv = currentURI->GetUserPass(currentUserPass
); 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", "currentURI->GetUserPass(currentUserPass)"
, "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/docshell/base/nsDocShell.cpp"
, 11268); return NS_ERROR_FAILURE; } } while (false)
11268 NS_ERROR_FAILURE)do { nsresult __rv = currentURI->GetUserPass(currentUserPass
); 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", "currentURI->GetUserPass(currentUserPass)"
, "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/docshell/base/nsDocShell.cpp"
, 11268); return NS_ERROR_FAILURE; } } while (false)
;
11269 NS_ENSURE_SUCCESS(newURI->GetUserPass(newUserPass), NS_ERROR_FAILURE)do { nsresult __rv = newURI->GetUserPass(newUserPass); 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", "newURI->GetUserPass(newUserPass)"
, "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/docshell/base/nsDocShell.cpp"
, 11269); return NS_ERROR_FAILURE; } } while (false)
;
11270 bool isPrivateWin =
11271 document->NodePrincipal()->OriginAttributesRef().IsPrivateBrowsing();
11272 if (NS_FAILED(secMan->CheckSameOriginURI(currentURI, newURI, true,((bool)(__builtin_expect(!!(NS_FAILED_impl(secMan->CheckSameOriginURI
(currentURI, newURI, true, isPrivateWin))), 0)))
11273 isPrivateWin))((bool)(__builtin_expect(!!(NS_FAILED_impl(secMan->CheckSameOriginURI
(currentURI, newURI, true, isPrivateWin))), 0)))
||
11274 !currentUserPass.Equals(newUserPass)) {
11275 return NS_ERROR_DOM_SECURITY_ERR;
11276 }
11277 } else {
11278 // It's a file:// URI
11279 nsCOMPtr<nsIPrincipal> principal = document->GetPrincipal();
11280
11281 if (!principal || NS_FAILED(principal->CheckMayLoadWithReporting(((bool)(__builtin_expect(!!(NS_FAILED_impl(principal->CheckMayLoadWithReporting
( newURI, false, document->InnerWindowID()))), 0)))
11282 newURI, false, document->InnerWindowID()))((bool)(__builtin_expect(!!(NS_FAILED_impl(principal->CheckMayLoadWithReporting
( newURI, false, document->InnerWindowID()))), 0)))
) {
11283 return NS_ERROR_DOM_SECURITY_ERR;
11284 }
11285 }
11286
11287 if (currentURI) {
11288 currentURI->Equals(newURI, &equalURIs);
11289 } else {
11290 equalURIs = false;
11291 }
11292
11293 } // end of same-origin check
11294
11295 // Step 8: call "URL and history update steps"
11296 rv = UpdateURLAndHistory(document, newURI, scContainer, aTitle, aReplace,
11297 currentURI, equalURIs);
11298 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/docshell/base/nsDocShell.cpp"
, 11298); return rv; } } while (false)
;
11299
11300 return NS_OK;
11301}
11302
11303nsresult nsDocShell::UpdateURLAndHistory(Document* aDocument, nsIURI* aNewURI,
11304 nsIStructuredCloneContainer* aData,
11305 const nsAString& aTitle, bool aReplace,
11306 nsIURI* aCurrentURI, bool aEqualURIs) {
11307 // Implements
11308 // https://html.spec.whatwg.org/multipage/history.html#url-and-history-update-steps
11309
11310 // If we have a pending title change, handle it before creating a new entry.
11311 aDocument->DoNotifyPossibleTitleChange();
11312
11313 // Step 2, if aReplace is false: Create a new entry in the session
11314 // history. This will erase all SHEntries after the new entry and make this
11315 // entry the current one. This operation may modify mOSHE, which we need
11316 // later, so we keep a reference here.
11317 NS_ENSURE_TRUE(mOSHE || mActiveEntry || aReplace, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(mOSHE || mActiveEntry || aReplace
)), 0))) { NS_DebugBreak(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "mOSHE || mActiveEntry || aReplace"
") failed", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 11317); return NS_ERROR_FAILURE; } } while (false)
;
11318 nsCOMPtr<nsISHEntry> oldOSHE = mOSHE;
11319
11320 // If this push/replaceState changed the document's current URI and the new
11321 // URI differs from the old URI in more than the hash, or if the old
11322 // SHEntry's URI was modified in this way by a push/replaceState call
11323 // set URIWasModified to true for the current SHEntry (bug 669671).
11324 bool sameExceptHashes = true;
11325 aNewURI->EqualsExceptRef(aCurrentURI, &sameExceptHashes);
11326 bool uriWasModified;
11327 if (sameExceptHashes) {
11328 if (mozilla::SessionHistoryInParent()) {
11329 uriWasModified = mActiveEntry && mActiveEntry->GetURIWasModified();
11330 } else {
11331 uriWasModified = oldOSHE && oldOSHE->GetURIWasModified();
11332 }
11333 } else {
11334 uriWasModified = true;
11335 }
11336
11337 mLoadType = LOAD_PUSHSTATE;
11338
11339 nsCOMPtr<nsISHEntry> newSHEntry;
11340 if (!aReplace) {
11341 // Step 2.
11342
11343 // Step 2.2, "Remove any tasks queued by the history traversal task
11344 // source that are associated with any Document objects in the
11345 // top-level browsing context's document family." This is very hard in
11346 // SessionHistoryInParent since we can't synchronously access the
11347 // pending navigations that are already sent to the parent. We can
11348 // abort any AsyncGo navigations that are waiting to be sent. If we
11349 // send a message to the parent, it would be processed after any
11350 // navigations previously sent. So long as we consider the "history
11351 // traversal task source" to be the list in this process we match the
11352 // spec. If we move the entire list to the parent, we can handle the
11353 // aborting of loads there, but we don't have a way to synchronously
11354 // remove entries as we do here for non-SHIP.
11355 RefPtr<ChildSHistory> shistory = GetRootSessionHistory();
11356 if (shistory) {
11357 shistory->RemovePendingHistoryNavigations();
11358 }
11359
11360 nsPoint scrollPos = GetCurScrollPos();
11361
11362 bool scrollRestorationIsManual;
11363 if (mozilla::SessionHistoryInParent()) {
11364 // FIXME Need to save the current scroll position on mActiveEntry.
11365 scrollRestorationIsManual = mActiveEntry->GetScrollRestorationIsManual();
11366 } else {
11367 // Save the current scroll position (bug 590573). Step 2.3.
11368 mOSHE->SetScrollPosition(scrollPos.x, scrollPos.y);
11369
11370 scrollRestorationIsManual = mOSHE->GetScrollRestorationIsManual();
11371 }
11372
11373 nsCOMPtr<nsIContentSecurityPolicy> csp = aDocument->GetCsp();
11374
11375 if (mozilla::SessionHistoryInParent()) {
11376 MOZ_LOG(gSHLog, LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = gSHLog; if
((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "nsDocShell %p UpdateActiveEntry (not replacing)"
, this); } } while (0)
11377 ("nsDocShell %p UpdateActiveEntry (not replacing)", this))do { const ::mozilla::LogModule* moz_real_module = gSHLog; if
((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "nsDocShell %p UpdateActiveEntry (not replacing)"
, this); } } while (0)
;
11378
11379 nsString title(mActiveEntry->GetTitle());
11380 nsCOMPtr<nsIReferrerInfo> referrerInfo = mActiveEntry->GetReferrerInfo();
11381
11382 UpdateActiveEntry(false,
11383 /* aPreviousScrollPos = */ Some(scrollPos), aNewURI,
11384 /* aOriginalURI = */ nullptr,
11385 /* aReferrerInfo = */ referrerInfo,
11386 /* aTriggeringPrincipal = */ aDocument->NodePrincipal(),
11387 csp, title, scrollRestorationIsManual, aData,
11388 uriWasModified);
11389 } else {
11390 // Since we're not changing which page we have loaded, pass
11391 // true for aCloneChildren.
11392 nsresult rv = AddToSessionHistory(
11393 aNewURI, nullptr,
11394 aDocument->NodePrincipal(), // triggeringPrincipal
11395 nullptr, nullptr, csp, true, getter_AddRefs(newSHEntry));
11396 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/docshell/base/nsDocShell.cpp"
, 11396); return rv; } } while (false)
;
11397
11398 NS_ENSURE_TRUE(newSHEntry, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(newSHEntry)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "newSHEntry" ") failed",
nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 11398); return NS_ERROR_FAILURE; } } while (false)
;
11399
11400 // Session history entries created by pushState inherit scroll restoration
11401 // mode from the current entry.
11402 newSHEntry->SetScrollRestorationIsManual(scrollRestorationIsManual);
11403
11404 // Set the new SHEntry's title (bug 655273).
11405 nsString title;
11406 mOSHE->GetTitle(title);
11407 newSHEntry->SetTitle(title);
11408
11409 nsCOMPtr<nsIReferrerInfo> referrerInfo = mOSHE->GetReferrerInfo();
11410 newSHEntry->SetReferrerInfo(referrerInfo);
11411
11412 // Link the new SHEntry to the old SHEntry's BFCache entry, since the
11413 // two entries correspond to the same document.
11414 NS_ENSURE_SUCCESS(newSHEntry->AdoptBFCacheEntry(oldOSHE),do { nsresult __rv = newSHEntry->AdoptBFCacheEntry(oldOSHE
); 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", "newSHEntry->AdoptBFCacheEntry(oldOSHE)"
, "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/docshell/base/nsDocShell.cpp"
, 11415); return NS_ERROR_FAILURE; } } while (false)
11415 NS_ERROR_FAILURE)do { nsresult __rv = newSHEntry->AdoptBFCacheEntry(oldOSHE
); 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", "newSHEntry->AdoptBFCacheEntry(oldOSHE)"
, "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/docshell/base/nsDocShell.cpp"
, 11415); return NS_ERROR_FAILURE; } } while (false)
;
11416
11417 // AddToSessionHistory may not modify mOSHE. In case it doesn't,
11418 // we'll just set mOSHE here.
11419 mOSHE = newSHEntry;
11420 }
11421 } else if (mozilla::SessionHistoryInParent()) {
11422 MOZ_LOG(gSHLog, LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = gSHLog; if
((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "nsDocShell %p UpdateActiveEntry (replacing) mActiveEntry %p"
, this, mActiveEntry.get()); } } while (0)
11423 ("nsDocShell %p UpdateActiveEntry (replacing) mActiveEntry %p",do { const ::mozilla::LogModule* moz_real_module = gSHLog; if
((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "nsDocShell %p UpdateActiveEntry (replacing) mActiveEntry %p"
, this, mActiveEntry.get()); } } while (0)
11424 this, mActiveEntry.get()))do { const ::mozilla::LogModule* moz_real_module = gSHLog; if
((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "nsDocShell %p UpdateActiveEntry (replacing) mActiveEntry %p"
, this, mActiveEntry.get()); } } while (0)
;
11425 // Setting the resultPrincipalURI to nullptr is fine here: it will cause
11426 // NS_GetFinalChannelURI to use the originalURI as the URI, which is aNewURI
11427 // in our case. We could also set it to aNewURI, with the same result.
11428 // We don't use aTitle here, see bug 544535.
11429 nsString title;
11430 nsCOMPtr<nsIReferrerInfo> referrerInfo;
11431 if (mActiveEntry) {
11432 title = mActiveEntry->GetTitle();
11433 referrerInfo = mActiveEntry->GetReferrerInfo();
11434 } else {
11435 referrerInfo = nullptr;
11436 }
11437 UpdateActiveEntry(
11438 true, /* aPreviousScrollPos = */ Nothing(), aNewURI, aNewURI,
11439 /* aReferrerInfo = */ referrerInfo, aDocument->NodePrincipal(),
11440 aDocument->GetCsp(), title,
11441 mActiveEntry && mActiveEntry->GetScrollRestorationIsManual(), aData,
11442 uriWasModified);
11443 } else {
11444 // Step 3.
11445 newSHEntry = mOSHE;
11446
11447 MOZ_LOG(gSHLog, LogLevel::Debug, ("nsDocShell %p step 3", this))do { const ::mozilla::LogModule* moz_real_module = gSHLog; if
((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "nsDocShell %p step 3", this); } } while (
0)
;
11448 // Since we're not changing which page we have loaded, pass
11449 // true for aCloneChildren.
11450 if (!newSHEntry) {
11451 nsresult rv = AddToSessionHistory(
11452 aNewURI, nullptr,
11453 aDocument->NodePrincipal(), // triggeringPrincipal
11454 nullptr, nullptr, aDocument->GetCsp(), true,
11455 getter_AddRefs(newSHEntry));
11456 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/docshell/base/nsDocShell.cpp"
, 11456); return rv; } } while (false)
;
11457 mOSHE = newSHEntry;
11458 }
11459
11460 nsCOMPtr<nsIReferrerInfo> referrerInfo = mOSHE->GetReferrerInfo();
11461
11462 newSHEntry->SetURI(aNewURI);
11463 newSHEntry->SetOriginalURI(aNewURI);
11464 // We replaced the URI of the entry, clear the unstripped URI as it
11465 // shouldn't be used for reloads anymore.
11466 newSHEntry->SetUnstrippedURI(nullptr);
11467 // Setting the resultPrincipalURI to nullptr is fine here: it will cause
11468 // NS_GetFinalChannelURI to use the originalURI as the URI, which is aNewURI
11469 // in our case. We could also set it to aNewURI, with the same result.
11470 newSHEntry->SetResultPrincipalURI(nullptr);
11471 newSHEntry->SetLoadReplace(false);
11472 newSHEntry->SetReferrerInfo(referrerInfo);
11473 }
11474
11475 if (!mozilla::SessionHistoryInParent()) {
11476 // Step 2.4 and 3: Modify new/original session history entry and clear its
11477 // POST data, if there is any.
11478 newSHEntry->SetStateData(aData);
11479 newSHEntry->SetPostData(nullptr);
11480
11481 newSHEntry->SetURIWasModified(uriWasModified);
11482
11483 // Step E as described at the top of AddState: If aReplace is false,
11484 // indicating that we're doing a pushState rather than a replaceState,
11485 // notify bfcache that we've added a page to the history so it can evict
11486 // content viewers if appropriate. Otherwise call ReplaceEntry so that we
11487 // notify nsIHistoryListeners that an entry was replaced. We may not have a
11488 // root session history if this call is coming from a document.open() in a
11489 // docshell subtree that disables session history.
11490 RefPtr<ChildSHistory> rootSH = GetRootSessionHistory();
11491 if (rootSH) {
11492 rootSH->LegacySHistory()->EvictDocumentViewersOrReplaceEntry(newSHEntry,
11493 aReplace);
11494 }
11495 }
11496
11497 // Step 4: If the document's URI changed, update document's URI and update
11498 // global history.
11499 //
11500 // We need to call FireOnLocationChange so that the browser's address bar
11501 // gets updated and the back button is enabled, but we only need to
11502 // explicitly call FireOnLocationChange if we're not calling SetCurrentURI,
11503 // since SetCurrentURI will call FireOnLocationChange for us.
11504 //
11505 // Both SetCurrentURI(...) and FireDummyOnLocationChange() pass
11506 // nullptr for aRequest param to FireOnLocationChange(...). Such an update
11507 // notification is allowed only when we know docshell is not loading a new
11508 // document and it requires LOCATION_CHANGE_SAME_DOCUMENT flag. Otherwise,
11509 // FireOnLocationChange(...) breaks security UI.
11510 //
11511 // If the docshell is shutting down, don't update the document URI, as we
11512 // can't load into a docshell that is being destroyed.
11513 if (!aEqualURIs && !mIsBeingDestroyed) {
11514 aDocument->SetDocumentURI(aNewURI);
11515 SetCurrentURI(aNewURI, nullptr, /* aFireLocationChange */ true,
11516 /* aIsInitialAboutBlank */ false,
11517 GetSameDocumentNavigationFlags(aNewURI));
11518
11519 AddURIVisit(aNewURI, aCurrentURI, 0);
11520
11521 // AddURIVisit doesn't set the title for the new URI in global history,
11522 // so do that here.
11523 UpdateGlobalHistoryTitle(aNewURI);
11524
11525 // Inform the favicon service that our old favicon applies to this new
11526 // URI.
11527 CopyFavicon(aCurrentURI, aNewURI, UsePrivateBrowsing());
11528 } else {
11529 FireDummyOnLocationChange();
11530 }
11531 aDocument->SetStateObject(aData);
11532
11533 return NS_OK;
11534}
11535
11536NS_IMETHODIMPnsresult
11537nsDocShell::GetCurrentScrollRestorationIsManual(bool* aIsManual) {
11538 if (mozilla::SessionHistoryInParent()) {
11539 *aIsManual = mActiveEntry && mActiveEntry->GetScrollRestorationIsManual();
11540 return NS_OK;
11541 }
11542
11543 *aIsManual = false;
11544 if (mOSHE) {
11545 return mOSHE->GetScrollRestorationIsManual(aIsManual);
11546 }
11547
11548 return NS_OK;
11549}
11550
11551NS_IMETHODIMPnsresult
11552nsDocShell::SetCurrentScrollRestorationIsManual(bool aIsManual) {
11553 SetScrollRestorationIsManualOnHistoryEntry(mOSHE, aIsManual);
11554
11555 return NS_OK;
11556}
11557
11558void nsDocShell::SetScrollRestorationIsManualOnHistoryEntry(
11559 nsISHEntry* aSHEntry, bool aIsManual) {
11560 if (aSHEntry) {
11561 aSHEntry->SetScrollRestorationIsManual(aIsManual);
11562 }
11563
11564 if (mActiveEntry && mBrowsingContext) {
11565 mActiveEntry->SetScrollRestorationIsManual(aIsManual);
11566 if (XRE_IsParentProcess()) {
11567 SessionHistoryEntry* entry =
11568 mBrowsingContext->Canonical()->GetActiveSessionHistoryEntry();
11569 if (entry) {
11570 entry->SetScrollRestorationIsManual(aIsManual);
11571 }
11572 } else {
11573 mozilla::Unused << ContentChild::GetSingleton()
11574 ->SendSessionHistoryEntryScrollRestorationIsManual(
11575 mBrowsingContext, aIsManual);
11576 }
11577 }
11578}
11579
11580void nsDocShell::SetCacheKeyOnHistoryEntry(nsISHEntry* aSHEntry,
11581 uint32_t aCacheKey) {
11582 if (aSHEntry) {
11583 aSHEntry->SetCacheKey(aCacheKey);
11584 }
11585
11586 if (mActiveEntry && mBrowsingContext) {
11587 mActiveEntry->SetCacheKey(aCacheKey);
11588 if (XRE_IsParentProcess()) {
11589 SessionHistoryEntry* entry =
11590 mBrowsingContext->Canonical()->GetActiveSessionHistoryEntry();
11591 if (entry) {
11592 entry->SetCacheKey(aCacheKey);
11593 }
11594 } else {
11595 mozilla::Unused
11596 << ContentChild::GetSingleton()->SendSessionHistoryEntryCacheKey(
11597 mBrowsingContext, aCacheKey);
11598 }
11599 }
11600}
11601
11602/* static */
11603bool nsDocShell::ShouldAddToSessionHistory(nsIURI* aURI, nsIChannel* aChannel) {
11604 // I believe none of the about: urls should go in the history. But then
11605 // that could just be me... If the intent is only deny about:blank then we
11606 // should just do a spec compare, rather than two gets of the scheme and
11607 // then the path. -Gagan
11608 nsresult rv;
11609 nsAutoCString buf;
11610
11611 rv = aURI->GetScheme(buf);
11612 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
11613 return false;
11614 }
11615
11616 if (buf.EqualsLiteral("about")) {
11617 rv = aURI->GetPathQueryRef(buf);
11618 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
11619 return false;
11620 }
11621
11622 if (buf.EqualsLiteral("blank")) {
11623 return false;
11624 }
11625 // We only want to add about:newtab if it's not privileged, and
11626 // if it is not configured to show the blank page.
11627 if (buf.EqualsLiteral("newtab")) {
11628 if (!StaticPrefs::browser_newtabpage_enabled()) {
11629 return false;
11630 }
11631
11632 NS_ENSURE_TRUE(aChannel, false)do { if ((__builtin_expect(!!(!(aChannel)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aChannel" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 11632); return false; } } while (false)
;
11633 nsCOMPtr<nsIPrincipal> resultPrincipal;
11634 rv = nsContentUtils::GetSecurityManager()->GetChannelResultPrincipal(
11635 aChannel, getter_AddRefs(resultPrincipal));
11636 NS_ENSURE_SUCCESS(rv, false)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", "false", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 11636); return false; } } while (false)
;
11637 return !resultPrincipal->IsSystemPrincipal();
11638 }
11639 }
11640
11641 return true;
11642}
11643
11644nsresult nsDocShell::AddToSessionHistory(
11645 nsIURI* aURI, nsIChannel* aChannel, nsIPrincipal* aTriggeringPrincipal,
11646 nsIPrincipal* aPrincipalToInherit,
11647 nsIPrincipal* aPartitionedPrincipalToInherit,
11648 nsIContentSecurityPolicy* aCsp, bool aCloneChildren,
11649 nsISHEntry** aNewEntry) {
11650 MOZ_ASSERT(aURI, "uri is null")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aURI)>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(aURI))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("aURI" " (" "uri is null" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 11650); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aURI" ") ("
"uri is null" ")"); do { *((volatile int*)__null) = 11650; __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
;
11651 MOZ_ASSERT(!aChannel || !aTriggeringPrincipal, "Shouldn't have both set")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aChannel || !aTriggeringPrincipal)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!aChannel || !aTriggeringPrincipal
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"!aChannel || !aTriggeringPrincipal" " (" "Shouldn't have both set"
")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 11651); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aChannel || !aTriggeringPrincipal"
") (" "Shouldn't have both set" ")"); do { *((volatile int*)
__null) = 11651; __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
11652 MOZ_DIAGNOSTIC_ASSERT(!mozilla::SessionHistoryInParent())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mozilla::SessionHistoryInParent())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mozilla::SessionHistoryInParent
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!mozilla::SessionHistoryInParent()", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 11652); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "!mozilla::SessionHistoryInParent()"
")"); do { *((volatile int*)__null) = 11652; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11653
11654#if defined(DEBUG1)
11655 if (MOZ_LOG_TEST(gDocShellLog, LogLevel::Debug)(__builtin_expect(!!(mozilla::detail::log_test(gDocShellLog, LogLevel
::Debug)), 0))
) {
11656 nsAutoCString chanName;
11657 if (aChannel) {
11658 aChannel->GetName(chanName);
11659 } else {
11660 chanName.AssignLiteral("<no channel>");
11661 }
11662
11663 MOZ_LOG(gDocShellLog, LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = gDocShellLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "nsDocShell[%p]::AddToSessionHistory(\"%s\", [%s])\n"
, this, aURI->GetSpecOrDefault().get(), chanName.get()); }
} while (0)
11664 ("nsDocShell[%p]::AddToSessionHistory(\"%s\", [%s])\n", this,do { const ::mozilla::LogModule* moz_real_module = gDocShellLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "nsDocShell[%p]::AddToSessionHistory(\"%s\", [%s])\n"
, this, aURI->GetSpecOrDefault().get(), chanName.get()); }
} while (0)
11665 aURI->GetSpecOrDefault().get(), chanName.get()))do { const ::mozilla::LogModule* moz_real_module = gDocShellLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "nsDocShell[%p]::AddToSessionHistory(\"%s\", [%s])\n"
, this, aURI->GetSpecOrDefault().get(), chanName.get()); }
} while (0)
;
11666 }
11667#endif
11668
11669 nsresult rv = NS_OK;
11670 nsCOMPtr<nsISHEntry> entry;
11671
11672 /*
11673 * If this is a LOAD_FLAGS_REPLACE_HISTORY in a subframe, we use
11674 * the existing SH entry in the page and replace the url and
11675 * other vitalities.
11676 */
11677 if (LOAD_TYPE_HAS_FLAGS(mLoadType, LOAD_FLAGS_REPLACE_HISTORY)((mLoadType) & ((LOAD_FLAGS_REPLACE_HISTORY) << 16)
)
&&
11678 !mBrowsingContext->IsTop()) {
11679 // This is a subframe
11680 entry = mOSHE;
11681 if (entry) {
11682 entry->ClearEntry();
11683 }
11684 }
11685
11686 // Create a new entry if necessary.
11687 if (!entry) {
11688 entry = new nsSHEntry();
11689 }
11690
11691 // Get the post data & referrer
11692 nsCOMPtr<nsIInputStream> inputStream;
11693 nsCOMPtr<nsIURI> originalURI;
11694 nsCOMPtr<nsIURI> resultPrincipalURI;
11695 nsCOMPtr<nsIURI> unstrippedURI;
11696 bool loadReplace = false;
11697 nsCOMPtr<nsIReferrerInfo> referrerInfo;
11698 uint32_t cacheKey = 0;
11699 nsCOMPtr<nsIPrincipal> triggeringPrincipal = aTriggeringPrincipal;
11700 nsCOMPtr<nsIPrincipal> principalToInherit = aPrincipalToInherit;
11701 nsCOMPtr<nsIPrincipal> partitionedPrincipalToInherit =
11702 aPartitionedPrincipalToInherit;
11703 nsCOMPtr<nsIContentSecurityPolicy> csp = aCsp;
11704 bool expired = false; // by default the page is not expired
11705 bool discardLayoutState = false;
11706 nsCOMPtr<nsICacheInfoChannel> cacheChannel;
11707 bool userActivation = false;
11708
11709 if (aChannel) {
11710 cacheChannel = do_QueryInterface(aChannel);
11711
11712 /* If there is a caching channel, get the Cache Key and store it
11713 * in SH.
11714 */
11715 if (cacheChannel) {
11716 cacheChannel->GetCacheKey(&cacheKey);
11717 }
11718 nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(aChannel));
11719
11720 // Check if the httpChannel is hiding under a multipartChannel
11721 if (!httpChannel) {
11722 GetHttpChannel(aChannel, getter_AddRefs(httpChannel));
11723 }
11724 if (httpChannel) {
11725 nsCOMPtr<nsIUploadChannel> uploadChannel(do_QueryInterface(httpChannel));
11726 if (uploadChannel) {
11727 uploadChannel->GetUploadStream(getter_AddRefs(inputStream));
11728 }
11729 httpChannel->GetOriginalURI(getter_AddRefs(originalURI));
11730 uint32_t loadFlags;
11731 aChannel->GetLoadFlags(&loadFlags);
11732 loadReplace = loadFlags & nsIChannel::LOAD_REPLACE;
11733 rv = httpChannel->GetReferrerInfo(getter_AddRefs(referrerInfo));
11734 MOZ_ASSERT(NS_SUCCEEDED(rv))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
)))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 11734); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { *((volatile int*)__null) = 11734; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11735
11736 discardLayoutState = ShouldDiscardLayoutState(httpChannel);
11737 }
11738
11739 nsCOMPtr<nsILoadInfo> loadInfo = aChannel->LoadInfo();
11740 if (!triggeringPrincipal) {
11741 triggeringPrincipal = loadInfo->TriggeringPrincipal();
11742 }
11743 if (!csp) {
11744 csp = loadInfo->GetCspToInherit();
11745 }
11746
11747 loadInfo->GetResultPrincipalURI(getter_AddRefs(resultPrincipalURI));
11748
11749 loadInfo->GetUnstrippedURI(getter_AddRefs(unstrippedURI));
11750
11751 userActivation = loadInfo->GetHasValidUserGestureActivation();
11752
11753 // For now keep storing just the principal in the SHEntry.
11754 if (!principalToInherit) {
11755 if (loadInfo->GetLoadingSandboxed()) {
11756 if (loadInfo->GetLoadingPrincipal()) {
11757 principalToInherit = NullPrincipal::CreateWithInheritedAttributes(
11758 loadInfo->GetLoadingPrincipal());
11759 } else {
11760 // get the OriginAttributes
11761 OriginAttributes attrs;
11762 loadInfo->GetOriginAttributes(&attrs);
11763 principalToInherit = NullPrincipal::Create(attrs);
11764 }
11765 } else {
11766 principalToInherit = loadInfo->PrincipalToInherit();
11767 }
11768 }
11769
11770 if (!partitionedPrincipalToInherit) {
11771 // XXXehsan is it correct to fall back to the principal to inherit in all
11772 // cases? For example, what about the cases where we are using the load
11773 // info's principal to inherit? Do we need to add a similar concept to
11774 // load info for partitioned principal?
11775 partitionedPrincipalToInherit = principalToInherit;
11776 }
11777 }
11778
11779 nsAutoString srcdoc;
11780 bool srcdocEntry = false;
11781 nsCOMPtr<nsIURI> baseURI;
11782
11783 nsCOMPtr<nsIInputStreamChannel> inStrmChan = do_QueryInterface(aChannel);
11784 if (inStrmChan) {
11785 bool isSrcdocChannel;
11786 inStrmChan->GetIsSrcdocChannel(&isSrcdocChannel);
11787 if (isSrcdocChannel) {
11788 inStrmChan->GetSrcdocData(srcdoc);
11789 srcdocEntry = true;
11790 inStrmChan->GetBaseURI(getter_AddRefs(baseURI));
11791 } else {
11792 srcdoc.SetIsVoid(true);
11793 }
11794 }
11795 /* If cache got a 'no-store', ask SH not to store
11796 * HistoryLayoutState. By default, SH will set this
11797 * flag to true and save HistoryLayoutState.
11798 */
11799 bool saveLayoutState = !discardLayoutState;
11800
11801 if (cacheChannel) {
11802 // Check if the page has expired from cache
11803 uint32_t expTime = 0;
11804 cacheChannel->GetCacheTokenExpirationTime(&expTime);
11805 uint32_t now = PRTimeToSeconds(PR_Now());
11806 if (expTime <= now) {
11807 expired = true;
11808 }
11809 }
11810
11811 // Title is set in nsDocShell::SetTitle()
11812 entry->Create(aURI, // uri
11813 u""_ns, // Title
11814 inputStream, // Post data stream
11815 cacheKey, // CacheKey
11816 mContentTypeHint, // Content-type
11817 triggeringPrincipal, // Channel or provided principal
11818 principalToInherit, partitionedPrincipalToInherit, csp,
11819 HistoryID(), GetCreatedDynamically(), originalURI,
11820 resultPrincipalURI, unstrippedURI, loadReplace, referrerInfo,
11821 srcdoc, srcdocEntry, baseURI, saveLayoutState, expired,
11822 userActivation);
11823
11824 if (mBrowsingContext->IsTop() && GetSessionHistory()) {
11825 bool shouldPersist = ShouldAddToSessionHistory(aURI, aChannel);
11826 Maybe<int32_t> previousEntryIndex;
11827 Maybe<int32_t> loadedEntryIndex;
11828 rv = GetSessionHistory()->LegacySHistory()->AddToRootSessionHistory(
11829 aCloneChildren, mOSHE, mBrowsingContext, entry, mLoadType,
11830 shouldPersist, &previousEntryIndex, &loadedEntryIndex);
11831
11832 MOZ_ASSERT(NS_SUCCEEDED(rv), "Could not add entry to root session history")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
)))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))" " ("
"Could not add entry to root session history" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 11832); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
") (" "Could not add entry to root session history" ")"); do
{ *((volatile int*)__null) = 11832; __attribute__((nomerge))
::abort(); } while (false); } } while (false)
;
11833 if (previousEntryIndex.isSome()) {
11834 mPreviousEntryIndex = previousEntryIndex.value();
11835 }
11836 if (loadedEntryIndex.isSome()) {
11837 mLoadedEntryIndex = loadedEntryIndex.value();
11838 }
11839
11840 // aCloneChildren implies that we are retaining the same document, thus we
11841 // need to signal to the top WC that the new SHEntry may receive a fresh
11842 // user interaction flag.
11843 if (aCloneChildren) {
11844 WindowContext* topWc = mBrowsingContext->GetTopWindowContext();
11845 if (topWc && !topWc->IsDiscarded()) {
11846 MOZ_ALWAYS_SUCCEEDS(topWc->SetSHEntryHasUserInteraction(false))do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(topWc->SetSHEntryHasUserInteraction(false))), 1)))), 1)))
{ } else { do { static_assert( mozilla::detail::AssertionConditionType
<decltype(false)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("false" " (" "NS_SUCCEEDED(topWc->SetSHEntryHasUserInteraction(false))"
")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 11846); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "false"
") (" "NS_SUCCEEDED(topWc->SetSHEntryHasUserInteraction(false))"
")"); do { *((volatile int*)__null) = 11846; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false); } } while
(false)
;
11847 }
11848 }
11849 } else {
11850 // This is a subframe, make sure that this new SHEntry will be
11851 // marked with user interaction.
11852 WindowContext* topWc = mBrowsingContext->GetTopWindowContext();
11853 if (topWc && !topWc->IsDiscarded()) {
11854 MOZ_ALWAYS_SUCCEEDS(topWc->SetSHEntryHasUserInteraction(false))do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(topWc->SetSHEntryHasUserInteraction(false))), 1)))), 1)))
{ } else { do { static_assert( mozilla::detail::AssertionConditionType
<decltype(false)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("false" " (" "NS_SUCCEEDED(topWc->SetSHEntryHasUserInteraction(false))"
")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 11854); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "false"
") (" "NS_SUCCEEDED(topWc->SetSHEntryHasUserInteraction(false))"
")"); do { *((volatile int*)__null) = 11854; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false); } } while
(false)
;
11855 }
11856 if (!mOSHE || !LOAD_TYPE_HAS_FLAGS(mLoadType, LOAD_FLAGS_REPLACE_HISTORY)((mLoadType) & ((LOAD_FLAGS_REPLACE_HISTORY) << 16)
)
) {
11857 rv = AddChildSHEntryToParent(entry, mBrowsingContext->ChildOffset(),
11858 aCloneChildren);
11859 }
11860 }
11861
11862 // Return the new SH entry...
11863 if (aNewEntry) {
11864 *aNewEntry = nullptr;
11865 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
11866 entry.forget(aNewEntry);
11867 }
11868 }
11869
11870 return rv;
11871}
11872
11873void nsDocShell::UpdateActiveEntry(
11874 bool aReplace, const Maybe<nsPoint>& aPreviousScrollPos, nsIURI* aURI,
11875 nsIURI* aOriginalURI, nsIReferrerInfo* aReferrerInfo,
11876 nsIPrincipal* aTriggeringPrincipal, nsIContentSecurityPolicy* aCsp,
11877 const nsAString& aTitle, bool aScrollRestorationIsManual,
11878 nsIStructuredCloneContainer* aData, bool aURIWasModified) {
11879 MOZ_ASSERT(mozilla::SessionHistoryInParent())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mozilla::SessionHistoryInParent())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mozilla::SessionHistoryInParent
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("mozilla::SessionHistoryInParent()", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 11879); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mozilla::SessionHistoryInParent()"
")"); do { *((volatile int*)__null) = 11879; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11880 MOZ_ASSERT(aURI, "uri is null")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aURI)>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(aURI))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("aURI" " (" "uri is null" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 11880); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aURI" ") ("
"uri is null" ")"); do { *((volatile int*)__null) = 11880; __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
;
11881 MOZ_ASSERT(mLoadType == LOAD_PUSHSTATE,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mLoadType == LOAD_PUSHSTATE)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mLoadType == LOAD_PUSHSTATE)
)), 0))) { do { } while (false); MOZ_ReportAssertionFailure("mLoadType == LOAD_PUSHSTATE"
" (" "This code only deals with pushState" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 11882); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mLoadType == LOAD_PUSHSTATE"
") (" "This code only deals with pushState" ")"); do { *((volatile
int*)__null) = 11882; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
11882 "This code only deals with pushState")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mLoadType == LOAD_PUSHSTATE)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mLoadType == LOAD_PUSHSTATE)
)), 0))) { do { } while (false); MOZ_ReportAssertionFailure("mLoadType == LOAD_PUSHSTATE"
" (" "This code only deals with pushState" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 11882); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mLoadType == LOAD_PUSHSTATE"
") (" "This code only deals with pushState" ")"); do { *((volatile
int*)__null) = 11882; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
11883 MOZ_ASSERT_IF(aPreviousScrollPos.isSome(), !aReplace)do { if (aPreviousScrollPos.isSome()) { do { static_assert( mozilla
::detail::AssertionConditionType<decltype(!aReplace)>::
isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!aReplace))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!aReplace", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 11883); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aReplace"
")"); do { *((volatile int*)__null) = 11883; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false); } } while
(false)
;
11884
11885 MOZ_LOG(gSHLog, LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = gSHLog; if
((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "Creating an active entry on nsDocShell %p to %s"
, this, aURI->GetSpecOrDefault().get()); } } while (0)
11886 ("Creating an active entry on nsDocShell %p to %s", this,do { const ::mozilla::LogModule* moz_real_module = gSHLog; if
((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "Creating an active entry on nsDocShell %p to %s"
, this, aURI->GetSpecOrDefault().get()); } } while (0)
11887 aURI->GetSpecOrDefault().get()))do { const ::mozilla::LogModule* moz_real_module = gSHLog; if
((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "Creating an active entry on nsDocShell %p to %s"
, this, aURI->GetSpecOrDefault().get()); } } while (0)
;
11888
11889 // Even if we're replacing an existing entry we create new a
11890 // SessionHistoryInfo. In the parent process we'll keep the existing
11891 // SessionHistoryEntry, but just replace its SessionHistoryInfo, that way the
11892 // entry keeps identity but its data is replaced.
11893 bool replace = aReplace && mActiveEntry;
11894
11895 if (!replace) {
11896 CollectWireframe();
11897 }
11898
11899 if (mActiveEntry) {
11900 // Link this entry to the previous active entry.
11901 mActiveEntry = MakeUnique<SessionHistoryInfo>(*mActiveEntry, aURI);
11902 } else {
11903 mActiveEntry = MakeUnique<SessionHistoryInfo>(
11904 aURI, aTriggeringPrincipal, nullptr, nullptr, aCsp, mContentTypeHint);
11905 }
11906 mActiveEntry->SetOriginalURI(aOriginalURI);
11907 mActiveEntry->SetUnstrippedURI(nullptr);
11908 mActiveEntry->SetReferrerInfo(aReferrerInfo);
11909 mActiveEntry->SetTitle(aTitle);
11910 mActiveEntry->SetStateData(static_cast<nsStructuredCloneContainer*>(aData));
11911 mActiveEntry->SetURIWasModified(aURIWasModified);
11912 mActiveEntry->SetScrollRestorationIsManual(aScrollRestorationIsManual);
11913
11914 if (replace) {
11915 mBrowsingContext->ReplaceActiveSessionHistoryEntry(mActiveEntry.get());
11916 } else {
11917 mBrowsingContext->IncrementHistoryEntryCountForBrowsingContext();
11918 // FIXME We should probably just compute mChildOffset in the parent
11919 // instead of passing it over IPC here.
11920 mBrowsingContext->SetActiveSessionHistoryEntry(
11921 aPreviousScrollPos, mActiveEntry.get(), mLoadType,
11922 /* aCacheKey = */ 0);
11923 // FIXME Do we need to update mPreviousEntryIndex and mLoadedEntryIndex?
11924 }
11925}
11926
11927nsresult nsDocShell::LoadHistoryEntry(nsISHEntry* aEntry, uint32_t aLoadType,
11928 bool aUserActivation) {
11929 NS_ENSURE_TRUE(aEntry, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(aEntry)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aEntry" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 11929); return NS_ERROR_FAILURE; } } while (false)
;
11930
11931 nsresult rv;
11932 RefPtr<nsDocShellLoadState> loadState;
11933 rv = aEntry->CreateLoadInfo(getter_AddRefs(loadState));
11934 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/docshell/base/nsDocShell.cpp"
, 11934); return rv; } } while (false)
;
11935
11936 // Calling CreateAboutBlankDocumentViewer can set mOSHE to null, and if
11937 // that's the only thing holding a ref to aEntry that will cause aEntry to
11938 // die while we're loading it. So hold a strong ref to aEntry here, just
11939 // in case.
11940 nsCOMPtr<nsISHEntry> kungFuDeathGrip(aEntry);
11941
11942 loadState->SetHasValidUserGestureActivation(
11943 loadState->HasValidUserGestureActivation() || aUserActivation);
11944
11945 loadState->SetTextDirectiveUserActivation(
11946 loadState->GetTextDirectiveUserActivation() || aUserActivation);
11947
11948 return LoadHistoryEntry(loadState, aLoadType, aEntry == mOSHE);
11949}
11950
11951nsresult nsDocShell::LoadHistoryEntry(const LoadingSessionHistoryInfo& aEntry,
11952 uint32_t aLoadType,
11953 bool aUserActivation) {
11954 RefPtr<nsDocShellLoadState> loadState = aEntry.CreateLoadInfo();
11955 loadState->SetHasValidUserGestureActivation(
11956 loadState->HasValidUserGestureActivation() || aUserActivation);
11957
11958 loadState->SetTextDirectiveUserActivation(
11959 loadState->GetTextDirectiveUserActivation() || aUserActivation);
11960
11961 return LoadHistoryEntry(loadState, aLoadType, aEntry.mLoadingCurrentEntry);
11962}
11963
11964nsresult nsDocShell::LoadHistoryEntry(nsDocShellLoadState* aLoadState,
11965 uint32_t aLoadType,
11966 bool aLoadingCurrentEntry) {
11967 if (!IsNavigationAllowed()) {
11968 return NS_OK;
11969 }
11970
11971 // We are setting load type afterwards so we don't have to
11972 // send it in an IPC message
11973 aLoadState->SetLoadType(aLoadType);
11974
11975 nsresult rv;
11976 if (SchemeIsJavascript(aLoadState->URI())) {
11977 // We're loading a URL that will execute script from inside asyncOpen.
11978 // Replace the current document with about:blank now to prevent
11979 // anything from the current document from leaking into any JavaScript
11980 // code in the URL.
11981 // Don't cache the presentation if we're going to just reload the
11982 // current entry. Caching would lead to trying to save the different
11983 // content viewers in the same nsISHEntry object.
11984 rv = CreateAboutBlankDocumentViewer(
11985 aLoadState->PrincipalToInherit(),
11986 aLoadState->PartitionedPrincipalToInherit(), nullptr, nullptr,
11987 /* aIsInitialDocument */ false, Nothing(), !aLoadingCurrentEntry);
11988
11989 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
11990 // The creation of the intermittent about:blank content
11991 // viewer failed for some reason (potentially because the
11992 // user prevented it). Interrupt the history load.
11993 return NS_OK;
11994 }
11995
11996 if (!aLoadState->TriggeringPrincipal()) {
11997 // Ensure that we have a triggeringPrincipal. Otherwise javascript:
11998 // URIs will pick it up from the about:blank page we just loaded,
11999 // and we don't really want even that in this case.
12000 nsCOMPtr<nsIPrincipal> principal =
12001 NullPrincipal::Create(GetOriginAttributes());
12002 aLoadState->SetTriggeringPrincipal(principal);
12003 }
12004 }
12005
12006 /* If there is a valid postdata *and* the user pressed
12007 * reload or shift-reload, take user's permission before we
12008 * repost the data to the server.
12009 */
12010 if ((aLoadType & LOAD_CMD_RELOAD) && aLoadState->PostDataStream()) {
12011 bool repost;
12012 rv = ConfirmRepost(&repost);
12013 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
12014 return rv;
12015 }
12016
12017 // If the user pressed cancel in the dialog, return. We're done here.
12018 if (!repost) {
12019 return NS_BINDING_ABORTED;
12020 }
12021 }
12022
12023 // If there is no valid triggeringPrincipal, we deny the load
12024 MOZ_ASSERT(aLoadState->TriggeringPrincipal(),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aLoadState->TriggeringPrincipal())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aLoadState->TriggeringPrincipal
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("aLoadState->TriggeringPrincipal()" " (" "need a valid triggeringPrincipal to load from history"
")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 12025); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->TriggeringPrincipal()"
") (" "need a valid triggeringPrincipal to load from history"
")"); do { *((volatile int*)__null) = 12025; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
12025 "need a valid triggeringPrincipal to load from history")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aLoadState->TriggeringPrincipal())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aLoadState->TriggeringPrincipal
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("aLoadState->TriggeringPrincipal()" " (" "need a valid triggeringPrincipal to load from history"
")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 12025); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->TriggeringPrincipal()"
") (" "need a valid triggeringPrincipal to load from history"
")"); do { *((volatile int*)__null) = 12025; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12026 if (!aLoadState->TriggeringPrincipal()) {
12027 return NS_ERROR_FAILURE;
12028 }
12029
12030 return InternalLoad(aLoadState); // No nsIRequest
12031}
12032
12033NS_IMETHODIMPnsresult
12034nsDocShell::PersistLayoutHistoryState() {
12035 nsresult rv = NS_OK;
12036
12037 if (mozilla::SessionHistoryInParent() ? !!mActiveEntry : !!mOSHE) {
12038 bool scrollRestorationIsManual;
12039 if (mozilla::SessionHistoryInParent()) {
12040 scrollRestorationIsManual = mActiveEntry->GetScrollRestorationIsManual();
12041 } else {
12042 scrollRestorationIsManual = mOSHE->GetScrollRestorationIsManual();
12043 }
12044 nsCOMPtr<nsILayoutHistoryState> layoutState;
12045 if (RefPtr<PresShell> presShell = GetPresShell()) {
12046 rv = presShell->CaptureHistoryState(getter_AddRefs(layoutState));
12047 } else if (scrollRestorationIsManual) {
12048 // Even if we don't have layout anymore, we may want to reset the
12049 // current scroll state in layout history.
12050 GetLayoutHistoryState(getter_AddRefs(layoutState));
12051 }
12052
12053 if (scrollRestorationIsManual && layoutState) {
12054 layoutState->ResetScrollState();
12055 }
12056 }
12057
12058 return rv;
12059}
12060
12061void nsDocShell::SwapHistoryEntries(nsISHEntry* aOldEntry,
12062 nsISHEntry* aNewEntry) {
12063 if (aOldEntry == mOSHE) {
12064 mOSHE = aNewEntry;
12065 }
12066
12067 if (aOldEntry == mLSHE) {
12068 mLSHE = aNewEntry;
12069 }
12070}
12071
12072void nsDocShell::SetHistoryEntryAndUpdateBC(const Maybe<nsISHEntry*>& aLSHE,
12073 const Maybe<nsISHEntry*>& aOSHE) {
12074 // We want to hold on to the reference in mLSHE before we update it.
12075 // Otherwise, SetHistoryEntry could release the last reference to
12076 // the entry while aOSHE is pointing to it.
12077 nsCOMPtr<nsISHEntry> deathGripOldLSHE;
12078 if (aLSHE.isSome()) {
12079 deathGripOldLSHE = SetHistoryEntry(&mLSHE, aLSHE.value());
12080 MOZ_ASSERT(mLSHE.get() == aLSHE.value())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mLSHE.get() == aLSHE.value())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mLSHE.get() == aLSHE.value()
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"mLSHE.get() == aLSHE.value()", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 12080); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mLSHE.get() == aLSHE.value()"
")"); do { *((volatile int*)__null) = 12080; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12081 }
12082 nsCOMPtr<nsISHEntry> deathGripOldOSHE;
12083 if (aOSHE.isSome()) {
12084 deathGripOldOSHE = SetHistoryEntry(&mOSHE, aOSHE.value());
12085 MOZ_ASSERT(mOSHE.get() == aOSHE.value())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mOSHE.get() == aOSHE.value())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mOSHE.get() == aOSHE.value()
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"mOSHE.get() == aOSHE.value()", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 12085); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mOSHE.get() == aOSHE.value()"
")"); do { *((volatile int*)__null) = 12085; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12086 }
12087}
12088
12089already_AddRefed<nsISHEntry> nsDocShell::SetHistoryEntry(
12090 nsCOMPtr<nsISHEntry>* aPtr, nsISHEntry* aEntry) {
12091 // We need to sync up the docshell and session history trees for
12092 // subframe navigation. If the load was in a subframe, we forward up to
12093 // the root docshell, which will then recursively sync up all docshells
12094 // to their corresponding entries in the new session history tree.
12095 // If we don't do this, then we can cache a content viewer on the wrong
12096 // cloned entry, and subsequently restore it at the wrong time.
12097 RefPtr<BrowsingContext> topBC = mBrowsingContext->Top();
12098 if (topBC->IsDiscarded()) {
12099 topBC = nullptr;
12100 }
12101 RefPtr<BrowsingContext> currBC =
12102 mBrowsingContext->IsDiscarded() ? nullptr : mBrowsingContext;
12103 if (topBC && *aPtr) {
12104 (*aPtr)->SyncTreesForSubframeNavigation(aEntry, topBC, currBC);
12105 }
12106 nsCOMPtr<nsISHEntry> entry(aEntry);
12107 entry.swap(*aPtr);
12108 return entry.forget();
12109}
12110
12111already_AddRefed<ChildSHistory> nsDocShell::GetRootSessionHistory() {
12112 RefPtr<ChildSHistory> childSHistory =
12113 mBrowsingContext->Top()->GetChildSessionHistory();
12114 return childSHistory.forget();
12115}
12116
12117nsresult nsDocShell::GetHttpChannel(nsIChannel* aChannel,
12118 nsIHttpChannel** aReturn) {
12119 NS_ENSURE_ARG_POINTER(aReturn)do { if ((__builtin_expect(!!(!(aReturn)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aReturn" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 12119); return NS_ERROR_INVALID_POINTER; } } while (false)
;
12120 if (!aChannel) {
12121 return NS_ERROR_FAILURE;
12122 }
12123
12124 nsCOMPtr<nsIMultiPartChannel> multiPartChannel(do_QueryInterface(aChannel));
12125 if (multiPartChannel) {
12126 nsCOMPtr<nsIChannel> baseChannel;
12127 multiPartChannel->GetBaseChannel(getter_AddRefs(baseChannel));
12128 nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(baseChannel));
12129 *aReturn = httpChannel;
12130 NS_IF_ADDREF(*aReturn)ns_if_addref(*aReturn);
12131 }
12132 return NS_OK;
12133}
12134
12135bool nsDocShell::ShouldDiscardLayoutState(nsIHttpChannel* aChannel) {
12136 // By default layout State will be saved.
12137 if (!aChannel) {
12138 return false;
12139 }
12140
12141 // figure out if SH should be saving layout state
12142 bool noStore = false;
12143 Unused << aChannel->IsNoStoreResponse(&noStore);
12144 return noStore;
12145}
12146
12147NS_IMETHODIMPnsresult
12148nsDocShell::GetEditor(nsIEditor** aEditor) {
12149 NS_ENSURE_ARG_POINTER(aEditor)do { if ((__builtin_expect(!!(!(aEditor)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aEditor" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 12149); return NS_ERROR_INVALID_POINTER; } } while (false)
;
12150 RefPtr<HTMLEditor> htmlEditor = GetHTMLEditorInternal();
12151 htmlEditor.forget(aEditor);
12152 return NS_OK;
12153}
12154
12155NS_IMETHODIMPnsresult
12156nsDocShell::SetEditor(nsIEditor* aEditor) {
12157 HTMLEditor* htmlEditor = aEditor ? aEditor->GetAsHTMLEditor() : nullptr;
12158 // If TextEditor comes, throw an error.
12159 if (aEditor && !htmlEditor) {
12160 return NS_ERROR_INVALID_ARG;
12161 }
12162 return SetHTMLEditorInternal(htmlEditor);
12163}
12164
12165HTMLEditor* nsDocShell::GetHTMLEditorInternal() {
12166 return mEditorData ? mEditorData->GetHTMLEditor() : nullptr;
12167}
12168
12169nsresult nsDocShell::SetHTMLEditorInternal(HTMLEditor* aHTMLEditor) {
12170 if (!aHTMLEditor && !mEditorData) {
12171 return NS_OK;
12172 }
12173
12174 nsresult rv = EnsureEditorData();
12175 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
12176 return rv;
12177 }
12178
12179 return mEditorData->SetHTMLEditor(aHTMLEditor);
12180}
12181
12182NS_IMETHODIMPnsresult
12183nsDocShell::GetEditable(bool* aEditable) {
12184 NS_ENSURE_ARG_POINTER(aEditable)do { if ((__builtin_expect(!!(!(aEditable)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aEditable" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 12184); return NS_ERROR_INVALID_POINTER; } } while (false)
;
12185 *aEditable = mEditorData && mEditorData->GetEditable();
12186 return NS_OK;
12187}
12188
12189NS_IMETHODIMPnsresult
12190nsDocShell::GetHasEditingSession(bool* aHasEditingSession) {
12191 NS_ENSURE_ARG_POINTER(aHasEditingSession)do { if ((__builtin_expect(!!(!(aHasEditingSession)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aHasEditingSession" ") failed"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 12191); return NS_ERROR_INVALID_POINTER; } } while (false)
;
12192
12193 if (mEditorData) {
12194 *aHasEditingSession = !!mEditorData->GetEditingSession();
12195 } else {
12196 *aHasEditingSession = false;
12197 }
12198
12199 return NS_OK;
12200}
12201
12202NS_IMETHODIMPnsresult
12203nsDocShell::MakeEditable(bool aInWaitForUriLoad) {
12204 nsresult rv = EnsureEditorData();
12205 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
12206 return rv;
12207 }
12208
12209 return mEditorData->MakeEditable(aInWaitForUriLoad);
12210}
12211
12212/* static */ bool nsDocShell::ShouldAddURIVisit(nsIChannel* aChannel) {
12213 bool needToAddURIVisit = true;
12214 nsCOMPtr<nsIPropertyBag2> props(do_QueryInterface(aChannel));
12215 if (props) {
12216 mozilla::Unused << props->GetPropertyAsBool(
12217 u"docshell.needToAddURIVisit"_ns, &needToAddURIVisit);
12218 }
12219
12220 return needToAddURIVisit;
12221}
12222
12223/* static */ void nsDocShell::ExtractLastVisit(
12224 nsIChannel* aChannel, nsIURI** aURI, uint32_t* aChannelRedirectFlags) {
12225 nsCOMPtr<nsIPropertyBag2> props(do_QueryInterface(aChannel));
12226 if (!props) {
12227 return;
12228 }
12229
12230 nsresult rv;
12231 nsCOMPtr<nsIURI> uri(do_GetProperty(props, u"docshell.previousURI"_ns, &rv));
12232 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
12233 uri.forget(aURI);
12234
12235 rv = props->GetPropertyAsUint32(u"docshell.previousFlags"_ns,
12236 aChannelRedirectFlags);
12237
12238 NS_WARNING_ASSERTION(do { if (!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1
))))) { NS_DebugBreak(NS_DEBUG_WARNING, "Could not fetch previous flags, URI will be treated like referrer"
, "NS_SUCCEEDED(rv)", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 12240); } } while (false)
12239 NS_SUCCEEDED(rv),do { if (!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1
))))) { NS_DebugBreak(NS_DEBUG_WARNING, "Could not fetch previous flags, URI will be treated like referrer"
, "NS_SUCCEEDED(rv)", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 12240); } } while (false)
12240 "Could not fetch previous flags, URI will be treated like referrer")do { if (!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1
))))) { NS_DebugBreak(NS_DEBUG_WARNING, "Could not fetch previous flags, URI will be treated like referrer"
, "NS_SUCCEEDED(rv)", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 12240); } } while (false)
;
12241
12242 } else {
12243 // There is no last visit for this channel, so this must be the first
12244 // link. Link the visit to the referrer of this request, if any.
12245 // Treat referrer as null if there is an error getting it.
12246 NS_GetReferrerFromChannel(aChannel, aURI);
12247 }
12248}
12249
12250void nsDocShell::SaveLastVisit(nsIChannel* aChannel, nsIURI* aURI,
12251 uint32_t aChannelRedirectFlags) {
12252 nsCOMPtr<nsIWritablePropertyBag2> props(do_QueryInterface(aChannel));
12253 if (!props || !aURI) {
12254 return;
12255 }
12256
12257 props->SetPropertyAsInterface(u"docshell.previousURI"_ns, aURI);
12258 props->SetPropertyAsUint32(u"docshell.previousFlags"_ns,
12259 aChannelRedirectFlags);
12260}
12261
12262/* static */ void nsDocShell::InternalAddURIVisit(
12263 nsIURI* aURI, nsIURI* aPreviousURI, uint32_t aChannelRedirectFlags,
12264 uint32_t aResponseStatus, BrowsingContext* aBrowsingContext,
12265 nsIWidget* aWidget, uint32_t aLoadType, bool aWasUpgraded) {
12266 MOZ_ASSERT(aURI, "Visited URI is null!")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aURI)>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(aURI))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("aURI" " (" "Visited URI is null!"
")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 12266); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aURI" ") ("
"Visited URI is null!" ")"); do { *((volatile int*)__null) =
12266; __attribute__((nomerge)) ::abort(); } while (false); }
} while (false)
;
12267 MOZ_ASSERT(aLoadType != LOAD_ERROR_PAGE && aLoadType != LOAD_BYPASS_HISTORY,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aLoadType != LOAD_ERROR_PAGE && aLoadType !=
LOAD_BYPASS_HISTORY)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aLoadType != LOAD_ERROR_PAGE
&& aLoadType != LOAD_BYPASS_HISTORY))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("aLoadType != LOAD_ERROR_PAGE && aLoadType != LOAD_BYPASS_HISTORY"
" (" "Do not add error or bypass pages to global history" ")"
, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 12268); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadType != LOAD_ERROR_PAGE && aLoadType != LOAD_BYPASS_HISTORY"
") (" "Do not add error or bypass pages to global history" ")"
); do { *((volatile int*)__null) = 12268; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
12268 "Do not add error or bypass pages to global history")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aLoadType != LOAD_ERROR_PAGE && aLoadType !=
LOAD_BYPASS_HISTORY)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aLoadType != LOAD_ERROR_PAGE
&& aLoadType != LOAD_BYPASS_HISTORY))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("aLoadType != LOAD_ERROR_PAGE && aLoadType != LOAD_BYPASS_HISTORY"
" (" "Do not add error or bypass pages to global history" ")"
, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 12268); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadType != LOAD_ERROR_PAGE && aLoadType != LOAD_BYPASS_HISTORY"
") (" "Do not add error or bypass pages to global history" ")"
); do { *((volatile int*)__null) = 12268; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
12269
12270 bool usePrivateBrowsing = false;
12271 aBrowsingContext->GetUsePrivateBrowsing(&usePrivateBrowsing);
12272
12273 // Only content-type docshells save URI visits. Also don't do
12274 // anything here if we're not supposed to use global history.
12275 if (!aBrowsingContext->IsContent() ||
12276 !aBrowsingContext->GetUseGlobalHistory() || usePrivateBrowsing) {
12277 return;
12278 }
12279
12280 nsCOMPtr<IHistory> history = components::History::Service();
12281
12282 if (history) {
12283 uint32_t visitURIFlags = 0;
12284
12285 if (aBrowsingContext->IsTop()) {
12286 visitURIFlags |= IHistory::TOP_LEVEL;
12287 }
12288
12289 if (aChannelRedirectFlags & nsIChannelEventSink::REDIRECT_TEMPORARY) {
12290 visitURIFlags |= IHistory::REDIRECT_TEMPORARY;
12291 } else if (aChannelRedirectFlags &
12292 nsIChannelEventSink::REDIRECT_PERMANENT) {
12293 visitURIFlags |= IHistory::REDIRECT_PERMANENT;
12294 } else {
12295 MOZ_ASSERT(!aChannelRedirectFlags,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aChannelRedirectFlags)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!aChannelRedirectFlags))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("!aChannelRedirectFlags"
" (" "One of REDIRECT_TEMPORARY or REDIRECT_PERMANENT must be set "
"if any flags in aChannelRedirectFlags is set." ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 12297); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aChannelRedirectFlags"
") (" "One of REDIRECT_TEMPORARY or REDIRECT_PERMANENT must be set "
"if any flags in aChannelRedirectFlags is set." ")"); do { *
((volatile int*)__null) = 12297; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
12296 "One of REDIRECT_TEMPORARY or REDIRECT_PERMANENT must be set "do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aChannelRedirectFlags)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!aChannelRedirectFlags))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("!aChannelRedirectFlags"
" (" "One of REDIRECT_TEMPORARY or REDIRECT_PERMANENT must be set "
"if any flags in aChannelRedirectFlags is set." ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 12297); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aChannelRedirectFlags"
") (" "One of REDIRECT_TEMPORARY or REDIRECT_PERMANENT must be set "
"if any flags in aChannelRedirectFlags is set." ")"); do { *
((volatile int*)__null) = 12297; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
12297 "if any flags in aChannelRedirectFlags is set.")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aChannelRedirectFlags)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!aChannelRedirectFlags))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("!aChannelRedirectFlags"
" (" "One of REDIRECT_TEMPORARY or REDIRECT_PERMANENT must be set "
"if any flags in aChannelRedirectFlags is set." ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 12297); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aChannelRedirectFlags"
") (" "One of REDIRECT_TEMPORARY or REDIRECT_PERMANENT must be set "
"if any flags in aChannelRedirectFlags is set." ")"); do { *
((volatile int*)__null) = 12297; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
;
12298 }
12299
12300 if (aResponseStatus >= 300 && aResponseStatus < 400) {
12301 visitURIFlags |= IHistory::REDIRECT_SOURCE;
12302 if (aResponseStatus == 301 || aResponseStatus == 308) {
12303 visitURIFlags |= IHistory::REDIRECT_SOURCE_PERMANENT;
12304 }
12305 }
12306 // Errors 400-501 and 505 are considered unrecoverable, in the sense a
12307 // simple retry attempt by the user is unlikely to solve them.
12308 // 408 is special cased, since may actually indicate a temporary
12309 // connection problem.
12310 else if (aResponseStatus != 408 &&
12311 ((aResponseStatus >= 400 && aResponseStatus <= 501) ||
12312 aResponseStatus == 505)) {
12313 visitURIFlags |= IHistory::UNRECOVERABLE_ERROR;
12314 }
12315
12316 if (aWasUpgraded) {
12317 visitURIFlags |=
12318 IHistory::REDIRECT_SOURCE | IHistory::REDIRECT_SOURCE_UPGRADED;
12319 }
12320
12321 mozilla::Unused << history->VisitURI(aWidget, aURI, aPreviousURI,
12322 visitURIFlags,
12323 aBrowsingContext->BrowserId());
12324 }
12325}
12326
12327void nsDocShell::AddURIVisit(nsIURI* aURI, nsIURI* aPreviousURI,
12328 uint32_t aChannelRedirectFlags,
12329 uint32_t aResponseStatus) {
12330 nsPIDOMWindowOuter* outer = GetWindow();
12331 nsCOMPtr<nsIWidget> widget = widget::WidgetUtils::DOMWindowToWidget(outer);
12332
12333 InternalAddURIVisit(aURI, aPreviousURI, aChannelRedirectFlags,
12334 aResponseStatus, mBrowsingContext, widget, mLoadType,
12335 false);
12336}
12337
12338//*****************************************************************************
12339// nsDocShell: Helper Routines
12340//*****************************************************************************
12341
12342NS_IMETHODIMPnsresult
12343nsDocShell::SetLoadType(uint32_t aLoadType) {
12344 mLoadType = aLoadType;
12345 return NS_OK;
12346}
12347
12348NS_IMETHODIMPnsresult
12349nsDocShell::GetLoadType(uint32_t* aLoadType) {
12350 *aLoadType = mLoadType;
12351 return NS_OK;
12352}
12353
12354nsresult nsDocShell::ConfirmRepost(bool* aRepost) {
12355 if (StaticPrefs::dom_confirm_repost_testing_always_accept()) {
12356 *aRepost = true;
12357 return NS_OK;
12358 }
12359
12360 nsCOMPtr<nsIPromptCollection> prompter =
12361 do_GetService("@mozilla.org/embedcomp/prompt-collection;1");
12362 if (!prompter) {
12363 return NS_ERROR_NOT_AVAILABLE;
12364 }
12365
12366 return prompter->ConfirmRepost(mBrowsingContext, aRepost);
12367}
12368
12369nsresult nsDocShell::GetPromptAndStringBundle(nsIPrompt** aPrompt,
12370 nsIStringBundle** aStringBundle) {
12371 NS_ENSURE_SUCCESS(GetInterface(NS_GET_IID(nsIPrompt), (void**)aPrompt),do { nsresult __rv = GetInterface((nsIPrompt::COMTypeInfo<
nsIPrompt, void>::kIID), (void**)aPrompt); 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", "GetInterface((nsIPrompt::COMTypeInfo<nsIPrompt, void>::kIID), (void**)aPrompt)"
, "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/docshell/base/nsDocShell.cpp"
, 12372); return NS_ERROR_FAILURE; } } while (false)
12372 NS_ERROR_FAILURE)do { nsresult __rv = GetInterface((nsIPrompt::COMTypeInfo<
nsIPrompt, void>::kIID), (void**)aPrompt); 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", "GetInterface((nsIPrompt::COMTypeInfo<nsIPrompt, void>::kIID), (void**)aPrompt)"
, "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/docshell/base/nsDocShell.cpp"
, 12372); return NS_ERROR_FAILURE; } } while (false)
;
12373
12374 nsCOMPtr<nsIStringBundleService> stringBundleService =
12375 mozilla::components::StringBundle::Service();
12376 NS_ENSURE_TRUE(stringBundleService, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(stringBundleService)), 0))) {
NS_DebugBreak(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "stringBundleService"
") failed", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 12376); return NS_ERROR_FAILURE; } } while (false)
;
12377
12378 NS_ENSURE_SUCCESS(do { nsresult __rv = stringBundleService->CreateBundle(kAppstringsBundleURL
, aStringBundle); 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", "stringBundleService->CreateBundle(kAppstringsBundleURL, aStringBundle)"
, "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/docshell/base/nsDocShell.cpp"
, 12380); return NS_ERROR_FAILURE; } } while (false)
12379 stringBundleService->CreateBundle(kAppstringsBundleURL, aStringBundle),do { nsresult __rv = stringBundleService->CreateBundle(kAppstringsBundleURL
, aStringBundle); 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", "stringBundleService->CreateBundle(kAppstringsBundleURL, aStringBundle)"
, "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/docshell/base/nsDocShell.cpp"
, 12380); return NS_ERROR_FAILURE; } } while (false)
12380 NS_ERROR_FAILURE)do { nsresult __rv = stringBundleService->CreateBundle(kAppstringsBundleURL
, aStringBundle); 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", "stringBundleService->CreateBundle(kAppstringsBundleURL, aStringBundle)"
, "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/docshell/base/nsDocShell.cpp"
, 12380); return NS_ERROR_FAILURE; } } while (false)
;
12381
12382 return NS_OK;
12383}
12384
12385ScrollContainerFrame* nsDocShell::GetRootScrollContainerFrame() {
12386 PresShell* presShell = GetPresShell();
12387 NS_ENSURE_TRUE(presShell, nullptr)do { if ((__builtin_expect(!!(!(presShell)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "presShell" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 12387); return nullptr; } } while (false)
;
12388
12389 return presShell->GetRootScrollContainerFrame();
12390}
12391
12392nsresult nsDocShell::EnsureScriptEnvironment() {
12393 if (mScriptGlobal) {
12394 return NS_OK;
12395 }
12396
12397 if (mIsBeingDestroyed) {
12398 return NS_ERROR_NOT_AVAILABLE;
12399 }
12400
12401#ifdef DEBUG1
12402 NS_ASSERTION(!mInEnsureScriptEnv,do { if (!(!mInEnsureScriptEnv)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "Infinite loop! Calling EnsureScriptEnvironment() from " "within EnsureScriptEnvironment()!"
, "!mInEnsureScriptEnv", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 12404); MOZ_PretendNoReturn(); } } while (0)
12403 "Infinite loop! Calling EnsureScriptEnvironment() from "do { if (!(!mInEnsureScriptEnv)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "Infinite loop! Calling EnsureScriptEnvironment() from " "within EnsureScriptEnvironment()!"
, "!mInEnsureScriptEnv", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 12404); MOZ_PretendNoReturn(); } } while (0)
12404 "within EnsureScriptEnvironment()!")do { if (!(!mInEnsureScriptEnv)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "Infinite loop! Calling EnsureScriptEnvironment() from " "within EnsureScriptEnvironment()!"
, "!mInEnsureScriptEnv", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 12404); MOZ_PretendNoReturn(); } } while (0)
;
12405
12406 // Yeah, this isn't re-entrant safe, but that's ok since if we
12407 // re-enter this method, we'll infinitely loop...
12408 AutoRestore<bool> boolSetter(mInEnsureScriptEnv);
12409 mInEnsureScriptEnv = true;
12410#endif
12411
12412 nsCOMPtr<nsIWebBrowserChrome> browserChrome(do_GetInterface(mTreeOwner));
12413 NS_ENSURE_TRUE(browserChrome, NS_ERROR_NOT_AVAILABLE)do { if ((__builtin_expect(!!(!(browserChrome)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "browserChrome" ") failed"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 12413); return NS_ERROR_NOT_AVAILABLE; } } while (false)
;
12414
12415 uint32_t chromeFlags;
12416 browserChrome->GetChromeFlags(&chromeFlags);
12417
12418 // If our window is modal and we're not opened as chrome, make
12419 // this window a modal content window.
12420 mScriptGlobal = nsGlobalWindowOuter::Create(this, mItemType == typeChrome);
12421 MOZ_ASSERT(mScriptGlobal)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mScriptGlobal)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mScriptGlobal))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("mScriptGlobal",
"/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 12421); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mScriptGlobal"
")"); do { *((volatile int*)__null) = 12421; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12422
12423 // Ensure the script object is set up to run script.
12424 return mScriptGlobal->EnsureScriptEnvironment();
12425}
12426
12427nsresult nsDocShell::EnsureEditorData() {
12428 MOZ_ASSERT(!mIsBeingDestroyed)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mIsBeingDestroyed)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mIsBeingDestroyed))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("!mIsBeingDestroyed"
, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 12428); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mIsBeingDestroyed"
")"); do { *((volatile int*)__null) = 12428; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12429
12430 bool openDocHasDetachedEditor = mOSHE && mOSHE->HasDetachedEditor();
12431 if (!mEditorData && !mIsBeingDestroyed && !openDocHasDetachedEditor) {
12432 // We shouldn't recreate the editor data if it already exists, or
12433 // we're shutting down, or we already have a detached editor data
12434 // stored in the session history. We should only have one editordata
12435 // per docshell.
12436 mEditorData = MakeUnique<nsDocShellEditorData>(this);
12437 }
12438
12439 return mEditorData ? NS_OK : NS_ERROR_NOT_AVAILABLE;
12440}
12441
12442nsresult nsDocShell::EnsureFind() {
12443 if (!mFind) {
12444 mFind = new nsWebBrowserFind();
12445 }
12446
12447 // we promise that the nsIWebBrowserFind that we return has been set
12448 // up to point to the focused, or content window, so we have to
12449 // set that up each time.
12450
12451 nsIScriptGlobalObject* scriptGO = GetScriptGlobalObject();
12452 NS_ENSURE_TRUE(scriptGO, NS_ERROR_UNEXPECTED)do { if ((__builtin_expect(!!(!(scriptGO)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "scriptGO" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 12452); return NS_ERROR_UNEXPECTED; } } while (false)
;
12453
12454 // default to our window
12455 nsCOMPtr<nsPIDOMWindowOuter> ourWindow = do_QueryInterface(scriptGO);
12456 nsCOMPtr<nsPIDOMWindowOuter> windowToSearch;
12457 nsFocusManager::GetFocusedDescendant(ourWindow,
12458 nsFocusManager::eIncludeAllDescendants,
12459 getter_AddRefs(windowToSearch));
12460
12461 nsCOMPtr<nsIWebBrowserFindInFrames> findInFrames = do_QueryInterface(mFind);
12462 if (!findInFrames) {
12463 return NS_ERROR_NO_INTERFACE;
12464 }
12465
12466 nsresult rv = findInFrames->SetRootSearchFrame(ourWindow);
12467 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
12468 return rv;
12469 }
12470 rv = findInFrames->SetCurrentSearchFrame(windowToSearch);
12471 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
12472 return rv;
12473 }
12474
12475 return NS_OK;
12476}
12477
12478NS_IMETHODIMPnsresult
12479nsDocShell::IsBeingDestroyed(bool* aDoomed) {
12480 NS_ENSURE_ARG(aDoomed)do { if ((__builtin_expect(!!(!(aDoomed)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aDoomed" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 12480); return NS_ERROR_INVALID_ARG; } } while (false)
;
12481 *aDoomed = mIsBeingDestroyed;
12482 return NS_OK;
12483}
12484
12485NS_IMETHODIMPnsresult
12486nsDocShell::GetIsExecutingOnLoadHandler(bool* aResult) {
12487 NS_ENSURE_ARG(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/docshell/base/nsDocShell.cpp"
, 12487); return NS_ERROR_INVALID_ARG; } } while (false)
;
12488 *aResult = mIsExecutingOnLoadHandler;
12489 return NS_OK;
12490}
12491
12492NS_IMETHODIMPnsresult
12493nsDocShell::GetLayoutHistoryState(nsILayoutHistoryState** aLayoutHistoryState) {
12494 nsCOMPtr<nsILayoutHistoryState> state;
12495 if (mozilla::SessionHistoryInParent()) {
12496 if (mActiveEntry) {
12497 state = mActiveEntry->GetLayoutHistoryState();
12498 }
12499 } else {
12500 if (mOSHE) {
12501 state = mOSHE->GetLayoutHistoryState();
12502 }
12503 }
12504 state.forget(aLayoutHistoryState);
12505 return NS_OK;
12506}
12507
12508NS_IMETHODIMPnsresult
12509nsDocShell::SetLayoutHistoryState(nsILayoutHistoryState* aLayoutHistoryState) {
12510 if (mOSHE) {
12511 mOSHE->SetLayoutHistoryState(aLayoutHistoryState);
12512 }
12513 if (mActiveEntry) {
12514 mActiveEntry->SetLayoutHistoryState(aLayoutHistoryState);
12515 }
12516 return NS_OK;
12517}
12518
12519nsDocShell::InterfaceRequestorProxy::InterfaceRequestorProxy(
12520 nsIInterfaceRequestor* aRequestor) {
12521 if (aRequestor) {
12522 mWeakPtr = do_GetWeakReference(aRequestor);
12523 }
12524}
12525
12526nsDocShell::InterfaceRequestorProxy::~InterfaceRequestorProxy() {
12527 mWeakPtr = nullptr;
12528}
12529
12530NS_IMPL_ISUPPORTS(nsDocShell::InterfaceRequestorProxy, nsIInterfaceRequestor)MozExternalRefCountType nsDocShell::InterfaceRequestorProxy::
AddRef(void) { static_assert(!std::is_destructible_v<nsDocShell
::InterfaceRequestorProxy>, "Reference-counted class " "nsDocShell::InterfaceRequestorProxy"
" 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/docshell/base/nsDocShell.cpp"
, 12530); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { *((volatile int*)__null) =
12530; __attribute__((nomerge)) ::abort(); } while (false); }
} while (false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("nsDocShell::InterfaceRequestorProxy" != nullptr
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!("nsDocShell::InterfaceRequestorProxy" != nullptr))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("\"nsDocShell::InterfaceRequestorProxy\" != nullptr"
" (" "Must specify a name" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 12530); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"nsDocShell::InterfaceRequestorProxy\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 12530; __attribute__((nomerge)) ::abort(); } while (false
); } } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread
.AssertOwnership("nsDocShell::InterfaceRequestorProxy" " not thread-safe"
); nsrefcnt count = ++mRefCnt; NS_LogAddRef((this), (count), (
"nsDocShell::InterfaceRequestorProxy"), (uint32_t)(sizeof(*this
))); return count; } MozExternalRefCountType nsDocShell::InterfaceRequestorProxy
::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/docshell/base/nsDocShell.cpp"
, 12530); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { *((volatile int*)__null) = 12530
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("nsDocShell::InterfaceRequestorProxy" != nullptr
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!("nsDocShell::InterfaceRequestorProxy" != nullptr))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("\"nsDocShell::InterfaceRequestorProxy\" != nullptr"
" (" "Must specify a name" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 12530); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"nsDocShell::InterfaceRequestorProxy\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 12530; __attribute__((nomerge)) ::abort(); } while (false
); } } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread
.AssertOwnership("nsDocShell::InterfaceRequestorProxy" " not thread-safe"
); const char* const nametmp = "nsDocShell::InterfaceRequestorProxy"
; nsrefcnt count = --mRefCnt; NS_LogRelease((this), (count), (
nametmp)); if (count == 0) { mRefCnt = 1; delete (this); return
0; } return count; } nsresult nsDocShell::InterfaceRequestorProxy
::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/docshell/base/nsDocShell.cpp"
, 12530); 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<nsDocShell::InterfaceRequestorProxy, nsIInterfaceRequestor
>, int32_t( reinterpret_cast<char*>(static_cast<nsIInterfaceRequestor
*>((nsDocShell::InterfaceRequestorProxy*)0x1000)) - reinterpret_cast
<char*>((nsDocShell::InterfaceRequestorProxy*)0x1000))}
, {&mozilla::detail::kImplementedIID<nsDocShell::InterfaceRequestorProxy
, nsISupports>, int32_t(reinterpret_cast<char*>(static_cast
<nsISupports*>( static_cast<nsIInterfaceRequestor*>
((nsDocShell::InterfaceRequestorProxy*)0x1000))) - reinterpret_cast
<char*>((nsDocShell::InterfaceRequestorProxy*)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; }
12531
12532NS_IMETHODIMPnsresult
12533nsDocShell::InterfaceRequestorProxy::GetInterface(const nsIID& aIID,
12534 void** aSink) {
12535 NS_ENSURE_ARG_POINTER(aSink)do { if ((__builtin_expect(!!(!(aSink)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aSink" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 12535); return NS_ERROR_INVALID_POINTER; } } while (false)
;
12536 nsCOMPtr<nsIInterfaceRequestor> ifReq = do_QueryReferent(mWeakPtr);
12537 if (ifReq) {
12538 return ifReq->GetInterface(aIID, aSink);
12539 }
12540 *aSink = nullptr;
12541 return NS_NOINTERFACE;
12542}
12543
12544//*****************************************************************************
12545// nsDocShell::nsIAuthPromptProvider
12546//*****************************************************************************
12547
12548NS_IMETHODIMPnsresult
12549nsDocShell::GetAuthPrompt(uint32_t aPromptReason, const nsIID& aIID,
12550 void** aResult) {
12551 // a priority prompt request will override a false mAllowAuth setting
12552 bool priorityPrompt = (aPromptReason == PROMPT_PROXY);
12553
12554 if (!mAllowAuth && !priorityPrompt) {
12555 return NS_ERROR_NOT_AVAILABLE;
12556 }
12557
12558 // we're either allowing auth, or it's a proxy request
12559 nsresult rv;
12560 nsCOMPtr<nsIPromptFactory> wwatch =
12561 do_GetService(NS_WINDOWWATCHER_CONTRACTID"@mozilla.org/embedcomp/window-watcher;1", &rv);
12562 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/docshell/base/nsDocShell.cpp"
, 12562); return rv; } } while (false)
;
12563
12564 rv = EnsureScriptEnvironment();
12565 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/docshell/base/nsDocShell.cpp"
, 12565); return rv; } } while (false)
;
12566
12567 // Get the an auth prompter for our window so that the parenting
12568 // of the dialogs works as it should when using tabs.
12569
12570 return wwatch->GetPrompt(mScriptGlobal, aIID,
12571 reinterpret_cast<void**>(aResult));
12572}
12573
12574//*****************************************************************************
12575// nsDocShell::nsILoadContext
12576//*****************************************************************************
12577
12578NS_IMETHODIMPnsresult
12579nsDocShell::GetAssociatedWindow(mozIDOMWindowProxy** aWindow) {
12580 CallGetInterface(this, aWindow);
12581 return NS_OK;
12582}
12583
12584NS_IMETHODIMPnsresult
12585nsDocShell::GetTopWindow(mozIDOMWindowProxy** aWindow) {
12586 return mBrowsingContext->GetTopWindow(aWindow);
12587}
12588
12589NS_IMETHODIMPnsresult
12590nsDocShell::GetTopFrameElement(Element** aElement) {
12591 return mBrowsingContext->GetTopFrameElement(aElement);
12592}
12593
12594NS_IMETHODIMPnsresult
12595nsDocShell::GetUseTrackingProtection(bool* aUseTrackingProtection) {
12596 return mBrowsingContext->GetUseTrackingProtection(aUseTrackingProtection);
12597}
12598
12599NS_IMETHODIMPnsresult
12600nsDocShell::SetUseTrackingProtection(bool aUseTrackingProtection) {
12601 return mBrowsingContext->SetUseTrackingProtection(aUseTrackingProtection);
12602}
12603
12604NS_IMETHODIMPnsresult
12605nsDocShell::GetIsContent(bool* aIsContent) {
12606 *aIsContent = (mItemType == typeContent);
12607 return NS_OK;
12608}
12609
12610bool nsDocShell::IsOKToLoadURI(nsIURI* aURI) {
12611 MOZ_ASSERT(aURI, "Must have a URI!")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aURI)>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(aURI))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("aURI" " (" "Must have a URI!" ")"
, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 12611); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aURI" ") ("
"Must have a URI!" ")"); do { *((volatile int*)__null) = 12611
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
;
12612
12613 if (!mFiredUnloadEvent) {
12614 return true;
12615 }
12616
12617 if (!mLoadingURI) {
12618 return false;
12619 }
12620
12621 bool isPrivateWin = false;
12622 Document* doc = GetDocument();
12623 if (doc) {
12624 isPrivateWin =
12625 doc->NodePrincipal()->OriginAttributesRef().IsPrivateBrowsing();
12626 }
12627
12628 nsCOMPtr<nsIScriptSecurityManager> secMan =
12629 do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID"@mozilla.org/scriptsecuritymanager;1");
12630 return secMan && NS_SUCCEEDED(secMan->CheckSameOriginURI(((bool)(__builtin_expect(!!(!NS_FAILED_impl(secMan->CheckSameOriginURI
( aURI, mLoadingURI, false, isPrivateWin))), 1)))
12631 aURI, mLoadingURI, false, isPrivateWin))((bool)(__builtin_expect(!!(!NS_FAILED_impl(secMan->CheckSameOriginURI
( aURI, mLoadingURI, false, isPrivateWin))), 1)))
;
12632}
12633
12634//
12635// Routines for selection and clipboard
12636//
12637nsresult nsDocShell::GetControllerForCommand(const char* aCommand,
12638 nsIController** aResult) {
12639 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/docshell/base/nsDocShell.cpp"
, 12639); return NS_ERROR_INVALID_POINTER; } } while (false)
;
12640 *aResult = nullptr;
12641
12642 NS_ENSURE_TRUE(mScriptGlobal, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(mScriptGlobal)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "mScriptGlobal" ") failed"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 12642); return NS_ERROR_FAILURE; } } while (false)
;
12643
12644 nsCOMPtr<nsPIWindowRoot> root = mScriptGlobal->GetTopWindowRoot();
12645 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/docshell/base/nsDocShell.cpp"
, 12645); return NS_ERROR_FAILURE; } } while (false)
;
12646
12647 return root->GetControllerForCommand(aCommand, false /* for any window */,
12648 aResult);
12649}
12650
12651NS_IMETHODIMPnsresult
12652nsDocShell::IsCommandEnabled(const char* aCommand, bool* aResult) {
12653 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/docshell/base/nsDocShell.cpp"
, 12653); return NS_ERROR_INVALID_POINTER; } } while (false)
;
12654 *aResult = false;
12655
12656 nsresult rv = NS_ERROR_FAILURE;
12657
12658 nsCOMPtr<nsIController> controller;
12659 rv = GetControllerForCommand(aCommand, getter_AddRefs(controller));
12660 if (controller) {
12661 rv = controller->IsCommandEnabled(aCommand, aResult);
12662 }
12663
12664 return rv;
12665}
12666
12667NS_IMETHODIMPnsresult
12668nsDocShell::DoCommand(const char* aCommand) {
12669 nsresult rv = NS_ERROR_FAILURE;
12670
12671 nsCOMPtr<nsIController> controller;
12672 rv = GetControllerForCommand(aCommand, getter_AddRefs(controller));
12673 if (controller) {
12674 rv = controller->DoCommand(aCommand);
12675 }
12676
12677 return rv;
12678}
12679
12680NS_IMETHODIMPnsresult
12681nsDocShell::DoCommandWithParams(const char* aCommand,
12682 nsICommandParams* aParams) {
12683 nsCOMPtr<nsIController> controller;
12684 nsresult rv = GetControllerForCommand(aCommand, getter_AddRefs(controller));
12685 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/docshell/base/nsDocShell.cpp"
, 12685)
) {
12686 return rv;
12687 }
12688
12689 nsCOMPtr<nsICommandController> commandController =
12690 do_QueryInterface(controller, &rv);
12691 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/docshell/base/nsDocShell.cpp"
, 12691)
) {
12692 return rv;
12693 }
12694
12695 return commandController->DoCommandWithParams(aCommand, aParams);
12696}
12697
12698nsresult nsDocShell::EnsureCommandHandler() {
12699 if (!mCommandManager) {
12700 if (nsCOMPtr<nsPIDOMWindowOuter> domWindow = GetWindow()) {
12701 mCommandManager = new nsCommandManager(domWindow);
12702 }
12703 }
12704 return mCommandManager ? NS_OK : NS_ERROR_FAILURE;
12705}
12706
12707// link handling
12708
12709class OnLinkClickEvent : public Runnable {
12710 public:
12711 OnLinkClickEvent(nsDocShell* aHandler, nsIContent* aContent,
12712 nsDocShellLoadState* aLoadState, bool aNoOpenerImplied,
12713 bool aIsTrusted, nsIPrincipal* aTriggeringPrincipal);
12714
12715 NS_IMETHODvirtual nsresult Run() override {
12716 // We need to set up an AutoJSAPI here for the following reason: When we
12717 // do OnLinkClickSync we'll eventually end up in
12718 // nsGlobalWindow::OpenInternal which only does popup blocking if
12719 // !LegacyIsCallerChromeOrNativeCode(). So we need to fake things so that
12720 // we don't look like native code as far as LegacyIsCallerNativeCode() is
12721 // concerned.
12722 AutoJSAPI jsapi;
12723 if (mIsTrusted || jsapi.Init(mContent->OwnerDoc()->GetScopeObject())) {
12724 mHandler->OnLinkClickSync(mContent, mLoadState, mNoOpenerImplied,
12725 mTriggeringPrincipal);
12726 }
12727 return NS_OK;
12728 }
12729
12730 private:
12731 RefPtr<nsDocShell> mHandler;
12732 nsCOMPtr<nsIContent> mContent;
12733 RefPtr<nsDocShellLoadState> mLoadState;
12734 nsCOMPtr<nsIPrincipal> mTriggeringPrincipal;
12735 bool mNoOpenerImplied;
12736 bool mIsTrusted;
12737};
12738
12739OnLinkClickEvent::OnLinkClickEvent(nsDocShell* aHandler, nsIContent* aContent,
12740 nsDocShellLoadState* aLoadState,
12741 bool aNoOpenerImplied, bool aIsTrusted,
12742 nsIPrincipal* aTriggeringPrincipal)
12743 : mozilla::Runnable("OnLinkClickEvent"),
12744 mHandler(aHandler),
12745 mContent(aContent),
12746 mLoadState(aLoadState),
12747 mTriggeringPrincipal(aTriggeringPrincipal),
12748 mNoOpenerImplied(aNoOpenerImplied),
12749 mIsTrusted(aIsTrusted) {}
12750
12751nsresult nsDocShell::OnLinkClick(
12752 nsIContent* aContent, nsIURI* aURI, const nsAString& aTargetSpec,
12753 const nsAString& aFileName, nsIInputStream* aPostDataStream,
12754 nsIInputStream* aHeadersDataStream, bool aIsUserTriggered, bool aIsTrusted,
12755 nsIPrincipal* aTriggeringPrincipal, nsIContentSecurityPolicy* aCsp) {
12756#ifndef ANDROID
12757 MOZ_ASSERT(aTriggeringPrincipal, "Need a valid triggeringPrincipal")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aTriggeringPrincipal)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aTriggeringPrincipal))), 0))
) { do { } while (false); MOZ_ReportAssertionFailure("aTriggeringPrincipal"
" (" "Need a valid triggeringPrincipal" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 12757); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aTriggeringPrincipal"
") (" "Need a valid triggeringPrincipal" ")"); do { *((volatile
int*)__null) = 12757; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
12758#endif
12759 NS_ASSERTION(NS_IsMainThread(), "wrong thread")do { if (!(NS_IsMainThread())) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "wrong thread", "NS_IsMainThread()", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 12759); MOZ_PretendNoReturn(); } } while (0)
;
12760
12761 if (!IsNavigationAllowed() || !IsOKToLoadURI(aURI)) {
12762 return NS_OK;
12763 }
12764
12765 // On history navigation through Back/Forward buttons, don't execute
12766 // automatic JavaScript redirection such as |anchorElement.click()| or
12767 // |formElement.submit()|.
12768 //
12769 // XXX |formElement.submit()| bypasses this checkpoint because it calls
12770 // nsDocShell::OnLinkClickSync(...) instead.
12771 if (ShouldBlockLoadingForBackButton()) {
12772 return NS_OK;
12773 }
12774
12775 if (aContent->IsEditable()) {
12776 return NS_OK;
12777 }
12778
12779 Document* ownerDoc = aContent->OwnerDoc();
12780 if (nsContentUtils::IsExternalProtocol(aURI)) {
12781 ownerDoc->EnsureNotEnteringAndExitFullscreen();
12782 }
12783
12784 bool noOpenerImplied = false;
12785 nsAutoString target(aTargetSpec);
12786 if (aFileName.IsVoid() &&
12787 ShouldOpenInBlankTarget(aTargetSpec, aURI, aContent, aIsUserTriggered)) {
12788 target = u"_blank";
12789 if (!aTargetSpec.Equals(target)) {
12790 noOpenerImplied = true;
12791 }
12792 }
12793
12794 RefPtr<nsDocShellLoadState> loadState = new nsDocShellLoadState(aURI);
12795 loadState->SetTarget(target);
12796 loadState->SetFileName(aFileName);
12797 loadState->SetPostDataStream(aPostDataStream);
12798 loadState->SetHeadersStream(aHeadersDataStream);
12799 loadState->SetFirstParty(true);
12800 loadState->SetTriggeringPrincipal(
12801 aTriggeringPrincipal ? aTriggeringPrincipal : aContent->NodePrincipal());
12802 loadState->SetPrincipalToInherit(aContent->NodePrincipal());
12803 loadState->SetCsp(aCsp ? aCsp : aContent->GetCsp());
12804 loadState->SetAllowFocusMove(UserActivation::IsHandlingUserInput());
12805
12806 const bool hasValidUserGestureActivation =
12807 ownerDoc->HasValidTransientUserGestureActivation();
12808 loadState->SetHasValidUserGestureActivation(hasValidUserGestureActivation);
12809 loadState->SetTextDirectiveUserActivation(
12810 ownerDoc->ConsumeTextDirectiveUserActivation() ||
12811 hasValidUserGestureActivation);
12812
12813 nsCOMPtr<nsIRunnable> ev =
12814 new OnLinkClickEvent(this, aContent, loadState, noOpenerImplied,
12815 aIsTrusted, aTriggeringPrincipal);
12816 return Dispatch(ev.forget());
12817}
12818
12819bool nsDocShell::ShouldOpenInBlankTarget(const nsAString& aOriginalTarget,
12820 nsIURI* aLinkURI, nsIContent* aContent,
12821 bool aIsUserTriggered) {
12822 if (net::SchemeIsJavascript(aLinkURI)) {
12823 return false;
12824 }
12825
12826 // External links from within app tabs should always open in new tabs
12827 // instead of replacing the app tab's page (Bug 575561)
12828 // nsIURI.host can throw for non-nsStandardURL nsIURIs. If we fail to
12829 // get either host, just return false to use the original target.
12830 nsAutoCString linkHost;
12831 if (NS_FAILED(aLinkURI->GetHost(linkHost))((bool)(__builtin_expect(!!(NS_FAILED_impl(aLinkURI->GetHost
(linkHost))), 0)))
) {
12832 return false;
12833 }
12834
12835 // The targetTopLevelLinkClicksToBlank property on BrowsingContext allows
12836 // privileged code to change the default targeting behaviour. In particular,
12837 // if a user-initiated link click for the (or targetting the) top-level frame
12838 // is detected, we default the target to "_blank" to give it a new
12839 // top-level BrowsingContext.
12840 if (mBrowsingContext->TargetTopLevelLinkClicksToBlank() && aIsUserTriggered &&
12841 ((aOriginalTarget.IsEmpty() && mBrowsingContext->IsTop()) ||
12842 aOriginalTarget == u"_top"_ns)) {
12843 return true;
12844 }
12845
12846 // Don't modify non-default targets.
12847 if (!aOriginalTarget.IsEmpty()) {
12848 return false;
12849 }
12850
12851 // Only check targets that are in extension panels or app tabs.
12852 // (isAppTab will be false for app tab subframes).
12853 nsString mmGroup = mBrowsingContext->Top()->GetMessageManagerGroup();
12854 if (!mmGroup.EqualsLiteral("webext-browsers") &&
12855 !mBrowsingContext->IsAppTab()) {
12856 return false;
12857 }
12858
12859 nsCOMPtr<nsIURI> docURI = aContent->OwnerDoc()->GetDocumentURIObject();
12860 if (!docURI) {
12861 return false;
12862 }
12863
12864 nsAutoCString docHost;
12865 if (NS_FAILED(docURI->GetHost(docHost))((bool)(__builtin_expect(!!(NS_FAILED_impl(docURI->GetHost
(docHost))), 0)))
) {
12866 return false;
12867 }
12868
12869 if (linkHost.Equals(docHost)) {
12870 return false;
12871 }
12872
12873 // Special case: ignore "www" prefix if it is part of host string
12874 return linkHost.Length() < docHost.Length()
12875 ? !docHost.Equals("www."_ns + linkHost)
12876 : !linkHost.Equals("www."_ns + docHost);
12877}
12878
12879static bool ElementCanHaveNoopener(nsIContent* aContent) {
12880 // Make sure we are dealing with either an <A>, <AREA>, or <FORM> element in
12881 // the HTML, XHTML, or SVG namespace.
12882 return aContent->IsAnyOfHTMLElements(nsGkAtoms::a, nsGkAtoms::area,
12883 nsGkAtoms::form) ||
12884 aContent->IsSVGElement(nsGkAtoms::a);
12885}
12886
12887nsresult nsDocShell::OnLinkClickSync(nsIContent* aContent,
12888 nsDocShellLoadState* aLoadState,
12889 bool aNoOpenerImplied,
12890 nsIPrincipal* aTriggeringPrincipal) {
12891 if (!IsNavigationAllowed() || !IsOKToLoadURI(aLoadState->URI())) {
12892 return NS_OK;
12893 }
12894
12895 // XXX When the linking node was HTMLFormElement, it is synchronous event.
12896 // That is, the caller of this method is not |OnLinkClickEvent::Run()|
12897 // but |HTMLFormElement::SubmitSubmission(...)|.
12898 if (aContent->IsHTMLElement(nsGkAtoms::form) &&
12899 ShouldBlockLoadingForBackButton()) {
12900 return NS_OK;
12901 }
12902
12903 if (aContent->IsEditable()) {
12904 return NS_OK;
12905 }
12906
12907 // if the triggeringPrincipal is not passed explicitly, then we
12908 // fall back to using doc->NodePrincipal() as the triggeringPrincipal.
12909 nsCOMPtr<nsIPrincipal> triggeringPrincipal =
12910 aTriggeringPrincipal ? aTriggeringPrincipal : aContent->NodePrincipal();
12911
12912 {
12913 // defer to an external protocol handler if necessary...
12914 nsCOMPtr<nsIExternalProtocolService> extProtService =
12915 do_GetService(NS_EXTERNALPROTOCOLSERVICE_CONTRACTID"@mozilla.org/uriloader/external-protocol-service;1");
12916 if (extProtService) {
12917 nsAutoCString scheme;
12918 aLoadState->URI()->GetScheme(scheme);
12919 if (!scheme.IsEmpty()) {
12920 // if the URL scheme does not correspond to an exposed protocol, then
12921 // we need to hand this link click over to the external protocol
12922 // handler.
12923 bool isExposed;
12924 nsresult rv =
12925 extProtService->IsExposedProtocol(scheme.get(), &isExposed);
12926 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && !isExposed) {
12927 return extProtService->LoadURI(
12928 aLoadState->URI(), triggeringPrincipal, nullptr, mBrowsingContext,
12929 /* aTriggeredExternally */
12930 false,
12931 /* aHasValidUserGestureActivation */
12932 aContent->OwnerDoc()->HasValidTransientUserGestureActivation(),
12933 /* aNewWindowTarget */ false);
12934 }
12935 }
12936 }
12937 }
12938 uint32_t triggeringSandboxFlags = 0;
12939 uint64_t triggeringWindowId = 0;
12940 bool triggeringStorageAccess = false;
12941 if (mBrowsingContext) {
12942 triggeringSandboxFlags = aContent->OwnerDoc()->GetSandboxFlags();
12943 triggeringWindowId = aContent->OwnerDoc()->InnerWindowID();
12944 triggeringStorageAccess = aContent->OwnerDoc()->UsingStorageAccess();
12945 }
12946
12947 uint32_t flags = INTERNAL_LOAD_FLAGS_NONE;
12948 bool elementCanHaveNoopener = ElementCanHaveNoopener(aContent);
12949 bool triggeringPrincipalIsSystemPrincipal =
12950 aLoadState->TriggeringPrincipal()->IsSystemPrincipal();
12951 if (elementCanHaveNoopener) {
12952 MOZ_ASSERT(aContent->IsHTMLElement() || aContent->IsSVGElement())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aContent->IsHTMLElement() || aContent->IsSVGElement
())>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(aContent->IsHTMLElement() || aContent->IsSVGElement
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("aContent->IsHTMLElement() || aContent->IsSVGElement()"
, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 12952); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aContent->IsHTMLElement() || aContent->IsSVGElement()"
")"); do { *((volatile int*)__null) = 12952; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12953 nsAutoString relString;
12954 aContent->AsElement()->GetAttr(nsGkAtoms::rel, relString);
12955 nsWhitespaceTokenizerTemplate<nsContentUtils::IsHTMLWhitespace> tok(
12956 relString);
12957
12958 bool targetBlank = aLoadState->Target().LowerCaseEqualsLiteral("_blank");
12959 bool explicitOpenerSet = false;
12960
12961 // The opener behaviour follows a hierarchy, such that if a higher
12962 // priority behaviour is specified, it always takes priority. That
12963 // priority is currently: norefrerer > noopener > opener > default
12964
12965 while (tok.hasMoreTokens()) {
12966 const nsAString& token = tok.nextToken();
12967 if (token.LowerCaseEqualsLiteral("noreferrer")) {
12968 flags |= INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER |
12969 INTERNAL_LOAD_FLAGS_NO_OPENER;
12970 // noreferrer cannot be overwritten by a 'rel=opener'.
12971 explicitOpenerSet = true;
12972 break;
12973 }
12974
12975 if (token.LowerCaseEqualsLiteral("noopener")) {
12976 flags |= INTERNAL_LOAD_FLAGS_NO_OPENER;
12977 explicitOpenerSet = true;
12978 }
12979
12980 if (targetBlank && StaticPrefs::dom_targetBlankNoOpener_enabled() &&
12981 token.LowerCaseEqualsLiteral("opener") && !explicitOpenerSet) {
12982 explicitOpenerSet = true;
12983 }
12984 }
12985
12986 if (targetBlank && StaticPrefs::dom_targetBlankNoOpener_enabled() &&
12987 !explicitOpenerSet && !triggeringPrincipalIsSystemPrincipal) {
12988 flags |= INTERNAL_LOAD_FLAGS_NO_OPENER;
12989 }
12990
12991 if (aNoOpenerImplied) {
12992 flags |= INTERNAL_LOAD_FLAGS_NO_OPENER;
12993 }
12994 }
12995
12996 // Get the owner document of the link that was clicked, this will be
12997 // the document that the link is in, or the last document that the
12998 // link was in. From that document, we'll get the URI to use as the
12999 // referrer, since the current URI in this docshell may be a
13000 // new document that we're in the process of loading.
13001 RefPtr<Document> referrerDoc = aContent->OwnerDoc();
13002
13003 // Now check that the referrerDoc's inner window is the current inner
13004 // window for mScriptGlobal. If it's not, then we don't want to
13005 // follow this link.
13006 nsPIDOMWindowInner* referrerInner = referrerDoc->GetInnerWindow();
13007 if (!mScriptGlobal || !referrerInner ||
13008 mScriptGlobal->GetCurrentInnerWindow() != referrerInner) {
13009 // We're no longer the current inner window
13010 return NS_OK;
13011 }
13012
13013 // referrer could be null here in some odd cases, but that's ok,
13014 // we'll just load the link w/o sending a referrer in those cases.
13015
13016 // If this is an anchor element, grab its type property to use as a hint
13017 nsAutoString typeHint;
13018 RefPtr<HTMLAnchorElement> anchor = HTMLAnchorElement::FromNode(aContent);
13019 if (anchor) {
13020 anchor->GetType(typeHint);
13021 NS_ConvertUTF16toUTF8 utf8Hint(typeHint);
13022 nsAutoCString type, dummy;
13023 NS_ParseRequestContentType(utf8Hint, type, dummy);
13024 CopyUTF8toUTF16(type, typeHint);
13025 }
13026
13027 uint32_t loadType = LOAD_LINK;
13028 if (aLoadState->IsFormSubmission()) {
13029 if (aLoadState->Target().IsEmpty()) {
13030 // We set the right load type here for form submissions with an empty
13031 // target. Form submission with a non-empty target are handled in
13032 // nsDocShell::PerformRetargeting after we've selected the correct target
13033 // BC.
13034 loadType = GetLoadTypeForFormSubmission(GetBrowsingContext(), aLoadState);
13035 }
13036 } else {
13037 // Link click can be triggered inside an onload handler, and we don't want
13038 // to add history entry in this case.
13039 bool inOnLoadHandler = false;
13040 GetIsExecutingOnLoadHandler(&inOnLoadHandler);
13041 if (inOnLoadHandler) {
13042 loadType = LOAD_NORMAL_REPLACE;
13043 }
13044 }
13045
13046 nsCOMPtr<nsIReferrerInfo> referrerInfo =
13047 elementCanHaveNoopener ? new ReferrerInfo(*aContent->AsElement())
13048 : new ReferrerInfo(*referrerDoc);
13049
13050 aLoadState->SetTriggeringSandboxFlags(triggeringSandboxFlags);
13051 aLoadState->SetTriggeringWindowId(triggeringWindowId);
13052 aLoadState->SetTriggeringStorageAccess(triggeringStorageAccess);
13053 aLoadState->SetReferrerInfo(referrerInfo);
13054 aLoadState->SetInternalLoadFlags(flags);
13055 aLoadState->SetTypeHint(NS_ConvertUTF16toUTF8(typeHint));
13056 aLoadState->SetLoadType(loadType);
13057 aLoadState->SetSourceBrowsingContext(mBrowsingContext);
13058
13059 nsresult rv = InternalLoad(aLoadState);
13060
13061 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
13062 nsPingListener::DispatchPings(this, aContent, aLoadState->URI(),
13063 referrerInfo);
13064 }
13065
13066 return rv;
13067}
13068
13069nsresult nsDocShell::OnOverLink(nsIContent* aContent, nsIURI* aURI,
13070 const nsAString& aTargetSpec) {
13071 if (aContent->IsEditable()) {
13072 return NS_OK;
13073 }
13074
13075 nsresult rv = NS_ERROR_FAILURE;
13076
13077 nsCOMPtr<nsIWebBrowserChrome> browserChrome = do_GetInterface(mTreeOwner);
13078 if (!browserChrome) {
13079 return rv;
13080 }
13081
13082 nsCOMPtr<nsIURI> exposableURI = nsIOService::CreateExposableURI(aURI);
13083 nsAutoCString spec;
13084 rv = exposableURI->GetDisplaySpec(spec);
13085 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/docshell/base/nsDocShell.cpp"
, 13085); return rv; } } while (false)
;
13086
13087 NS_ConvertUTF8toUTF16 uStr(spec);
13088
13089 PredictorPredict(aURI, mCurrentURI, nsINetworkPredictor::PREDICT_LINK,
13090 aContent->NodePrincipal()->OriginAttributesRef(), nullptr);
13091
13092 rv = browserChrome->SetLinkStatus(uStr);
13093 return rv;
13094}
13095
13096nsresult nsDocShell::OnLeaveLink() {
13097 nsCOMPtr<nsIWebBrowserChrome> browserChrome(do_GetInterface(mTreeOwner));
13098 nsresult rv = NS_ERROR_FAILURE;
13099
13100 if (browserChrome) {
13101 rv = browserChrome->SetLinkStatus(u""_ns);
13102 }
13103 return rv;
13104}
13105
13106bool nsDocShell::ShouldBlockLoadingForBackButton() {
13107 if (!(mLoadType & LOAD_CMD_HISTORY) ||
13108 UserActivation::IsHandlingUserInput() ||
13109 !Preferences::GetBool("accessibility.blockjsredirection")) {
13110 return false;
13111 }
13112
13113 bool canGoForward = false;
13114 GetCanGoForward(&canGoForward);
13115 return canGoForward;
13116}
13117
13118//----------------------------------------------------------------------
13119// Web Shell Services API
13120
13121// This functions is only called when a new charset is detected in loading a
13122// document.
13123nsresult nsDocShell::CharsetChangeReloadDocument(
13124 mozilla::NotNull<const mozilla::Encoding*> aEncoding, int32_t aSource) {
13125 // XXX hack. keep the aCharset and aSource wait to pick it up
13126 nsCOMPtr<nsIDocumentViewer> viewer;
13127 NS_ENSURE_SUCCESS(GetDocViewer(getter_AddRefs(viewer)), NS_ERROR_FAILURE)do { nsresult __rv = GetDocViewer(getter_AddRefs(viewer)); 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", "GetDocViewer(getter_AddRefs(viewer))"
, "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/docshell/base/nsDocShell.cpp"
, 13127); return NS_ERROR_FAILURE; } } while (false)
;
13128 if (viewer) {
13129 int32_t source;
13130 Unused << viewer->GetReloadEncodingAndSource(&source);
13131 if (aSource > source) {
13132 viewer->SetReloadEncodingAndSource(aEncoding, aSource);
13133 if (eCharsetReloadRequested != mCharsetReloadState) {
13134 mCharsetReloadState = eCharsetReloadRequested;
13135 switch (mLoadType) {
13136 case LOAD_RELOAD_BYPASS_PROXY_AND_CACHE:
13137 return Reload(LOAD_FLAGS_CHARSET_CHANGE | LOAD_FLAGS_BYPASS_CACHE |
13138 LOAD_FLAGS_BYPASS_PROXY);
13139 case LOAD_RELOAD_BYPASS_CACHE:
13140 return Reload(LOAD_FLAGS_CHARSET_CHANGE | LOAD_FLAGS_BYPASS_CACHE);
13141 default:
13142 return Reload(LOAD_FLAGS_CHARSET_CHANGE);
13143 }
13144 }
13145 }
13146 }
13147 // return failure if this request is not accepted due to mCharsetReloadState
13148 return NS_ERROR_DOCSHELL_REQUEST_REJECTED;
13149}
13150
13151nsresult nsDocShell::CharsetChangeStopDocumentLoad() {
13152 if (eCharsetReloadRequested != mCharsetReloadState) {
13153 Stop(nsIWebNavigation::STOP_ALL);
13154 return NS_OK;
13155 }
13156 // return failer if this request is not accepted due to mCharsetReloadState
13157 return NS_ERROR_DOCSHELL_REQUEST_REJECTED;
13158}
13159
13160NS_IMETHODIMPnsresult nsDocShell::ExitPrintPreview() {
13161#if NS_PRINT_PREVIEW1
13162 nsCOMPtr<nsIWebBrowserPrint> viewer = do_QueryInterface(mDocumentViewer);
13163 return viewer->ExitPrintPreview();
13164#else
13165 return NS_OK;
13166#endif
13167}
13168
13169/* [infallible] */
13170NS_IMETHODIMPnsresult nsDocShell::GetIsTopLevelContentDocShell(
13171 bool* aIsTopLevelContentDocShell) {
13172 *aIsTopLevelContentDocShell = false;
13173
13174 if (mItemType == typeContent) {
13175 *aIsTopLevelContentDocShell = mBrowsingContext->IsTopContent();
13176 }
13177
13178 return NS_OK;
13179}
13180
13181// Implements nsILoadContext.originAttributes
13182NS_IMETHODIMPnsresult
13183nsDocShell::GetScriptableOriginAttributes(JSContext* aCx,
13184 JS::MutableHandle<JS::Value> aVal) {
13185 return mBrowsingContext->GetScriptableOriginAttributes(aCx, aVal);
13186}
13187
13188// Implements nsIDocShell.GetOriginAttributes()
13189NS_IMETHODIMPnsresult
13190nsDocShell::GetOriginAttributes(JSContext* aCx,
13191 JS::MutableHandle<JS::Value> aVal) {
13192 return mBrowsingContext->GetScriptableOriginAttributes(aCx, aVal);
13193}
13194
13195bool nsDocShell::ServiceWorkerAllowedToControlWindow(nsIPrincipal* aPrincipal,
13196 nsIURI* aURI) {
13197 MOZ_ASSERT(aPrincipal)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aPrincipal)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aPrincipal))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("aPrincipal", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 13197); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPrincipal"
")"); do { *((volatile int*)__null) = 13197; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
13198 MOZ_ASSERT(aURI)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aURI)>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(aURI))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("aURI", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 13198); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aURI" ")")
; do { *((volatile int*)__null) = 13198; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
13199
13200 if (UsePrivateBrowsing() || mBrowsingContext->GetSandboxFlags()) {
13201 return false;
13202 }
13203
13204 nsCOMPtr<nsIDocShellTreeItem> parent;
13205 GetInProcessSameTypeParent(getter_AddRefs(parent));
13206 nsPIDOMWindowOuter* parentOuter = parent ? parent->GetWindow() : nullptr;
13207 nsPIDOMWindowInner* parentInner =
13208 parentOuter ? parentOuter->GetCurrentInnerWindow() : nullptr;
13209
13210 StorageAccess storage =
13211 StorageAllowedForNewWindow(aPrincipal, aURI, parentInner);
13212
13213 // If the partitioned service worker is enabled, service worker is allowed to
13214 // control the window if partition is enabled.
13215 if (StaticPrefs::privacy_partition_serviceWorkers() && parentInner) {
13216 RefPtr<Document> doc = parentInner->GetExtantDoc();
13217
13218 if (doc && StoragePartitioningEnabled(storage, doc->CookieJarSettings())) {
13219 return true;
13220 }
13221 }
13222
13223 return storage == StorageAccess::eAllow;
13224}
13225
13226nsresult nsDocShell::SetOriginAttributes(const OriginAttributes& aAttrs) {
13227 MOZ_ASSERT(!mIsBeingDestroyed)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mIsBeingDestroyed)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mIsBeingDestroyed))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("!mIsBeingDestroyed"
, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 13227); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mIsBeingDestroyed"
")"); do { *((volatile int*)__null) = 13227; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
13228 return mBrowsingContext->SetOriginAttributes(aAttrs);
13229}
13230
13231NS_IMETHODIMPnsresult
13232nsDocShell::ResumeRedirectedLoad(uint64_t aIdentifier, int32_t aHistoryIndex) {
13233 RefPtr<nsDocShell> self = this;
13234 RefPtr<ChildProcessChannelListener> cpcl =
13235 ChildProcessChannelListener::GetSingleton();
13236
13237 // Call into InternalLoad with the pending channel when it is received.
13238 cpcl->RegisterCallback(
13239 aIdentifier, [self, aHistoryIndex](
13240 nsDocShellLoadState* aLoadState,
13241 nsTArray<Endpoint<extensions::PStreamFilterParent>>&&
13242 aStreamFilterEndpoints,
13243 nsDOMNavigationTiming* aTiming) {
13244 MOZ_ASSERT(aLoadState->GetPendingRedirectedChannel())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aLoadState->GetPendingRedirectedChannel())>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(aLoadState->GetPendingRedirectedChannel()))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("aLoadState->GetPendingRedirectedChannel()"
, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 13244); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->GetPendingRedirectedChannel()"
")"); do { *((volatile int*)__null) = 13244; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
13245 if (NS_WARN_IF(self->mIsBeingDestroyed)NS_warn_if_impl(self->mIsBeingDestroyed, "self->mIsBeingDestroyed"
, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 13245)
) {
13246 aLoadState->GetPendingRedirectedChannel()->CancelWithReason(
13247 NS_BINDING_ABORTED, "nsDocShell::mIsBeingDestroyed"_ns);
13248 return NS_BINDING_ABORTED;
13249 }
13250
13251 self->mLoadType = aLoadState->LoadType();
13252 nsCOMPtr<nsIURI> previousURI;
13253 uint32_t previousFlags = 0;
13254 ExtractLastVisit(aLoadState->GetPendingRedirectedChannel(),
13255 getter_AddRefs(previousURI), &previousFlags);
13256 self->SaveLastVisit(aLoadState->GetPendingRedirectedChannel(),
13257 previousURI, previousFlags);
13258
13259 if (aTiming) {
13260 self->mTiming = new nsDOMNavigationTiming(self, aTiming);
13261 self->mBlankTiming = false;
13262 }
13263
13264 // If we're performing a history load, locate the correct history entry,
13265 // and set the relevant bits on our loadState.
13266 if (aHistoryIndex >= 0 && self->GetSessionHistory() &&
13267 !mozilla::SessionHistoryInParent()) {
13268 nsCOMPtr<nsISHistory> legacySHistory =
13269 self->GetSessionHistory()->LegacySHistory();
13270
13271 nsCOMPtr<nsISHEntry> entry;
13272 nsresult rv = legacySHistory->GetEntryAtIndex(aHistoryIndex,
13273 getter_AddRefs(entry));
13274 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
13275 legacySHistory->InternalSetRequestedIndex(aHistoryIndex);
13276 aLoadState->SetLoadType(LOAD_HISTORY);
13277 aLoadState->SetSHEntry(entry);
13278 }
13279 }
13280
13281 self->InternalLoad(aLoadState);
13282
13283 if (aLoadState->GetOriginalURIString().isSome()) {
13284 // Save URI string in case it's needed later when
13285 // sending to search engine service in EndPageLoad()
13286 self->mOriginalUriString = *aLoadState->GetOriginalURIString();
13287 }
13288
13289 for (auto& endpoint : aStreamFilterEndpoints) {
13290 extensions::StreamFilterParent::Attach(
13291 aLoadState->GetPendingRedirectedChannel(), std::move(endpoint));
13292 }
13293
13294 // If the channel isn't pending, then it means that InternalLoad
13295 // never connected it, and we shouldn't try to continue. This
13296 // can happen even if InternalLoad returned NS_OK.
13297 bool pending = false;
13298 aLoadState->GetPendingRedirectedChannel()->IsPending(&pending);
13299 NS_ASSERTION(pending, "We should have connected the pending channel!")do { if (!(pending)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "We should have connected the pending channel!"
, "pending", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 13299); MOZ_PretendNoReturn(); } } while (0)
;
13300 if (!pending) {
13301 return NS_BINDING_ABORTED;
13302 }
13303 return NS_OK;
13304 });
13305 return NS_OK;
13306}
13307
13308NS_IMETHODIMPnsresult
13309nsDocShell::SetOriginAttributes(JS::Handle<JS::Value> aOriginAttributes,
13310 JSContext* aCx) {
13311 OriginAttributes attrs;
13312 if (!aOriginAttributes.isObject() || !attrs.Init(aCx, aOriginAttributes)) {
13313 return NS_ERROR_INVALID_ARG;
13314 }
13315
13316 return SetOriginAttributes(attrs);
13317}
13318
13319NS_IMETHODIMPnsresult
13320nsDocShell::GetAsyncPanZoomEnabled(bool* aOut) {
13321 if (PresShell* presShell = GetPresShell()) {
13322 *aOut = presShell->AsyncPanZoomEnabled();
13323 return NS_OK;
13324 }
13325
13326 // If we don't have a presShell, fall back to the default platform value of
13327 // whether or not APZ is enabled.
13328 *aOut = gfxPlatform::AsyncPanZoomEnabled();
13329 return NS_OK;
13330}
13331
13332bool nsDocShell::HasUnloadedParent() {
13333 for (WindowContext* wc = GetBrowsingContext()->GetParentWindowContext(); wc;
13334 wc = wc->GetParentWindowContext()) {
13335 if (!wc->IsCurrent() || wc->IsDiscarded() ||
13336 wc->GetBrowsingContext()->IsDiscarded()) {
13337 // If a parent is OOP and the parent WindowContext is no
13338 // longer current, we can assume the parent was unloaded.
13339 return true;
13340 }
13341
13342 if (wc->GetBrowsingContext()->IsInProcess() &&
13343 (!wc->GetBrowsingContext()->GetDocShell() ||
13344 wc->GetBrowsingContext()->GetDocShell()->GetIsInUnload())) {
13345 return true;
13346 }
13347 }
13348 return false;
13349}
13350
13351/* static */
13352bool nsDocShell::ShouldUpdateGlobalHistory(uint32_t aLoadType) {
13353 return !(aLoadType == LOAD_BYPASS_HISTORY || aLoadType == LOAD_ERROR_PAGE ||
13354 aLoadType & LOAD_CMD_HISTORY);
13355}
13356
13357void nsDocShell::UpdateGlobalHistoryTitle(nsIURI* aURI) {
13358 if (!mBrowsingContext->GetUseGlobalHistory() || UsePrivateBrowsing()) {
13359 return;
13360 }
13361
13362 // Global history is interested into sub-frame visits only for link-coloring
13363 // purposes, thus title updates are skipped for those.
13364 //
13365 // Moreover, some iframe documents (such as the ones created via
13366 // document.open()) inherit the document uri of the caller, which would cause
13367 // us to override a previously set page title with one from the subframe.
13368 if (IsSubframe()) {
13369 return;
13370 }
13371
13372 if (nsCOMPtr<IHistory> history = components::History::Service()) {
13373 history->SetURITitle(aURI, mTitle);
13374 }
13375}
13376
13377bool nsDocShell::IsInvisible() { return mInvisible; }
13378
13379void nsDocShell::SetInvisible(bool aInvisible) { mInvisible = aInvisible; }
13380
13381/* static */
13382void nsDocShell::MaybeNotifyKeywordSearchLoading(const nsString& aProvider,
13383 const nsString& aKeyword) {
13384 if (aProvider.IsEmpty()) {
13385 return;
13386 }
13387 nsresult rv;
13388 nsCOMPtr<nsISupportsString> isupportsString =
13389 do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID"@mozilla.org/supports-string;1", &rv);
13390 NS_ENSURE_SUCCESS_VOID(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_VOID(%s) failed with "
"result 0x%" "X" "%s%s%s", "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/docshell/base/nsDocShell.cpp"
, 13390); return; } } while (false)
;
13391
13392 rv = isupportsString->SetData(aProvider);
13393 NS_ENSURE_SUCCESS_VOID(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_VOID(%s) failed with "
"result 0x%" "X" "%s%s%s", "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/docshell/base/nsDocShell.cpp"
, 13393); return; } } while (false)
;
13394
13395 nsCOMPtr<nsIObserverService> obsSvc = services::GetObserverService();
13396 if (obsSvc) {
13397 // Note that "keyword-search" refers to a search via the url
13398 // bar, not a bookmarks keyword search.
13399 obsSvc->NotifyObservers(isupportsString, "keyword-search", aKeyword.get());
13400 }
13401}
13402
13403NS_IMETHODIMPnsresult
13404nsDocShell::ShouldPrepareForIntercept(nsIURI* aURI, nsIChannel* aChannel,
13405 bool* aShouldIntercept) {
13406 return mInterceptController->ShouldPrepareForIntercept(aURI, aChannel,
13407 aShouldIntercept);
13408}
13409
13410NS_IMETHODIMPnsresult
13411nsDocShell::ChannelIntercepted(nsIInterceptedChannel* aChannel) {
13412 return mInterceptController->ChannelIntercepted(aChannel);
13413}
13414
13415bool nsDocShell::InFrameSwap() {
13416 RefPtr<nsDocShell> shell = this;
13417 do {
13418 if (shell->mInFrameSwap) {
13419 return true;
13420 }
13421 shell = shell->GetInProcessParentDocshell();
13422 } while (shell);
13423 return false;
13424}
13425
13426UniquePtr<ClientSource> nsDocShell::TakeInitialClientSource() {
13427 return std::move(mInitialClientSource);
13428}
13429
13430NS_IMETHODIMPnsresult
13431nsDocShell::GetEditingSession(nsIEditingSession** aEditSession) {
13432 if (!NS_SUCCEEDED(EnsureEditorData())((bool)(__builtin_expect(!!(!NS_FAILED_impl(EnsureEditorData(
))), 1)))
) {
13433 return NS_ERROR_FAILURE;
13434 }
13435
13436 *aEditSession = do_AddRef(mEditorData->GetEditingSession()).take();
13437 return *aEditSession ? NS_OK : NS_ERROR_FAILURE;
13438}
13439
13440NS_IMETHODIMPnsresult
13441nsDocShell::GetScriptableBrowserChild(nsIBrowserChild** aBrowserChild) {
13442 *aBrowserChild = GetBrowserChild().take();
13443 return *aBrowserChild ? NS_OK : NS_ERROR_FAILURE;
13444}
13445
13446already_AddRefed<nsIBrowserChild> nsDocShell::GetBrowserChild() {
13447 nsCOMPtr<nsIBrowserChild> tc = do_QueryReferent(mBrowserChild);
13448 return tc.forget();
13449}
13450
13451nsCommandManager* nsDocShell::GetCommandManager() {
13452 NS_ENSURE_SUCCESS(EnsureCommandHandler(), nullptr)do { nsresult __rv = EnsureCommandHandler(); 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", "EnsureCommandHandler()", "nullptr", static_cast
<uint32_t>(__rv), name ? " (" : "", name ? name : "", name
? ")" : ""); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 13452); return nullptr; } } while (false)
;
13453 return mCommandManager;
13454}
13455
13456NS_IMETHODIMP_(void)void
13457nsDocShell::GetOriginAttributes(mozilla::OriginAttributes& aAttrs) {
13458 mBrowsingContext->GetOriginAttributes(aAttrs);
13459}
13460
13461HTMLEditor* nsIDocShell::GetHTMLEditor() {
13462 nsDocShell* docShell = static_cast<nsDocShell*>(this);
13463 return docShell->GetHTMLEditorInternal();
13464}
13465
13466nsresult nsIDocShell::SetHTMLEditor(HTMLEditor* aHTMLEditor) {
13467 nsDocShell* docShell = static_cast<nsDocShell*>(this);
13468 return docShell->SetHTMLEditorInternal(aHTMLEditor);
13469}
13470
13471#define MATRIX_LENGTH 20
13472
13473NS_IMETHODIMPnsresult
13474nsDocShell::SetColorMatrix(const nsTArray<float>& aMatrix) {
13475 if (aMatrix.Length() == MATRIX_LENGTH) {
13476 mColorMatrix.reset(new gfx::Matrix5x4());
13477 static_assert(
13478 MATRIX_LENGTH * sizeof(float) == sizeof(mColorMatrix->components),
13479 "Size mismatch for our memcpy");
13480 memcpy(mColorMatrix->components, aMatrix.Elements(),
13481 sizeof(mColorMatrix->components));
13482 } else if (aMatrix.Length() == 0) {
13483 mColorMatrix.reset();
13484 } else {
13485 return NS_ERROR_INVALID_ARG;
13486 }
13487
13488 PresShell* presShell = GetPresShell();
13489 if (!presShell) {
13490 return NS_ERROR_FAILURE;
13491 }
13492
13493 nsIFrame* frame = presShell->GetRootFrame();
13494 if (!frame) {
13495 return NS_ERROR_FAILURE;
13496 }
13497
13498 frame->SchedulePaint();
13499
13500 return NS_OK;
13501}
13502
13503NS_IMETHODIMPnsresult
13504nsDocShell::GetColorMatrix(nsTArray<float>& aMatrix) {
13505 if (mColorMatrix) {
13506 aMatrix.SetLength(MATRIX_LENGTH);
13507 static_assert(
13508 MATRIX_LENGTH * sizeof(float) == sizeof(mColorMatrix->components),
13509 "Size mismatch for our memcpy");
13510 memcpy(aMatrix.Elements(), mColorMatrix->components,
13511 MATRIX_LENGTH * sizeof(float));
13512 }
13513
13514 return NS_OK;
13515}
13516
13517#undef MATRIX_LENGTH
13518
13519NS_IMETHODIMPnsresult
13520nsDocShell::GetIsForceReloading(bool* aForceReload) {
13521 *aForceReload = IsForceReloading();
13522 return NS_OK;
13523}
13524
13525bool nsDocShell::IsForceReloading() { return IsForceReloadType(mLoadType); }
13526
13527NS_IMETHODIMPnsresult
13528nsDocShell::GetBrowsingContextXPCOM(BrowsingContext** aBrowsingContext) {
13529 *aBrowsingContext = do_AddRef(mBrowsingContext).take();
13530 return NS_OK;
13531}
13532
13533BrowsingContext* nsDocShell::GetBrowsingContext() { return mBrowsingContext; }
13534
13535bool nsDocShell::GetIsAttemptingToNavigate() {
13536 // XXXbz the document.open spec says to abort even if there's just a
13537 // queued navigation task, sort of. It's not clear whether browsers
13538 // actually do that, and we didn't use to do it, so for now let's
13539 // not do that.
13540 // https://github.com/whatwg/html/issues/3447 tracks the spec side of this.
13541 if (mDocumentRequest) {
13542 // There's definitely a navigation in progress.
13543 return true;
13544 }
13545
13546 // javascript: channels have slightly weird behavior: they're LOAD_BACKGROUND
13547 // until the script runs, which means they're not sending loadgroup
13548 // notifications and hence not getting set as mDocumentRequest. Look through
13549 // our loadgroup for document-level javascript: loads.
13550 if (!mLoadGroup) {
13551 return false;
13552 }
13553
13554 nsCOMPtr<nsISimpleEnumerator> requests;
13555 mLoadGroup->GetRequests(getter_AddRefs(requests));
13556 bool hasMore = false;
13557 while (NS_SUCCEEDED(requests->HasMoreElements(&hasMore))((bool)(__builtin_expect(!!(!NS_FAILED_impl(requests->HasMoreElements
(&hasMore))), 1)))
&& hasMore) {
13558 nsCOMPtr<nsISupports> elem;
13559 requests->GetNext(getter_AddRefs(elem));
13560 nsCOMPtr<nsIScriptChannel> scriptChannel(do_QueryInterface(elem));
13561 if (!scriptChannel) {
13562 continue;
13563 }
13564
13565 if (scriptChannel->GetIsDocumentLoad()) {
13566 // This is a javascript: load that might lead to a new document,
13567 // hence a navigation.
13568 return true;
13569 }
13570 }
13571
13572 return mCheckingSessionHistory;
13573}
13574
13575void nsDocShell::SetLoadingSessionHistoryInfo(
13576 const mozilla::dom::LoadingSessionHistoryInfo& aLoadingInfo,
13577 bool aNeedToReportActiveAfterLoadingBecomesActive) {
13578 // FIXME Would like to assert this, but can't yet.
13579 // MOZ_ASSERT(!mLoadingEntry);
13580 MOZ_LOG(gSHLog, LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = gSHLog; if
((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "Setting the loading entry on nsDocShell %p to %s"
, this, aLoadingInfo.mInfo.GetURI()->GetSpecOrDefault().get
()); } } while (0)
13581 ("Setting the loading entry on nsDocShell %p to %s", this,do { const ::mozilla::LogModule* moz_real_module = gSHLog; if
((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "Setting the loading entry on nsDocShell %p to %s"
, this, aLoadingInfo.mInfo.GetURI()->GetSpecOrDefault().get
()); } } while (0)
13582 aLoadingInfo.mInfo.GetURI()->GetSpecOrDefault().get()))do { const ::mozilla::LogModule* moz_real_module = gSHLog; if
((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "Setting the loading entry on nsDocShell %p to %s"
, this, aLoadingInfo.mInfo.GetURI()->GetSpecOrDefault().get
()); } } while (0)
;
13583 mLoadingEntry = MakeUnique<LoadingSessionHistoryInfo>(aLoadingInfo);
13584 mNeedToReportActiveAfterLoadingBecomesActive =
13585 aNeedToReportActiveAfterLoadingBecomesActive;
13586}
13587
13588void nsDocShell::MoveLoadingToActiveEntry(bool aPersist, bool aExpired,
13589 uint32_t aCacheKey,
13590 nsIURI* aPreviousURI) {
13591 MOZ_ASSERT(mozilla::SessionHistoryInParent())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mozilla::SessionHistoryInParent())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mozilla::SessionHistoryInParent
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("mozilla::SessionHistoryInParent()", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 13591); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mozilla::SessionHistoryInParent()"
")"); do { *((volatile int*)__null) = 13591; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
13592
13593 MOZ_LOG(gSHLog, LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = gSHLog; if
((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "nsDocShell %p MoveLoadingToActiveEntry", this
); } } while (0)
13594 ("nsDocShell %p MoveLoadingToActiveEntry", this))do { const ::mozilla::LogModule* moz_real_module = gSHLog; if
((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "nsDocShell %p MoveLoadingToActiveEntry", this
); } } while (0)
;
13595
13596 UniquePtr<SessionHistoryInfo> previousActiveEntry(mActiveEntry.release());
13597 mozilla::UniquePtr<mozilla::dom::LoadingSessionHistoryInfo> loadingEntry;
13598 mActiveEntryIsLoadingFromSessionHistory =
13599 mLoadingEntry && mLoadingEntry->mLoadIsFromSessionHistory;
13600 if (mLoadingEntry) {
13601 MOZ_LOG(gSHLog, LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = gSHLog; if
((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "Moving the loading entry to the active entry on nsDocShell %p "
"to %s", this, mLoadingEntry->mInfo.GetURI()->GetSpecOrDefault
().get()); } } while (0)
13602 ("Moving the loading entry to the active entry on nsDocShell %p "do { const ::mozilla::LogModule* moz_real_module = gSHLog; if
((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "Moving the loading entry to the active entry on nsDocShell %p "
"to %s", this, mLoadingEntry->mInfo.GetURI()->GetSpecOrDefault
().get()); } } while (0)
13603 "to %s",do { const ::mozilla::LogModule* moz_real_module = gSHLog; if
((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "Moving the loading entry to the active entry on nsDocShell %p "
"to %s", this, mLoadingEntry->mInfo.GetURI()->GetSpecOrDefault
().get()); } } while (0)
13604 this, mLoadingEntry->mInfo.GetURI()->GetSpecOrDefault().get()))do { const ::mozilla::LogModule* moz_real_module = gSHLog; if
((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "Moving the loading entry to the active entry on nsDocShell %p "
"to %s", this, mLoadingEntry->mInfo.GetURI()->GetSpecOrDefault
().get()); } } while (0)
;
13605 mActiveEntry = MakeUnique<SessionHistoryInfo>(mLoadingEntry->mInfo);
13606 mLoadingEntry.swap(loadingEntry);
13607 if (!mActiveEntryIsLoadingFromSessionHistory) {
13608 if (mNeedToReportActiveAfterLoadingBecomesActive) {
13609 // Needed to pass various history length WPTs.
13610 mBrowsingContext->SetActiveSessionHistoryEntry(
13611 mozilla::Nothing(), mActiveEntry.get(), mLoadType,
13612 /* aUpdatedCacheKey = */ 0, false);
13613 }
13614 mBrowsingContext->IncrementHistoryEntryCountForBrowsingContext();
13615 }
13616 }
13617 mNeedToReportActiveAfterLoadingBecomesActive = false;
13618
13619 if (mActiveEntry) {
13620 if (aCacheKey != 0) {
13621 mActiveEntry->SetCacheKey(aCacheKey);
13622 }
13623 MOZ_ASSERT(loadingEntry)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(loadingEntry)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(loadingEntry))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("loadingEntry", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 13623); AnnotateMozCrashReason("MOZ_ASSERT" "(" "loadingEntry"
")"); do { *((volatile int*)__null) = 13623; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
13624 uint32_t loadType =
13625 mLoadType == LOAD_ERROR_PAGE ? mFailedLoadType : mLoadType;
13626
13627 if (loadingEntry->mLoadId != UINT64_MAX(18446744073709551615UL)) {
13628 // We're passing in mCurrentURI, which could be null. SessionHistoryCommit
13629 // does require a non-null uri if this is for a refresh load of the same
13630 // URI, but in that case mCurrentURI won't be null here.
13631 mBrowsingContext->SessionHistoryCommit(
13632 *loadingEntry, loadType, aPreviousURI, previousActiveEntry.get(),
13633 aPersist, false, aExpired, aCacheKey);
13634 }
13635 }
13636}
13637
13638static bool IsFaviconLoad(nsIRequest* aRequest) {
13639 nsCOMPtr<nsIChannel> channel = do_QueryInterface(aRequest);
13640 if (!channel) {
13641 return false;
13642 }
13643
13644 nsCOMPtr<nsILoadInfo> li = channel->LoadInfo();
13645 return li && li->InternalContentPolicyType() ==
13646 nsIContentPolicy::TYPE_INTERNAL_IMAGE_FAVICON;
13647}
13648
13649void nsDocShell::RecordSingleChannelId(bool aStartRequest,
13650 nsIRequest* aRequest) {
13651 // Ignore favicon loads, they don't need to block caching.
13652 if (IsFaviconLoad(aRequest)) {
13653 return;
13654 }
13655
13656 MOZ_ASSERT_IF(!aStartRequest, mRequestForBlockingFromBFCacheCount > 0)do { if (!aStartRequest) { do { static_assert( mozilla::detail
::AssertionConditionType<decltype(mRequestForBlockingFromBFCacheCount
> 0)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(mRequestForBlockingFromBFCacheCount > 0))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("mRequestForBlockingFromBFCacheCount > 0"
, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 13656); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mRequestForBlockingFromBFCacheCount > 0"
")"); do { *((volatile int*)__null) = 13656; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false); } } while
(false)
;
13657
13658 mRequestForBlockingFromBFCacheCount += aStartRequest ? 1 : -1;
13659
13660 if (mBrowsingContext->GetCurrentWindowContext()) {
13661 // We have three states: no request, one request with an id and
13662 // eiher one request without an id or multiple requests. Nothing() is no
13663 // request, Some(non-zero) is one request with an id and Some(0) is one
13664 // request without an id or multiple requests.
13665 Maybe<uint64_t> singleChannelId;
13666 if (mRequestForBlockingFromBFCacheCount > 1) {
13667 singleChannelId = Some(0);
13668 } else if (mRequestForBlockingFromBFCacheCount == 1) {
13669 nsCOMPtr<nsIIdentChannel> identChannel;
13670 if (aStartRequest) {
13671 identChannel = do_QueryInterface(aRequest);
13672 } else {
13673 // aChannel is the channel that's being removed, but we need to check if
13674 // the remaining channel in the loadgroup has an id.
13675 nsCOMPtr<nsISimpleEnumerator> requests;
13676 mLoadGroup->GetRequests(getter_AddRefs(requests));
13677 for (const auto& request : SimpleEnumerator<nsIRequest>(requests)) {
13678 if (!IsFaviconLoad(request) &&
13679 !!(identChannel = do_QueryInterface(request))) {
13680 break;
13681 }
13682 }
13683 }
13684
13685 if (identChannel) {
13686 singleChannelId = Some(identChannel->ChannelId());
13687 } else {
13688 singleChannelId = Some(0);
13689 }
13690 } else {
13691 MOZ_ASSERT(mRequestForBlockingFromBFCacheCount == 0)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mRequestForBlockingFromBFCacheCount == 0)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(mRequestForBlockingFromBFCacheCount == 0))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("mRequestForBlockingFromBFCacheCount == 0"
, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 13691); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mRequestForBlockingFromBFCacheCount == 0"
")"); do { *((volatile int*)__null) = 13691; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
13692 singleChannelId = Nothing();
13693 }
13694
13695 if (MOZ_UNLIKELY(MOZ_LOG_TEST(gSHIPBFCacheLog, LogLevel::Verbose))(__builtin_expect(!!((__builtin_expect(!!(mozilla::detail::log_test
(gSHIPBFCacheLog, LogLevel::Verbose)), 0))), 0))
) {
13696 nsAutoCString uri("[no uri]");
13697 if (mCurrentURI) {
13698 uri = mCurrentURI->GetSpecOrDefault();
13699 }
13700 if (singleChannelId.isNothing()) {
13701 MOZ_LOG(gSHIPBFCacheLog, LogLevel::Verbose,do { const ::mozilla::LogModule* moz_real_module = gSHIPBFCacheLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Verbose)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Verbose, "Loadgroup for %s doesn't have any requests relevant for "
"blocking BFCache", uri.get()); } } while (0)
13702 ("Loadgroup for %s doesn't have any requests relevant for "do { const ::mozilla::LogModule* moz_real_module = gSHIPBFCacheLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Verbose)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Verbose, "Loadgroup for %s doesn't have any requests relevant for "
"blocking BFCache", uri.get()); } } while (0)
13703 "blocking BFCache",do { const ::mozilla::LogModule* moz_real_module = gSHIPBFCacheLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Verbose)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Verbose, "Loadgroup for %s doesn't have any requests relevant for "
"blocking BFCache", uri.get()); } } while (0)
13704 uri.get()))do { const ::mozilla::LogModule* moz_real_module = gSHIPBFCacheLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Verbose)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Verbose, "Loadgroup for %s doesn't have any requests relevant for "
"blocking BFCache", uri.get()); } } while (0)
;
13705 } else if (singleChannelId.value() == 0) {
13706 MOZ_LOG(gSHIPBFCacheLog, LogLevel::Verbose,do { const ::mozilla::LogModule* moz_real_module = gSHIPBFCacheLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Verbose)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Verbose, "Loadgroup for %s has multiple requests relevant for blocking "
"BFCache", uri.get()); } } while (0)
13707 ("Loadgroup for %s has multiple requests relevant for blocking "do { const ::mozilla::LogModule* moz_real_module = gSHIPBFCacheLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Verbose)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Verbose, "Loadgroup for %s has multiple requests relevant for blocking "
"BFCache", uri.get()); } } while (0)
13708 "BFCache",do { const ::mozilla::LogModule* moz_real_module = gSHIPBFCacheLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Verbose)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Verbose, "Loadgroup for %s has multiple requests relevant for blocking "
"BFCache", uri.get()); } } while (0)
13709 uri.get()))do { const ::mozilla::LogModule* moz_real_module = gSHIPBFCacheLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Verbose)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Verbose, "Loadgroup for %s has multiple requests relevant for blocking "
"BFCache", uri.get()); } } while (0)
;
13710 } else {
13711 MOZ_LOG(gSHIPBFCacheLog, LogLevel::Verbose,do { const ::mozilla::LogModule* moz_real_module = gSHIPBFCacheLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Verbose)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Verbose, "Loadgroup for %s has one request with id %"
"l" "u" " relevant for blocking BFCache", uri.get(), singleChannelId
.value()); } } while (0)
13712 ("Loadgroup for %s has one request with id %" PRIu64do { const ::mozilla::LogModule* moz_real_module = gSHIPBFCacheLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Verbose)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Verbose, "Loadgroup for %s has one request with id %"
"l" "u" " relevant for blocking BFCache", uri.get(), singleChannelId
.value()); } } while (0)
13713 " relevant for blocking BFCache",do { const ::mozilla::LogModule* moz_real_module = gSHIPBFCacheLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Verbose)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Verbose, "Loadgroup for %s has one request with id %"
"l" "u" " relevant for blocking BFCache", uri.get(), singleChannelId
.value()); } } while (0)
13714 uri.get(), singleChannelId.value()))do { const ::mozilla::LogModule* moz_real_module = gSHIPBFCacheLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Verbose)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Verbose, "Loadgroup for %s has one request with id %"
"l" "u" " relevant for blocking BFCache", uri.get(), singleChannelId
.value()); } } while (0)
;
13715 }
13716 }
13717
13718 if (mSingleChannelId != singleChannelId) {
13719 mSingleChannelId = singleChannelId;
13720 WindowGlobalChild* wgc =
13721 mBrowsingContext->GetCurrentWindowContext()->GetWindowGlobalChild();
13722 if (wgc) {
13723 wgc->SendSetSingleChannelId(singleChannelId);
13724 }
13725 }
13726 }
13727}
13728
13729NS_IMETHODIMPnsresult
13730nsDocShell::OnStartRequest(nsIRequest* aRequest) {
13731 if (MOZ_UNLIKELY(MOZ_LOG_TEST(gSHIPBFCacheLog, LogLevel::Verbose))(__builtin_expect(!!((__builtin_expect(!!(mozilla::detail::log_test
(gSHIPBFCacheLog, LogLevel::Verbose)), 0))), 0))
) {
13732 nsAutoCString uri("[no uri]");
13733 if (mCurrentURI) {
13734 uri = mCurrentURI->GetSpecOrDefault();
13735 }
13736 nsAutoCString name;
13737 aRequest->GetName(name);
13738 MOZ_LOG(gSHIPBFCacheLog, LogLevel::Verbose,do { const ::mozilla::LogModule* moz_real_module = gSHIPBFCacheLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Verbose)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Verbose, "Adding request %s to loadgroup for %s",
name.get(), uri.get()); } } while (0)
13739 ("Adding request %s to loadgroup for %s", name.get(), uri.get()))do { const ::mozilla::LogModule* moz_real_module = gSHIPBFCacheLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Verbose)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Verbose, "Adding request %s to loadgroup for %s",
name.get(), uri.get()); } } while (0)
;
13740 }
13741 RecordSingleChannelId(true, aRequest);
13742 return nsDocLoader::OnStartRequest(aRequest);
13743}
13744
13745NS_IMETHODIMPnsresult
13746nsDocShell::OnStopRequest(nsIRequest* aRequest, nsresult aStatusCode) {
13747 if (MOZ_UNLIKELY(MOZ_LOG_TEST(gSHIPBFCacheLog, LogLevel::Verbose))(__builtin_expect(!!((__builtin_expect(!!(mozilla::detail::log_test
(gSHIPBFCacheLog, LogLevel::Verbose)), 0))), 0))
) {
13748 nsAutoCString uri("[no uri]");
13749 if (mCurrentURI) {
13750 uri = mCurrentURI->GetSpecOrDefault();
13751 }
13752 nsAutoCString name;
13753 aRequest->GetName(name);
13754 MOZ_LOG(do { const ::mozilla::LogModule* moz_real_module = gSHIPBFCacheLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Verbose)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Verbose, "Removing request %s from loadgroup for %s"
, name.get(), uri.get()); } } while (0)
13755 gSHIPBFCacheLog, LogLevel::Verbose,do { const ::mozilla::LogModule* moz_real_module = gSHIPBFCacheLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Verbose)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Verbose, "Removing request %s from loadgroup for %s"
, name.get(), uri.get()); } } while (0)
13756 ("Removing request %s from loadgroup for %s", name.get(), uri.get()))do { const ::mozilla::LogModule* moz_real_module = gSHIPBFCacheLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Verbose)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Verbose, "Removing request %s from loadgroup for %s"
, name.get(), uri.get()); } } while (0)
;
13757 }
13758 RecordSingleChannelId(false, aRequest);
13759 return nsDocLoader::OnStopRequest(aRequest, aStatusCode);
13760}
13761
13762void nsDocShell::MaybeDisconnectChildListenersOnPageHide() {
13763 MOZ_RELEASE_ASSERT(XRE_IsContentProcess())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(XRE_IsContentProcess())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(XRE_IsContentProcess()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("XRE_IsContentProcess()"
, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 13763); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "XRE_IsContentProcess()"
")"); do { *((volatile int*)__null) = 13763; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
13764
13765 if (mChannelToDisconnectOnPageHide != 0 && mLoadGroup) {
13766 nsCOMPtr<nsISimpleEnumerator> requests;
13767 mLoadGroup->GetRequests(getter_AddRefs(requests));
13768 for (const auto& request : SimpleEnumerator<nsIRequest>(requests)) {
13769 RefPtr<DocumentChannel> channel = do_QueryObject(request);
13770 if (channel && channel->ChannelId() == mChannelToDisconnectOnPageHide) {
13771 static_cast<DocumentChannelChild*>(channel.get())
13772 ->DisconnectChildListeners(NS_BINDING_ABORTED, NS_BINDING_ABORTED);
13773 }
13774 }
13775 mChannelToDisconnectOnPageHide = 0;
13776 }
13777}