Bug Summary

File:var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp
Warning:line 3422, 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-20/lib/clang/20 -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 _GLIBCXX_ASSERTIONS -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-20/lib/clang/20/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-2025-01-20-090804-167946-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 { do { } while (false); MOZ_ReportCrash
("" "NS_SUCCEEDED(mBrowsingContext->SetDefaultLoadFlags(defaultLoadFlags))"
, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 745); AnnotateMozCrashReason("MOZ_CRASH(" "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 { do { } while (false); MOZ_ReportCrash("" "NS_SUCCEEDED(topWc->SetSHEntryHasUserInteraction(true))"
, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 838); AnnotateMozCrashReason("MOZ_CRASH(" "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(std::size(table) > 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;
2168 if (!aValue && mItemType == typeChrome &&
2169 !(parent = GetInProcessParentDocshell())) {
2170 // Window dragging is always allowed for top level
2171 // chrome docshells.
2172 return NS_ERROR_FAILURE;
2173 }
2174 mWindowDraggingAllowed = aValue;
2175 return NS_OK;
2176}
2177
2178NS_IMETHODIMPnsresult
2179nsDocShell::GetWindowDraggingAllowed(bool* aValue) {
2180 // window dragging regions in CSS (-moz-window-drag:drag)
2181 // can be slow. Default behavior is to only allow it for
2182 // chrome top level windows.
2183 RefPtr<nsDocShell> parent;
2184 if (mItemType == typeChrome && !(parent = GetInProcessParentDocshell())) {
2185 // Top level chrome window
2186 *aValue = true;
2187 } else {
2188 *aValue = mWindowDraggingAllowed;
2189 }
2190 return NS_OK;
2191}
2192
2193NS_IMETHODIMPnsresult
2194nsDocShell::GetCurrentDocumentChannel(nsIChannel** aResult) {
2195 NS_IF_ADDREF(*aResult = GetCurrentDocChannel())ns_if_addref(*aResult = GetCurrentDocChannel());
2196 return NS_OK;
2197}
2198
2199nsIChannel* nsDocShell::GetCurrentDocChannel() {
2200 if (mDocumentViewer) {
2201 Document* doc = mDocumentViewer->GetDocument();
2202 if (doc) {
2203 return doc->GetChannel();
2204 }
2205 }
2206 return nullptr;
2207}
2208
2209NS_IMETHODIMPnsresult
2210nsDocShell::AddWeakScrollObserver(nsIScrollObserver* aObserver) {
2211 nsWeakPtr weakObs = do_GetWeakReference(aObserver);
2212 if (!weakObs) {
2213 return NS_ERROR_FAILURE;
2214 }
2215 mScrollObservers.AppendElement(weakObs);
2216 return NS_OK;
2217}
2218
2219NS_IMETHODIMPnsresult
2220nsDocShell::RemoveWeakScrollObserver(nsIScrollObserver* aObserver) {
2221 nsWeakPtr obs = do_GetWeakReference(aObserver);
2222 return mScrollObservers.RemoveElement(obs) ? NS_OK : NS_ERROR_FAILURE;
2223}
2224
2225void nsDocShell::NotifyAsyncPanZoomStarted() {
2226 nsTObserverArray<nsWeakPtr>::ForwardIterator iter(mScrollObservers);
2227 while (iter.HasMore()) {
2228 nsWeakPtr ref = iter.GetNext();
2229 nsCOMPtr<nsIScrollObserver> obs = do_QueryReferent(ref);
2230 if (obs) {
2231 obs->AsyncPanZoomStarted();
2232 } else {
2233 iter.Remove();
2234 }
2235 }
2236}
2237
2238void nsDocShell::NotifyAsyncPanZoomStopped() {
2239 nsTObserverArray<nsWeakPtr>::ForwardIterator iter(mScrollObservers);
2240 while (iter.HasMore()) {
2241 nsWeakPtr ref = iter.GetNext();
2242 nsCOMPtr<nsIScrollObserver> obs = do_QueryReferent(ref);
2243 if (obs) {
2244 obs->AsyncPanZoomStopped();
2245 } else {
2246 iter.Remove();
2247 }
2248 }
2249}
2250
2251NS_IMETHODIMPnsresult
2252nsDocShell::NotifyScrollObservers() {
2253 nsTObserverArray<nsWeakPtr>::ForwardIterator iter(mScrollObservers);
2254 while (iter.HasMore()) {
2255 nsWeakPtr ref = iter.GetNext();
2256 nsCOMPtr<nsIScrollObserver> obs = do_QueryReferent(ref);
2257 if (obs) {
2258 obs->ScrollPositionChanged();
2259 } else {
2260 iter.Remove();
2261 }
2262 }
2263 return NS_OK;
2264}
2265
2266//*****************************************************************************
2267// nsDocShell::nsIDocShellTreeItem
2268//*****************************************************************************
2269
2270NS_IMETHODIMPnsresult
2271nsDocShell::GetName(nsAString& aName) {
2272 aName = mBrowsingContext->Name();
2273 return NS_OK;
2274}
2275
2276NS_IMETHODIMPnsresult
2277nsDocShell::SetName(const nsAString& aName) {
2278 return mBrowsingContext->SetName(aName);
2279}
2280
2281NS_IMETHODIMPnsresult
2282nsDocShell::NameEquals(const nsAString& aName, bool* aResult) {
2283 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"
, 2283); return NS_ERROR_INVALID_POINTER; } } while (false)
;
2284 *aResult = mBrowsingContext->NameEquals(aName);
2285 return NS_OK;
2286}
2287
2288NS_IMETHODIMPnsresult
2289nsDocShell::GetCustomUserAgent(nsAString& aCustomUserAgent) {
2290 mBrowsingContext->GetCustomUserAgent(aCustomUserAgent);
2291 return NS_OK;
2292}
2293
2294NS_IMETHODIMPnsresult
2295nsDocShell::SetCustomUserAgent(const nsAString& aCustomUserAgent) {
2296 if (mWillChangeProcess) {
2297 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"
, 2297)
;
2298 return NS_ERROR_FAILURE;
2299 }
2300
2301 return mBrowsingContext->SetCustomUserAgent(aCustomUserAgent);
2302}
2303
2304NS_IMETHODIMPnsresult
2305nsDocShell::ClearCachedPlatform() {
2306 nsCOMPtr<nsPIDOMWindowInner> win =
2307 mScriptGlobal ? mScriptGlobal->GetCurrentInnerWindow() : nullptr;
2308 if (win) {
2309 Navigator* navigator = win->Navigator();
2310 if (navigator) {
2311 navigator->ClearPlatformCache();
2312 }
2313 }
2314
2315 return NS_OK;
2316}
2317
2318NS_IMETHODIMPnsresult
2319nsDocShell::ClearCachedUserAgent() {
2320 nsCOMPtr<nsPIDOMWindowInner> win =
2321 mScriptGlobal ? mScriptGlobal->GetCurrentInnerWindow() : nullptr;
2322 if (win) {
2323 Navigator* navigator = win->Navigator();
2324 if (navigator) {
2325 navigator->ClearUserAgentCache();
2326 }
2327 }
2328
2329 return NS_OK;
2330}
2331
2332/* virtual */
2333int32_t nsDocShell::ItemType() { return mItemType; }
2334
2335NS_IMETHODIMPnsresult
2336nsDocShell::GetItemType(int32_t* aItemType) {
2337 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"
, 2337); return NS_ERROR_INVALID_POINTER; } } while (false)
;
2338
2339 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"
, 2340); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "(mBrowsingContext->IsContent() ? typeContent : typeChrome) == mItemType"
")"); do { *((volatile int*)__null) = 2340; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2340 (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"
, 2340); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "(mBrowsingContext->IsContent() ? typeContent : typeChrome) == mItemType"
")"); do { *((volatile int*)__null) = 2340; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2341 *aItemType = mItemType;
2342 return NS_OK;
2343}
2344
2345NS_IMETHODIMPnsresult
2346nsDocShell::GetInProcessParent(nsIDocShellTreeItem** aParent) {
2347 if (!mParent) {
2348 *aParent = nullptr;
2349 } else {
2350 CallQueryInterface(mParent, aParent);
2351 }
2352 // Note that in the case when the parent is not an nsIDocShellTreeItem we
2353 // don't want to throw; we just want to return null.
2354 return NS_OK;
2355}
2356
2357// With Fission, related nsDocShell objects may exist in a different process. In
2358// that case, this method will return `nullptr`, despite a parent nsDocShell
2359// object existing.
2360//
2361// Prefer using `BrowsingContext::Parent()`, which will succeed even if the
2362// parent entry is not in the current process, and handle the case where the
2363// parent nsDocShell is inaccessible.
2364already_AddRefed<nsDocShell> nsDocShell::GetInProcessParentDocshell() {
2365 nsCOMPtr<nsIDocShell> docshell = do_QueryInterface(GetAsSupports(mParent));
2366 return docshell.forget().downcast<nsDocShell>();
2367}
2368
2369void nsDocShell::MaybeCreateInitialClientSource(nsIPrincipal* aPrincipal) {
2370 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"
, 2370); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mIsBeingDestroyed"
")"); do { *((volatile int*)__null) = 2370; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2371
2372 // If there is an existing document then there is no need to create
2373 // a client for a future initial about:blank document.
2374 if (mScriptGlobal && mScriptGlobal->GetCurrentInnerWindow() &&
2375 mScriptGlobal->GetCurrentInnerWindow()->GetExtantDoc()) {
2376 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"
, 2377); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "mScriptGlobal->GetCurrentInnerWindow()->GetClientInfo().isSome()"
")"); do { *((volatile int*)__null) = 2377; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2377 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"
, 2377); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "mScriptGlobal->GetCurrentInnerWindow()->GetClientInfo().isSome()"
")"); do { *((volatile int*)__null) = 2377; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2378 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"
, 2378); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "!mInitialClientSource"
")"); do { *((volatile int*)__null) = 2378; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2379 return;
2380 }
2381
2382 // Don't recreate the initial client source. We call this multiple times
2383 // when DoChannelLoad() is called before CreateAboutBlankDocumentViewer.
2384 if (mInitialClientSource) {
2385 return;
2386 }
2387
2388 // Don't pre-allocate the client when we are sandboxed. The inherited
2389 // principal does not take sandboxing into account.
2390 // TODO: Refactor sandboxing principal code out so we can use it here.
2391 if (!aPrincipal && mBrowsingContext->GetSandboxFlags()) {
2392 return;
2393 }
2394
2395 // We cannot get inherited foreign partitioned principal here. Instead, we
2396 // directly check which principal we want to inherit for the service worker.
2397 nsIPrincipal* principal =
2398 aPrincipal
2399 ? aPrincipal
2400 : GetInheritedPrincipal(
2401 false, StoragePrincipalHelper::
2402 ShouldUsePartitionPrincipalForServiceWorker(this));
2403
2404 // Sometimes there is no principal available when we are called from
2405 // CreateAboutBlankDocumentViewer. For example, sometimes the principal
2406 // is only extracted from the load context after the document is created
2407 // in Document::ResetToURI(). Ideally we would do something similar
2408 // here, but for now lets just avoid the issue by not preallocating the
2409 // client.
2410 if (!principal) {
2411 return;
2412 }
2413
2414 nsCOMPtr<nsPIDOMWindowOuter> win = GetWindow();
2415 if (!win) {
2416 return;
2417 }
2418
2419 mInitialClientSource = ClientManager::CreateSource(
2420 ClientType::Window, GetMainThreadSerialEventTarget(), principal);
2421 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"
, 2421); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "mInitialClientSource"
")"); do { *((volatile int*)__null) = 2421; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2422
2423 // Mark the initial client as execution ready, but owned by the docshell.
2424 // If the client is actually used this will cause ClientSource to force
2425 // the creation of the initial about:blank by calling
2426 // nsDocShell::GetDocument().
2427 mInitialClientSource->DocShellExecutionReady(this);
2428
2429 // Next, check to see if the parent is controlled.
2430 nsCOMPtr<nsIDocShell> parent = GetInProcessParentDocshell();
2431 nsPIDOMWindowOuter* parentOuter = parent ? parent->GetWindow() : nullptr;
2432 nsPIDOMWindowInner* parentInner =
2433 parentOuter ? parentOuter->GetCurrentInnerWindow() : nullptr;
2434 if (!parentInner) {
2435 return;
2436 }
2437
2438 nsCOMPtr<nsIURI> uri;
2439 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 { do { } while (false); MOZ_ReportCrash("" "NS_SUCCEEDED(NS_NewURI(getter_AddRefs(uri), \"about:blank\"_ns))"
, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 2439); AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED(NS_NewURI(getter_AddRefs(uri), \"about:blank\"_ns))"
")"); do { *((volatile int*)__null) = 2439; __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
;
2440
2441 // We're done if there is no parent controller or if this docshell
2442 // is not permitted to control for some reason.
2443 Maybe<ServiceWorkerDescriptor> controller(parentInner->GetController());
2444 if (controller.isNothing() ||
2445 !ServiceWorkerAllowedToControlWindow(principal, uri)) {
2446 return;
2447 }
2448
2449 mInitialClientSource->InheritController(controller.ref());
2450}
2451
2452Maybe<ClientInfo> nsDocShell::GetInitialClientInfo() const {
2453 if (mInitialClientSource) {
2454 Maybe<ClientInfo> result;
2455 result.emplace(mInitialClientSource->Info());
2456 return result;
2457 }
2458
2459 nsPIDOMWindowInner* innerWindow =
2460 mScriptGlobal ? mScriptGlobal->GetCurrentInnerWindow() : nullptr;
2461 Document* doc = innerWindow ? innerWindow->GetExtantDoc() : nullptr;
2462
2463 if (!doc || !doc->IsInitialDocument()) {
2464 return Maybe<ClientInfo>();
2465 }
2466
2467 return innerWindow->GetClientInfo();
2468}
2469
2470nsresult nsDocShell::SetDocLoaderParent(nsDocLoader* aParent) {
2471 bool wasFrame = IsSubframe();
2472
2473 nsresult rv = nsDocLoader::SetDocLoaderParent(aParent);
2474 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"
, 2474); return rv; } } while (false)
;
2475
2476 nsCOMPtr<nsISupportsPriority> priorityGroup = do_QueryInterface(mLoadGroup);
2477 if (wasFrame != IsSubframe() && priorityGroup) {
2478 priorityGroup->AdjustPriority(wasFrame ? -1 : 1);
2479 }
2480
2481 // Curse ambiguous nsISupports inheritance!
2482 nsISupports* parent = GetAsSupports(aParent);
2483
2484 // If parent is another docshell, we inherit all their flags for
2485 // allowing plugins, scripting etc.
2486 bool value;
2487 nsCOMPtr<nsIDocShell> parentAsDocShell(do_QueryInterface(parent));
2488
2489 if (parentAsDocShell) {
2490 if (mAllowMetaRedirects &&
2491 NS_SUCCEEDED(parentAsDocShell->GetAllowMetaRedirects(&value))((bool)(__builtin_expect(!!(!NS_FAILED_impl(parentAsDocShell->
GetAllowMetaRedirects(&value))), 1)))
) {
2492 SetAllowMetaRedirects(value);
2493 }
2494 if (mAllowSubframes &&
2495 NS_SUCCEEDED(parentAsDocShell->GetAllowSubframes(&value))((bool)(__builtin_expect(!!(!NS_FAILED_impl(parentAsDocShell->
GetAllowSubframes(&value))), 1)))
) {
2496 SetAllowSubframes(value);
2497 }
2498 if (mAllowImages &&
2499 NS_SUCCEEDED(parentAsDocShell->GetAllowImages(&value))((bool)(__builtin_expect(!!(!NS_FAILED_impl(parentAsDocShell->
GetAllowImages(&value))), 1)))
) {
2500 SetAllowImages(value);
2501 }
2502 SetAllowMedia(parentAsDocShell->GetAllowMedia() && mAllowMedia);
2503 if (mAllowWindowControl &&
2504 NS_SUCCEEDED(parentAsDocShell->GetAllowWindowControl(&value))((bool)(__builtin_expect(!!(!NS_FAILED_impl(parentAsDocShell->
GetAllowWindowControl(&value))), 1)))
) {
2505 SetAllowWindowControl(value);
2506 }
2507 if (NS_FAILED(parentAsDocShell->GetAllowDNSPrefetch(&value))((bool)(__builtin_expect(!!(NS_FAILED_impl(parentAsDocShell->
GetAllowDNSPrefetch(&value))), 0)))
) {
2508 value = false;
2509 }
2510 SetAllowDNSPrefetch(mAllowDNSPrefetch && value);
2511 }
2512
2513 nsCOMPtr<nsIURIContentListener> parentURIListener(do_GetInterface(parent));
2514 if (parentURIListener) {
2515 mContentListener->SetParentContentListener(parentURIListener);
2516 }
2517
2518 return NS_OK;
2519}
2520
2521void nsDocShell::MaybeRestoreWindowName() {
2522 if (!StaticPrefs::privacy_window_name_update_enabled()) {
2523 return;
2524 }
2525
2526 // We only restore window.name for the top-level content.
2527 if (!mBrowsingContext->IsTopContent()) {
2528 return;
2529 }
2530
2531 nsAutoString name;
2532
2533 // Following implements https://html.spec.whatwg.org/#history-traversal:
2534 // Step 4.4. Check if the loading entry has a name.
2535
2536 if (mLSHE) {
2537 mLSHE->GetName(name);
2538 }
2539
2540 if (mLoadingEntry) {
2541 name = mLoadingEntry->mInfo.GetName();
2542 }
2543
2544 if (name.IsEmpty()) {
2545 return;
2546 }
2547
2548 // Step 4.4.1. Set the name to the browsing context.
2549 Unused << mBrowsingContext->SetName(name);
2550
2551 // Step 4.4.2. Clear the name of all entries that are contiguous and
2552 // same-origin with the loading entry.
2553 if (mLSHE) {
2554 nsSHistory::WalkContiguousEntries(
2555 mLSHE, [](nsISHEntry* aEntry) { aEntry->SetName(EmptyString()); });
2556 }
2557
2558 if (mLoadingEntry) {
2559 // Clear the name of the session entry in the child side. For parent side,
2560 // the clearing will be done when we commit the history to the parent.
2561 mLoadingEntry->mInfo.SetName(EmptyString());
2562 }
2563}
2564
2565void nsDocShell::StoreWindowNameToSHEntries() {
2566 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"
, 2566); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mBrowsingContext->IsTopContent()"
")"); do { *((volatile int*)__null) = 2566; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2567
2568 nsAutoString name;
2569 mBrowsingContext->GetName(name);
2570
2571 if (mOSHE) {
2572 nsSHistory::WalkContiguousEntries(
2573 mOSHE, [&](nsISHEntry* aEntry) { aEntry->SetName(name); });
2574 }
2575
2576 if (mozilla::SessionHistoryInParent()) {
2577 if (XRE_IsParentProcess()) {
2578 SessionHistoryEntry* entry =
2579 mBrowsingContext->Canonical()->GetActiveSessionHistoryEntry();
2580 if (entry) {
2581 nsSHistory::WalkContiguousEntries(
2582 entry, [&](nsISHEntry* aEntry) { aEntry->SetName(name); });
2583 }
2584 } else {
2585 // Ask parent process to store the name in entries.
2586 mozilla::Unused
2587 << ContentChild::GetSingleton()
2588 ->SendSessionHistoryEntryStoreWindowNameInContiguousEntries(
2589 mBrowsingContext, name);
2590 }
2591 }
2592}
2593
2594NS_IMETHODIMPnsresult
2595nsDocShell::GetInProcessSameTypeParent(nsIDocShellTreeItem** aParent) {
2596 if (BrowsingContext* parentBC = mBrowsingContext->GetParent()) {
2597 *aParent = do_AddRef(parentBC->GetDocShell()).take();
2598 }
2599 return NS_OK;
2600}
2601
2602NS_IMETHODIMPnsresult
2603nsDocShell::GetInProcessRootTreeItem(nsIDocShellTreeItem** aRootTreeItem) {
2604 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"
, 2604); return NS_ERROR_INVALID_POINTER; } } while (false)
;
2605
2606 RefPtr<nsDocShell> root = this;
2607 RefPtr<nsDocShell> parent = root->GetInProcessParentDocshell();
2608 while (parent) {
2609 root = parent;
2610 parent = root->GetInProcessParentDocshell();
2611 }
2612
2613 root.forget(aRootTreeItem);
2614 return NS_OK;
2615}
2616
2617NS_IMETHODIMPnsresult
2618nsDocShell::GetInProcessSameTypeRootTreeItem(
2619 nsIDocShellTreeItem** aRootTreeItem) {
2620 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"
, 2620); return NS_ERROR_INVALID_POINTER; } } while (false)
;
2621 *aRootTreeItem = static_cast<nsIDocShellTreeItem*>(this);
2622
2623 nsCOMPtr<nsIDocShellTreeItem> parent;
2624 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"
, 2625); return NS_ERROR_FAILURE; } } while (false)
2625 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"
, 2625); return NS_ERROR_FAILURE; } } while (false)
;
2626 while (parent) {
2627 *aRootTreeItem = parent;
2628 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"
, 2630); return NS_ERROR_FAILURE; } } while (false)
2629 (*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"
, 2630); return NS_ERROR_FAILURE; } } while (false)
2630 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"
, 2630); return NS_ERROR_FAILURE; } } while (false)
;
2631 }
2632 NS_ADDREF(*aRootTreeItem)(*aRootTreeItem)->AddRef();
2633 return NS_OK;
2634}
2635
2636NS_IMETHODIMPnsresult
2637nsDocShell::GetTreeOwner(nsIDocShellTreeOwner** aTreeOwner) {
2638 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"
, 2638); return NS_ERROR_INVALID_POINTER; } } while (false)
;
2639
2640 *aTreeOwner = mTreeOwner;
2641 NS_IF_ADDREF(*aTreeOwner)ns_if_addref(*aTreeOwner);
2642 return NS_OK;
2643}
2644
2645NS_IMETHODIMPnsresult
2646nsDocShell::SetTreeOwner(nsIDocShellTreeOwner* aTreeOwner) {
2647 if (mIsBeingDestroyed && aTreeOwner) {
2648 return NS_ERROR_FAILURE;
2649 }
2650
2651 // Don't automatically set the progress based on the tree owner for frames
2652 if (!IsSubframe()) {
2653 nsCOMPtr<nsIWebProgress> webProgress =
2654 do_QueryInterface(GetAsSupports(this));
2655
2656 if (webProgress) {
2657 nsCOMPtr<nsIWebProgressListener> oldListener =
2658 do_QueryInterface(mTreeOwner);
2659 nsCOMPtr<nsIWebProgressListener> newListener =
2660 do_QueryInterface(aTreeOwner);
2661
2662 if (oldListener) {
2663 webProgress->RemoveProgressListener(oldListener);
2664 }
2665
2666 if (newListener) {
2667 webProgress->AddProgressListener(newListener,
2668 nsIWebProgress::NOTIFY_ALL);
2669 }
2670 }
2671 }
2672
2673 mTreeOwner = aTreeOwner; // Weak reference per API
2674
2675 for (auto* childDocLoader : mChildList.ForwardRange()) {
2676 nsCOMPtr<nsIDocShellTreeItem> child = do_QueryObject(childDocLoader);
2677 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"
, 2677); return NS_ERROR_FAILURE; } } while (false)
;
2678
2679 if (child->ItemType() == mItemType) {
2680 child->SetTreeOwner(aTreeOwner);
2681 }
2682 }
2683
2684 // If we're in the content process and have had a TreeOwner set on us, extract
2685 // our BrowserChild actor. If we've already had our BrowserChild set, assert
2686 // that it hasn't changed.
2687 if (mTreeOwner && XRE_IsContentProcess()) {
2688 nsCOMPtr<nsIBrowserChild> newBrowserChild = do_GetInterface(mTreeOwner);
2689 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"
, 2690); AnnotateMozCrashReason("MOZ_ASSERT" "(" "newBrowserChild"
") (" "No BrowserChild actor for tree owner in Content!" ")"
); do { *((volatile int*)__null) = 2690; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2690 "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"
, 2690); AnnotateMozCrashReason("MOZ_ASSERT" "(" "newBrowserChild"
") (" "No BrowserChild actor for tree owner in Content!" ")"
); do { *((volatile int*)__null) = 2690; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2691
2692 if (mBrowserChild) {
2693 nsCOMPtr<nsIBrowserChild> oldBrowserChild =
2694 do_QueryReferent(mBrowserChild);
2695 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"
, 2697); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "oldBrowserChild == newBrowserChild"
") (" "Cannot change BrowserChild during nsDocShell lifetime!"
")"); do { *((volatile int*)__null) = 2697; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2696 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"
, 2697); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "oldBrowserChild == newBrowserChild"
") (" "Cannot change BrowserChild during nsDocShell lifetime!"
")"); do { *((volatile int*)__null) = 2697; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2697 "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"
, 2697); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "oldBrowserChild == newBrowserChild"
") (" "Cannot change BrowserChild during nsDocShell lifetime!"
")"); do { *((volatile int*)__null) = 2697; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2698 } else {
2699 mBrowserChild = do_GetWeakReference(newBrowserChild);
2700 }
2701 }
2702
2703 return NS_OK;
2704}
2705
2706NS_IMETHODIMPnsresult
2707nsDocShell::GetHistoryID(nsID& aID) {
2708 aID = mBrowsingContext->GetHistoryID();
2709 return NS_OK;
2710}
2711
2712const nsID& nsDocShell::HistoryID() { return mBrowsingContext->GetHistoryID(); }
2713
2714NS_IMETHODIMPnsresult
2715nsDocShell::GetIsInUnload(bool* aIsInUnload) {
2716 *aIsInUnload = mFiredUnloadEvent;
2717 return NS_OK;
2718}
2719
2720NS_IMETHODIMPnsresult
2721nsDocShell::GetInProcessChildCount(int32_t* aChildCount) {
2722 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"
, 2722); return NS_ERROR_INVALID_POINTER; } } while (false)
;
2723 *aChildCount = mChildList.Length();
2724 return NS_OK;
2725}
2726
2727NS_IMETHODIMPnsresult
2728nsDocShell::AddChild(nsIDocShellTreeItem* aChild) {
2729 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"
, 2729); return NS_ERROR_INVALID_POINTER; } } while (false)
;
2730
2731 RefPtr<nsDocLoader> childAsDocLoader = GetAsDocLoader(aChild);
2732 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"
, 2732); return NS_ERROR_UNEXPECTED; } } while (false)
;
2733
2734 // Make sure we're not creating a loop in the docshell tree
2735 nsDocLoader* ancestor = this;
2736 do {
2737 if (childAsDocLoader == ancestor) {
2738 return NS_ERROR_ILLEGAL_VALUE;
2739 }
2740 ancestor = ancestor->GetParent();
2741 } while (ancestor);
2742
2743 // Make sure to remove the child from its current parent.
2744 nsDocLoader* childsParent = childAsDocLoader->GetParent();
2745 if (childsParent) {
2746 nsresult rv = childsParent->RemoveChildLoader(childAsDocLoader);
2747 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"
, 2747); return rv; } } while (false)
;
2748 }
2749
2750 // Make sure to clear the treeowner in case this child is a different type
2751 // from us.
2752 aChild->SetTreeOwner(nullptr);
2753
2754 nsresult res = AddChildLoader(childAsDocLoader);
2755 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"
, 2755); return res; } } while (false)
;
2756 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"
, 2757); MOZ_PretendNoReturn(); } } while (0)
2757 "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"
, 2757); MOZ_PretendNoReturn(); } } while (0)
;
2758
2759 /* Set the child's global history if the parent has one */
2760 if (mBrowsingContext->GetUseGlobalHistory()) {
2761 // childDocShell->SetUseGlobalHistory(true);
2762 // this should be set through BC inherit
2763 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"
, 2763); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aChild->GetBrowsingContext()->GetUseGlobalHistory()"
")"); do { *((volatile int*)__null) = 2763; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2764 }
2765
2766 if (aChild->ItemType() != mItemType) {
2767 return NS_OK;
2768 }
2769
2770 aChild->SetTreeOwner(mTreeOwner);
2771
2772 nsCOMPtr<nsIDocShell> childAsDocShell(do_QueryInterface(aChild));
2773 if (!childAsDocShell) {
2774 return NS_OK;
2775 }
2776
2777 // charset, style-disabling, and zoom will be inherited in SetupNewViewer()
2778
2779 // Now take this document's charset and set the child's parentCharset field
2780 // to it. We'll later use that field, in the loading process, for the
2781 // charset choosing algorithm.
2782 // If we fail, at any point, we just return NS_OK.
2783 // This code has some performance impact. But this will be reduced when
2784 // the current charset will finally be stored as an Atom, avoiding the
2785 // alias resolution extra look-up.
2786
2787 // we are NOT going to propagate the charset is this Chrome's docshell
2788 if (mItemType == nsIDocShellTreeItem::typeChrome) {
2789 return NS_OK;
2790 }
2791
2792 // get the parent's current charset
2793 if (!mDocumentViewer) {
2794 return NS_OK;
2795 }
2796 Document* doc = mDocumentViewer->GetDocument();
2797 if (!doc) {
2798 return NS_OK;
2799 }
2800
2801 const Encoding* parentCS = doc->GetDocumentCharacterSet();
2802 int32_t charsetSource = doc->GetDocumentCharacterSetSource();
2803 // set the child's parentCharset
2804 childAsDocShell->SetParentCharset(parentCS, charsetSource,
2805 doc->NodePrincipal());
2806
2807 // printf("### 1 >>> Adding child. Parent CS = %s. ItemType = %d.\n",
2808 // NS_LossyConvertUTF16toASCII(parentCS).get(), mItemType);
2809
2810 return NS_OK;
2811}
2812
2813NS_IMETHODIMPnsresult
2814nsDocShell::RemoveChild(nsIDocShellTreeItem* aChild) {
2815 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"
, 2815); return NS_ERROR_INVALID_POINTER; } } while (false)
;
2816
2817 RefPtr<nsDocLoader> childAsDocLoader = GetAsDocLoader(aChild);
2818 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"
, 2818); return NS_ERROR_UNEXPECTED; } } while (false)
;
2819
2820 nsresult rv = RemoveChildLoader(childAsDocLoader);
2821 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"
, 2821); return rv; } } while (false)
;
2822
2823 aChild->SetTreeOwner(nullptr);
2824
2825 return nsDocLoader::AddDocLoaderAsChildOfRoot(childAsDocLoader);
2826}
2827
2828NS_IMETHODIMPnsresult
2829nsDocShell::GetInProcessChildAt(int32_t aIndex, nsIDocShellTreeItem** aChild) {
2830 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"
, 2830); return NS_ERROR_INVALID_POINTER; } } while (false)
;
2831
2832 RefPtr<nsDocShell> child = GetInProcessChildAt(aIndex);
2833 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"
, 2833); return NS_ERROR_UNEXPECTED; } } while (false)
;
2834
2835 child.forget(aChild);
2836
2837 return NS_OK;
2838}
2839
2840nsDocShell* nsDocShell::GetInProcessChildAt(int32_t aIndex) {
2841#ifdef DEBUG1
2842 if (aIndex < 0) {
2843 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"
, 2843)
;
2844 } else if (static_cast<uint32_t>(aIndex) >= mChildList.Length()) {
2845 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"
, 2845)
;
2846 }
2847#endif
2848
2849 nsIDocumentLoader* child = ChildAt(aIndex);
2850
2851 // child may be nullptr here.
2852 return static_cast<nsDocShell*>(child);
2853}
2854
2855nsresult nsDocShell::AddChildSHEntry(nsISHEntry* aCloneRef,
2856 nsISHEntry* aNewEntry,
2857 int32_t aChildOffset, uint32_t aLoadType,
2858 bool aCloneChildren) {
2859 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"
, 2859); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mozilla::SessionHistoryInParent()"
")"); do { *((volatile int*)__null) = 2859; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2860 nsresult rv = NS_OK;
2861
2862 if (mLSHE && aLoadType != LOAD_PUSHSTATE) {
2863 /* You get here if you are currently building a
2864 * hierarchy ie.,you just visited a frameset page
2865 */
2866 if (NS_FAILED(mLSHE->ReplaceChild(aNewEntry))((bool)(__builtin_expect(!!(NS_FAILED_impl(mLSHE->ReplaceChild
(aNewEntry))), 0)))
) {
2867 rv = mLSHE->AddChild(aNewEntry, aChildOffset);
2868 }
2869 } else if (!aCloneRef) {
2870 /* This is an initial load in some subframe. Just append it if we can */
2871 if (mOSHE) {
2872 rv = mOSHE->AddChild(aNewEntry, aChildOffset, UseRemoteSubframes());
2873 }
2874 } else {
2875 RefPtr<ChildSHistory> shistory = GetRootSessionHistory();
2876 if (shistory) {
2877 rv = shistory->LegacySHistory()->AddChildSHEntryHelper(
2878 aCloneRef, aNewEntry, mBrowsingContext->Top(), aCloneChildren);
2879 }
2880 }
2881 return rv;
2882}
2883
2884nsresult nsDocShell::AddChildSHEntryToParent(nsISHEntry* aNewEntry,
2885 int32_t aChildOffset,
2886 bool aCloneChildren) {
2887 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"
, 2887); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mozilla::SessionHistoryInParent()"
")"); do { *((volatile int*)__null) = 2887; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2888 /* You will get here when you are in a subframe and
2889 * a new url has been loaded on you.
2890 * The mOSHE in this subframe will be the previous url's
2891 * mOSHE. This mOSHE will be used as the identification
2892 * for this subframe in the CloneAndReplace function.
2893 */
2894
2895 // In this case, we will end up calling AddEntry, which increases the
2896 // current index by 1
2897 RefPtr<ChildSHistory> rootSH = GetRootSessionHistory();
2898 if (rootSH) {
2899 mPreviousEntryIndex = rootSH->Index();
2900 }
2901
2902 nsresult rv;
2903 // XXX(farre): this is not Fission safe, expect errors. This never
2904 // get's executed once session history in the parent is enabled.
2905 nsCOMPtr<nsIDocShell> parent = do_QueryInterface(GetAsSupports(mParent), &rv);
2906 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"
, 2909); } } while (false)
2907 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"
, 2909); } } while (false)
2908 "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"
, 2909); } } while (false)
2909 "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"
, 2909); } } while (false)
;
2910 if (parent) {
2911 rv = nsDocShell::Cast(parent)->AddChildSHEntry(
2912 mOSHE, aNewEntry, aChildOffset, mLoadType, aCloneChildren);
2913 }
2914
2915 if (rootSH) {
2916 mLoadedEntryIndex = rootSH->Index();
2917
2918 if (MOZ_UNLIKELY(MOZ_LOG_TEST(gPageCacheLog, LogLevel::Verbose))(__builtin_expect(!!((__builtin_expect(!!(mozilla::detail::log_test
(gPageCacheLog, LogLevel::Verbose)), 0))), 0))
) {
2919 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)
2920 ("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)
2921 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)
;
2922 }
2923 }
2924
2925 return rv;
2926}
2927
2928NS_IMETHODIMPnsresult
2929nsDocShell::GetCurrentSHEntry(nsISHEntry** aEntry, bool* aOSHE) {
2930 *aOSHE = false;
2931 *aEntry = nullptr;
2932 if (mLSHE) {
2933 NS_ADDREF(*aEntry = mLSHE)(*aEntry = mLSHE)->AddRef();
2934 } else if (mOSHE) {
2935 NS_ADDREF(*aEntry = mOSHE)(*aEntry = mOSHE)->AddRef();
2936 *aOSHE = true;
2937 }
2938 return NS_OK;
2939}
2940
2941NS_IMETHODIMPnsresult nsDocShell::SynchronizeLayoutHistoryState() {
2942 if (mActiveEntry && mActiveEntry->GetLayoutHistoryState() &&
2943 mBrowsingContext) {
2944 if (XRE_IsContentProcess()) {
2945 dom::ContentChild* contentChild = dom::ContentChild::GetSingleton();
2946 if (contentChild) {
2947 contentChild->SendSynchronizeLayoutHistoryState(
2948 mBrowsingContext, mActiveEntry->GetLayoutHistoryState());
2949 }
2950 } else {
2951 SessionHistoryEntry* entry =
2952 mBrowsingContext->Canonical()->GetActiveSessionHistoryEntry();
2953 if (entry) {
2954 entry->SetLayoutHistoryState(mActiveEntry->GetLayoutHistoryState());
2955 }
2956 }
2957 if (mLoadingEntry &&
2958 mLoadingEntry->mInfo.SharedId() == mActiveEntry->SharedId()) {
2959 mLoadingEntry->mInfo.SetLayoutHistoryState(
2960 mActiveEntry->GetLayoutHistoryState());
2961 }
2962 }
2963
2964 return NS_OK;
2965}
2966
2967void nsDocShell::SetLoadGroupDefaultLoadFlags(nsLoadFlags aLoadFlags) {
2968 if (mLoadGroup) {
2969 mLoadGroup->SetDefaultLoadFlags(aLoadFlags);
2970 } else {
2971 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"
, 2973)
2972 "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"
, 2973)
2973 "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"
, 2973)
;
2974 }
2975}
2976
2977nsIScriptGlobalObject* nsDocShell::GetScriptGlobalObject() {
2978 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"
, 2978); return nullptr; } } while (false)
;
2979 return mScriptGlobal;
2980}
2981
2982Document* nsDocShell::GetDocument() {
2983 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"
, 2983); return nullptr; } } while (false)
;
2984 return mDocumentViewer->GetDocument();
2985}
2986
2987Document* nsDocShell::GetExtantDocument() {
2988 return mDocumentViewer ? mDocumentViewer->GetDocument() : nullptr;
2989}
2990
2991nsPIDOMWindowOuter* nsDocShell::GetWindow() {
2992 if (NS_FAILED(EnsureScriptEnvironment())((bool)(__builtin_expect(!!(NS_FAILED_impl(EnsureScriptEnvironment
())), 0)))
) {
2993 return nullptr;
2994 }
2995 return mScriptGlobal;
2996}
2997
2998NS_IMETHODIMPnsresult
2999nsDocShell::GetDomWindow(mozIDOMWindowProxy** aWindow) {
3000 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"
, 3000); return NS_ERROR_INVALID_POINTER; } } while (false)
;
3001
3002 nsresult rv = EnsureScriptEnvironment();
3003 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"
, 3003); return rv; } } while (false)
;
3004
3005 RefPtr<nsGlobalWindowOuter> window = mScriptGlobal;
3006 window.forget(aWindow);
3007 return NS_OK;
3008}
3009
3010NS_IMETHODIMPnsresult
3011nsDocShell::GetMessageManager(ContentFrameMessageManager** aMessageManager) {
3012 RefPtr<ContentFrameMessageManager> mm;
3013 if (RefPtr<BrowserChild> browserChild = BrowserChild::GetFrom(this)) {
3014 mm = browserChild->GetMessageManager();
3015 } else if (nsPIDOMWindowOuter* win = GetWindow()) {
3016 mm = win->GetMessageManager();
3017 }
3018 mm.forget(aMessageManager);
3019 return NS_OK;
3020}
3021
3022NS_IMETHODIMPnsresult
3023nsDocShell::GetIsNavigating(bool* aOut) {
3024 *aOut = mIsNavigating;
3025 return NS_OK;
3026}
3027
3028void nsDocShell::ClearFrameHistory(nsISHEntry* aEntry) {
3029 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"
, 3029); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mozilla::SessionHistoryInParent()"
")"); do { *((volatile int*)__null) = 3029; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3030 RefPtr<ChildSHistory> rootSH = GetRootSessionHistory();
3031 if (!rootSH || !aEntry) {
3032 return;
3033 }
3034
3035 rootSH->LegacySHistory()->RemoveFrameEntries(aEntry);
3036}
3037
3038//-------------------------------------
3039//-- Helper Method for Print discovery
3040//-------------------------------------
3041bool nsDocShell::NavigationBlockedByPrinting(bool aDisplayErrorDialog) {
3042 if (!mBrowsingContext->Top()->GetIsPrinting()) {
3043 return false;
3044 }
3045 if (aDisplayErrorDialog) {
3046 DisplayLoadError(NS_ERROR_DOCUMENT_IS_PRINTMODE, nullptr, nullptr, nullptr);
3047 }
3048 return true;
3049}
3050
3051bool nsDocShell::IsNavigationAllowed(bool aDisplayPrintErrorDialog,
3052 bool aCheckIfUnloadFired) {
3053 bool isAllowed = !NavigationBlockedByPrinting(aDisplayPrintErrorDialog) &&
3054 (!aCheckIfUnloadFired || !mFiredUnloadEvent);
3055 if (!isAllowed) {
3056 return false;
3057 }
3058 if (!mDocumentViewer) {
3059 return true;
3060 }
3061 bool firingBeforeUnload;
3062 mDocumentViewer->GetBeforeUnloadFiring(&firingBeforeUnload);
3063 return !firingBeforeUnload;
3064}
3065
3066//*****************************************************************************
3067// nsDocShell::nsIWebNavigation
3068//*****************************************************************************
3069
3070NS_IMETHODIMPnsresult
3071nsDocShell::GetCanGoBack(bool* aCanGoBack) {
3072 *aCanGoBack = false;
3073 if (!IsNavigationAllowed(false)) {
3074 return NS_OK; // JS may not handle returning of an error code
3075 }
3076 RefPtr<ChildSHistory> rootSH = GetRootSessionHistory();
3077 if (rootSH) {
3078 *aCanGoBack = rootSH->CanGo(
3079 -1, StaticPrefs::browser_navigation_requireUserInteraction());
3080 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)
3081 ("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)
;
3082
3083 return NS_OK;
3084 }
3085 return NS_ERROR_FAILURE;
3086}
3087
3088NS_IMETHODIMPnsresult
3089nsDocShell::GetCanGoBackIgnoringUserInteraction(bool* aCanGoBack) {
3090 *aCanGoBack = false;
3091 if (!IsNavigationAllowed(false)) {
3092 return NS_OK; // JS may not handle returning of an error code
3093 }
3094 RefPtr<ChildSHistory> rootSH = GetRootSessionHistory();
3095 if (rootSH) {
3096 *aCanGoBack = rootSH->CanGo(-1, false);
3097 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 CanGoBackIgnoringUserInteraction()->%d"
, this, *aCanGoBack); } } while (0)
3098 ("nsDocShell %p CanGoBackIgnoringUserInteraction()->%d", this,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 CanGoBackIgnoringUserInteraction()->%d"
, this, *aCanGoBack); } } while (0)
3099 *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 CanGoBackIgnoringUserInteraction()->%d"
, this, *aCanGoBack); } } while (0)
;
3100
3101 return NS_OK;
3102 }
3103 return NS_ERROR_FAILURE;
3104}
3105
3106NS_IMETHODIMPnsresult
3107nsDocShell::GetCanGoForward(bool* aCanGoForward) {
3108 *aCanGoForward = false;
3109 if (!IsNavigationAllowed(false)) {
3110 return NS_OK; // JS may not handle returning of an error code
3111 }
3112 RefPtr<ChildSHistory> rootSH = GetRootSessionHistory();
3113 if (rootSH) {
3114 *aCanGoForward = rootSH->CanGo(
3115 1, StaticPrefs::browser_navigation_requireUserInteraction());
3116 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)
3117 ("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)
;
3118 return NS_OK;
3119 }
3120 return NS_ERROR_FAILURE;
3121}
3122
3123NS_IMETHODIMPnsresult
3124nsDocShell::GoBack(bool aRequireUserInteraction, bool aUserActivation) {
3125 if (!IsNavigationAllowed()) {
3126 return NS_OK; // JS may not handle returning of an error code
3127 }
3128
3129 auto cleanupIsNavigating = MakeScopeExit([&]() { mIsNavigating = false; });
3130 mIsNavigating = true;
3131
3132 RefPtr<ChildSHistory> rootSH = GetRootSessionHistory();
3133 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"
, 3133); return NS_ERROR_FAILURE; } } while (false)
;
3134 ErrorResult rv;
3135 rootSH->Go(-1, aRequireUserInteraction, aUserActivation, rv);
3136 return rv.StealNSResult();
3137}
3138
3139NS_IMETHODIMPnsresult
3140nsDocShell::GoForward(bool aRequireUserInteraction, bool aUserActivation) {
3141 if (!IsNavigationAllowed()) {
3142 return NS_OK; // JS may not handle returning of an error code
3143 }
3144
3145 auto cleanupIsNavigating = MakeScopeExit([&]() { mIsNavigating = false; });
3146 mIsNavigating = true;
3147
3148 RefPtr<ChildSHistory> rootSH = GetRootSessionHistory();
3149 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"
, 3149); return NS_ERROR_FAILURE; } } while (false)
;
3150 ErrorResult rv;
3151 rootSH->Go(1, aRequireUserInteraction, aUserActivation, rv);
3152 return rv.StealNSResult();
3153}
3154
3155// XXX(nika): We may want to stop exposing this API in the child process? Going
3156// to a specific index from multiple different processes could definitely race.
3157NS_IMETHODIMPnsresult
3158nsDocShell::GotoIndex(int32_t aIndex, bool aUserActivation) {
3159 if (!IsNavigationAllowed()) {
3160 return NS_OK; // JS may not handle returning of an error code
3161 }
3162
3163 auto cleanupIsNavigating = MakeScopeExit([&]() { mIsNavigating = false; });
3164 mIsNavigating = true;
3165
3166 RefPtr<ChildSHistory> rootSH = GetRootSessionHistory();
3167 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"
, 3167); return NS_ERROR_FAILURE; } } while (false)
;
3168
3169 ErrorResult rv;
3170 rootSH->GotoIndex(aIndex, aIndex - rootSH->Index(), false, aUserActivation,
3171 rv);
3172 return rv.StealNSResult();
3173}
3174
3175nsresult nsDocShell::LoadURI(nsIURI* aURI,
3176 const LoadURIOptions& aLoadURIOptions) {
3177 if (!IsNavigationAllowed()) {
3178 return NS_OK; // JS may not handle returning of an error code
3179 }
3180 RefPtr<nsDocShellLoadState> loadState;
3181 nsresult rv = nsDocShellLoadState::CreateFromLoadURIOptions(
3182 mBrowsingContext, aURI, aLoadURIOptions, getter_AddRefs(loadState));
3183 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"
, 3183); AnnotateMozCrashReason("MOZ_ASSERT" "(" "rv != NS_ERROR_MALFORMED_URI"
")"); do { *((volatile int*)__null) = 3183; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3184 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) || !loadState) {
3185 return NS_ERROR_FAILURE;
3186 }
3187
3188 return LoadURI(loadState, true);
3189}
3190
3191NS_IMETHODIMPnsresult
3192nsDocShell::LoadURIFromScript(nsIURI* aURI,
3193 JS::Handle<JS::Value> aLoadURIOptions,
3194 JSContext* aCx) {
3195 // generate dictionary for aLoadURIOptions and forward call
3196 LoadURIOptions loadURIOptions;
3197 if (!loadURIOptions.Init(aCx, aLoadURIOptions)) {
3198 return NS_ERROR_INVALID_ARG;
3199 }
3200 return LoadURI(aURI, loadURIOptions);
3201}
3202
3203nsresult nsDocShell::FixupAndLoadURIString(
3204 const nsAString& aURIString, const LoadURIOptions& aLoadURIOptions) {
3205 if (!IsNavigationAllowed()) {
3206 return NS_OK; // JS may not handle returning of an error code
3207 }
3208
3209 RefPtr<nsDocShellLoadState> loadState;
3210 nsresult rv = nsDocShellLoadState::CreateFromLoadURIOptions(
3211 mBrowsingContext, aURIString, aLoadURIOptions, getter_AddRefs(loadState));
3212
3213 uint32_t loadFlags = aLoadURIOptions.mLoadFlags;
3214 if (NS_ERROR_MALFORMED_URI == rv) {
3215 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)
3216 ("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)
3217 "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)
3218 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)
;
3219
3220 // We need to store a session history entry. We don't have a valid URI, so
3221 // we use about:blank instead.
3222 nsCOMPtr<nsIURI> uri;
3223 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 { do { } while (false); MOZ_ReportCrash("" "NS_SUCCEEDED(NS_NewURI(getter_AddRefs(uri), \"about:blank\"_ns))"
, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 3223); AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED(NS_NewURI(getter_AddRefs(uri), \"about:blank\"_ns))"
")"); do { *((volatile int*)__null) = 3223; __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
;
3224 nsCOMPtr<nsIPrincipal> triggeringPrincipal;
3225 if (aLoadURIOptions.mTriggeringPrincipal) {
3226 triggeringPrincipal = aLoadURIOptions.mTriggeringPrincipal;
3227 } else {
3228 triggeringPrincipal = nsContentUtils::GetSystemPrincipal();
3229 }
3230 if (mozilla::SessionHistoryInParent()) {
3231 mActiveEntry = MakeUnique<SessionHistoryInfo>(
3232 uri, triggeringPrincipal, nullptr, nullptr, nullptr,
3233 nsLiteralCString("text/html"));
3234 mBrowsingContext->SetActiveSessionHistoryEntry(
3235 Nothing(), mActiveEntry.get(), MAKE_LOAD_TYPE(LOAD_NORMAL, loadFlags)((LOAD_NORMAL) | ((loadFlags) << 16)),
3236 /* aUpdatedCacheKey = */ 0);
3237 }
3238 if (DisplayLoadError(rv, nullptr, PromiseFlatStringTPromiseFlatString<char16_t>(aURIString).get(),
3239 nullptr) &&
3240 (loadFlags & LOAD_FLAGS_ERROR_LOAD_CHANGES_RV) != 0) {
3241 return NS_ERROR_LOAD_SHOWED_ERRORPAGE;
3242 }
3243 }
3244
3245 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) || !loadState) {
3246 return NS_ERROR_FAILURE;
3247 }
3248
3249 return LoadURI(loadState, true);
3250}
3251
3252NS_IMETHODIMPnsresult
3253nsDocShell::FixupAndLoadURIStringFromScript(
3254 const nsAString& aURIString, JS::Handle<JS::Value> aLoadURIOptions,
3255 JSContext* aCx) {
3256 // generate dictionary for aLoadURIOptions and forward call
3257 LoadURIOptions loadURIOptions;
3258 if (!loadURIOptions.Init(aCx, aLoadURIOptions)) {
3259 return NS_ERROR_INVALID_ARG;
3260 }
3261 return FixupAndLoadURIString(aURIString, loadURIOptions);
3262}
3263
3264void nsDocShell::UnblockEmbedderLoadEventForFailure(bool aFireFrameErrorEvent) {
3265 // If we're not in a content frame, or are at a BrowsingContext tree boundary,
3266 // such as the content-chrome boundary, don't fire the error event.
3267 if (mBrowsingContext->IsTopContent() || mBrowsingContext->IsChrome()) {
3268 return;
3269 }
3270
3271 // If embedder is same-process, then unblocking the load event is already
3272 // handled by nsDocLoader. Fire the error event on our embedder element if
3273 // requested.
3274 //
3275 // XXX: Bug 1440212 is looking into potentially changing this behaviour to act
3276 // more like the remote case when in-process.
3277 RefPtr<Element> element = mBrowsingContext->GetEmbedderElement();
3278 if (element) {
3279 if (aFireFrameErrorEvent) {
3280 if (RefPtr<nsFrameLoaderOwner> flo = do_QueryObject(element)) {
3281 if (RefPtr<nsFrameLoader> fl = flo->GetFrameLoader()) {
3282 fl->FireErrorEvent();
3283 }
3284 }
3285 }
3286 return;
3287 }
3288
3289 // If we have a cross-process parent document, we must notify it that we no
3290 // longer block its load event. This is necessary for OOP sub-documents
3291 // because error documents do not result in a call to
3292 // SendMaybeFireEmbedderLoadEvents via any of the normal call paths.
3293 // (Obviously, we must do this before any of the returns below.)
3294 RefPtr<BrowserChild> browserChild = BrowserChild::GetFrom(this);
3295 if (browserChild &&
3296 !mBrowsingContext->GetParentWindowContext()->IsInProcess()) {
3297 mozilla::Unused << browserChild->SendMaybeFireEmbedderLoadEvents(
3298 aFireFrameErrorEvent ? EmbedderElementEventType::ErrorEvent
3299 : EmbedderElementEventType::NoEvent);
3300 }
3301}
3302
3303NS_IMETHODIMPnsresult
3304nsDocShell::DisplayLoadError(nsresult aError, nsIURI* aURI,
3305 const char16_t* aURL, nsIChannel* aFailedChannel,
3306 bool* aDisplayedErrorPage) {
3307 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
)
3308 ("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
)
3309 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
)
;
3310
3311 *aDisplayedErrorPage = false;
3312 // Get prompt and string bundle services
3313 nsCOMPtr<nsIPrompt> prompter;
3314 nsCOMPtr<nsIStringBundle> stringBundle;
3315 GetPromptAndStringBundle(getter_AddRefs(prompter),
3316 getter_AddRefs(stringBundle));
3317
3318 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"
, 3318); return NS_ERROR_FAILURE; } } while (false)
;
3319 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"
, 3319); return NS_ERROR_FAILURE; } } while (false)
;
3320
3321 const char* error = nullptr;
3322 // The key used to select the appropriate error message from the properties
3323 // file.
3324 const char* errorDescriptionID = nullptr;
3325 AutoTArray<nsString, 3> formatStrs;
3326 bool addHostPort = false;
3327 bool isBadStsCertError = false;
3328 nsresult rv = NS_OK;
3329 nsAutoString messageStr;
3330 nsAutoCString cssClass;
3331 nsAutoCString errorPage;
3332
3333 errorPage.AssignLiteral("neterror");
3334
3335 // Turn the error code into a human readable error message.
3336 if (NS_ERROR_UNKNOWN_PROTOCOL == aError) {
3337 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"
, 3337); return NS_ERROR_INVALID_POINTER; } } while (false)
;
3338
3339 // Extract the schemes into a comma delimited list.
3340 nsAutoCString scheme;
3341 aURI->GetScheme(scheme);
3342 CopyASCIItoUTF16(scheme, *formatStrs.AppendElement());
3343 nsCOMPtr<nsINestedURI> nestedURI = do_QueryInterface(aURI);
3344 while (nestedURI) {
3345 nsCOMPtr<nsIURI> tempURI;
3346 nsresult rv2;
3347 rv2 = nestedURI->GetInnerURI(getter_AddRefs(tempURI));
3348 if (NS_SUCCEEDED(rv2)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv2)), 1))) && tempURI) {
3349 tempURI->GetScheme(scheme);
3350 formatStrs[0].AppendLiteral(", ");
3351 AppendASCIItoUTF16(scheme, formatStrs[0]);
3352 }
3353 nestedURI = do_QueryInterface(tempURI);
3354 }
3355 error = "unknownProtocolFound";
3356 } else if (NS_ERROR_NET_ERROR_RESPONSE == aError) {
3357 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"
, 3357); return NS_ERROR_INVALID_POINTER; } } while (false)
;
3358 error = "serverError";
3359 } else if (NS_ERROR_FILE_NOT_FOUND == aError) {
3360 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"
, 3360); return NS_ERROR_INVALID_POINTER; } } while (false)
;
3361 error = "fileNotFound";
3362 } else if (NS_ERROR_FILE_ACCESS_DENIED == aError) {
3363 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"
, 3363); return NS_ERROR_INVALID_POINTER; } } while (false)
;
3364 error = "fileAccessDenied";
3365 } else if (NS_ERROR_UNKNOWN_HOST == aError) {
3366 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"
, 3366); return NS_ERROR_INVALID_POINTER; } } while (false)
;
3367 // Get the host
3368 nsAutoCString host;
3369 nsCOMPtr<nsIURI> innermostURI = NS_GetInnermostURI(aURI);
3370 innermostURI->GetHost(host);
3371 CopyUTF8toUTF16(host, *formatStrs.AppendElement());
3372 errorDescriptionID = "dnsNotFound2";
3373 error = "dnsNotFound";
3374 } else if (NS_ERROR_CONNECTION_REFUSED == aError ||
3375 NS_ERROR_PROXY_BAD_GATEWAY == aError) {
3376 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"
, 3376); return NS_ERROR_INVALID_POINTER; } } while (false)
;
3377 addHostPort = true;
3378 error = "connectionFailure";
3379 } else if (NS_ERROR_NET_INTERRUPT == aError) {
3380 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"
, 3380); return NS_ERROR_INVALID_POINTER; } } while (false)
;
3381 addHostPort = true;
3382 error = "netInterrupt";
3383 } else if (NS_ERROR_NET_TIMEOUT == aError ||
3384 NS_ERROR_PROXY_GATEWAY_TIMEOUT == aError ||
3385 NS_ERROR_NET_TIMEOUT_EXTERNAL == aError) {
3386 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"
, 3386); return NS_ERROR_INVALID_POINTER; } } while (false)
;
3387 // Get the host
3388 nsAutoCString host;
3389 aURI->GetHost(host);
3390 CopyUTF8toUTF16(host, *formatStrs.AppendElement());
3391 error = "netTimeout";
3392 } else if (NS_ERROR_CSP_FRAME_ANCESTOR_VIOLATION == aError ||
3393 NS_ERROR_CSP_FORM_ACTION_VIOLATION == aError) {
3394 // CSP error
3395 cssClass.AssignLiteral("neterror");
3396 error = "cspBlocked";
3397 } else if (NS_ERROR_XFO_VIOLATION == aError) {
3398 // XFO error
3399 cssClass.AssignLiteral("neterror");
3400 error = "xfoBlocked";
3401 } else if (NS_ERROR_GET_MODULE(aError) == NS_ERROR_MODULE_SECURITY21) {
3402 nsCOMPtr<nsINSSErrorsService> nsserr =
3403 do_GetService(NS_NSS_ERRORS_SERVICE_CONTRACTID"@mozilla.org/nss_errors_service;1");
3404
3405 uint32_t errorClass;
3406 if (!nsserr || NS_FAILED(nsserr->GetErrorClass(aError, &errorClass))((bool)(__builtin_expect(!!(NS_FAILED_impl(nsserr->GetErrorClass
(aError, &errorClass))), 0)))
) {
3407 errorClass = nsINSSErrorsService::ERROR_CLASS_SSL_PROTOCOL;
3408 }
3409
3410 nsCOMPtr<nsITransportSecurityInfo> tsi;
3411 if (aFailedChannel) {
3412 aFailedChannel->GetSecurityInfo(getter_AddRefs(tsi));
3413 }
3414 if (tsi) {
3415 uint32_t securityState;
3416 tsi->GetSecurityState(&securityState);
3417 if (securityState & nsIWebProgressListener::STATE_USES_SSL_3) {
3418 error = "sslv3Used";
3419 addHostPort = true;
3420 } else if (securityState &
3421 nsIWebProgressListener::STATE_USES_WEAK_CRYPTO) {
3422 error = "weakCryptoUsed";
Value stored to 'error' is never read
3423 addHostPort = true;
3424 }
3425 } else {
3426 // No channel, let's obtain the generic error message
3427 if (nsserr) {
3428 nsserr->GetErrorMessage(aError, messageStr);
3429 }
3430 }
3431 // We don't have a message string here anymore but DisplayLoadError
3432 // requires a non-empty messageStr.
3433 messageStr.Truncate();
3434 messageStr.AssignLiteral(u" ");
3435 if (errorClass == nsINSSErrorsService::ERROR_CLASS_BAD_CERT) {
3436 error = "nssBadCert";
3437
3438 // If this is an HTTP Strict Transport Security host or a pinned host
3439 // and the certificate is bad, don't allow overrides (RFC 6797 section
3440 // 12.1).
3441 bool isStsHost = false;
3442 bool isPinnedHost = false;
3443 OriginAttributes attrsForHSTS;
3444 if (aFailedChannel) {
3445 StoragePrincipalHelper::GetOriginAttributesForHSTS(aFailedChannel,
3446 attrsForHSTS);
3447 } else {
3448 attrsForHSTS = GetOriginAttributes();
3449 }
3450
3451 if (XRE_IsParentProcess()) {
3452 nsCOMPtr<nsISiteSecurityService> sss =
3453 do_GetService(NS_SSSERVICE_CONTRACTID"@mozilla.org/ssservice;1", &rv);
3454 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"
, 3454); return rv; } } while (false)
;
3455 rv = sss->IsSecureURI(aURI, attrsForHSTS, &isStsHost);
3456 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"
, 3456); return rv; } } while (false)
;
3457 } else {
3458 mozilla::dom::ContentChild* cc =
3459 mozilla::dom::ContentChild::GetSingleton();
3460 cc->SendIsSecureURI(aURI, attrsForHSTS, &isStsHost);
3461 }
3462 nsCOMPtr<nsIPublicKeyPinningService> pkps =
3463 do_GetService(NS_PKPSERVICE_CONTRACTID"@mozilla.org/security/publickeypinningservice;1", &rv);
3464 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"
, 3464); return rv; } } while (false)
;
3465 rv = pkps->HostHasPins(aURI, &isPinnedHost);
3466
3467 if (Preferences::GetBool("browser.xul.error_pages.expert_bad_cert",
3468 false)) {
3469 cssClass.AssignLiteral("expertBadCert");
3470 }
3471
3472 // HSTS/pinning takes precedence over the expert bad cert pref. We
3473 // never want to show the "Add Exception" button for these sites.
3474 // In the future we should differentiate between an HSTS host and a
3475 // pinned host and display a more informative message to the user.
3476 if (isStsHost || isPinnedHost) {
3477 isBadStsCertError = true;
3478 cssClass.AssignLiteral("badStsCert");
3479 }
3480
3481 errorPage.Assign("certerror");
3482 } else {
3483 error = "nssFailure2";
3484 }
3485 } else if (NS_ERROR_PHISHING_URI == aError ||
3486 NS_ERROR_MALWARE_URI == aError ||
3487 NS_ERROR_UNWANTED_URI == aError ||
3488 NS_ERROR_HARMFUL_URI == aError) {
3489 nsAutoCString host;
3490 aURI->GetHost(host);
3491 CopyUTF8toUTF16(host, *formatStrs.AppendElement());
3492
3493 // Malware and phishing detectors may want to use an alternate error
3494 // page, but if the pref's not set, we'll fall back on the standard page
3495 nsAutoCString alternateErrorPage;
3496 nsresult rv = Preferences::GetCString("urlclassifier.alternate_error_page",
3497 alternateErrorPage);
3498 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
3499 errorPage.Assign(alternateErrorPage);
3500 }
3501
3502 if (NS_ERROR_PHISHING_URI == aError) {
3503 error = "deceptiveBlocked";
3504 } else if (NS_ERROR_MALWARE_URI == aError) {
3505 error = "malwareBlocked";
3506 } else if (NS_ERROR_UNWANTED_URI == aError) {
3507 error = "unwantedBlocked";
3508 } else if (NS_ERROR_HARMFUL_URI == aError) {
3509 error = "harmfulBlocked";
3510 }
3511
3512 cssClass.AssignLiteral("blacklist");
3513 } else if (NS_ERROR_CONTENT_CRASHED == aError) {
3514 errorPage.AssignLiteral("tabcrashed");
3515 error = "tabcrashed";
3516
3517 RefPtr<EventTarget> handler = mChromeEventHandler;
3518 if (handler) {
3519 nsCOMPtr<Element> element = do_QueryInterface(handler);
3520 element->GetAttribute(u"crashedPageTitle"_ns, messageStr);
3521 }
3522
3523 // DisplayLoadError requires a non-empty messageStr to proceed and call
3524 // LoadErrorPage. If the page doesn't have a title, we will use a blank
3525 // space which will be trimmed and thus treated as empty by the front-end.
3526 if (messageStr.IsEmpty()) {
3527 messageStr.AssignLiteral(u" ");
3528 }
3529 } else if (NS_ERROR_FRAME_CRASHED == aError) {
3530 errorPage.AssignLiteral("framecrashed");
3531 error = "framecrashed";
3532 messageStr.AssignLiteral(u" ");
3533 } else if (NS_ERROR_BUILDID_MISMATCH == aError) {
3534 errorPage.AssignLiteral("restartrequired");
3535 error = "restartrequired";
3536
3537 // DisplayLoadError requires a non-empty messageStr to proceed and call
3538 // LoadErrorPage. If the page doesn't have a title, we will use a blank
3539 // space which will be trimmed and thus treated as empty by the front-end.
3540 if (messageStr.IsEmpty()) {
3541 messageStr.AssignLiteral(u" ");
3542 }
3543 } else {
3544 // Errors requiring simple formatting
3545 switch (aError) {
3546 case NS_ERROR_MALFORMED_URI:
3547 // URI is malformed
3548 error = "malformedURI";
3549 errorDescriptionID = "malformedURI2";
3550 break;
3551 case NS_ERROR_REDIRECT_LOOP:
3552 // Doc failed to load because the server generated too many redirects
3553 error = "redirectLoop";
3554 break;
3555 case NS_ERROR_UNKNOWN_SOCKET_TYPE:
3556 // Doc failed to load because PSM is not installed
3557 error = "unknownSocketType";
3558 break;
3559 case NS_ERROR_NET_RESET:
3560 // Doc failed to load because the server kept reseting the connection
3561 // before we could read any data from it
3562 error = "netReset";
3563 break;
3564 case NS_ERROR_DOCUMENT_NOT_CACHED:
3565 // Doc failed to load because the cache does not contain a copy of
3566 // the document.
3567 error = "notCached";
3568 break;
3569 case NS_ERROR_OFFLINE:
3570 // Doc failed to load because we are offline.
3571 error = "netOffline";
3572 break;
3573 case NS_ERROR_DOCUMENT_IS_PRINTMODE:
3574 // Doc navigation attempted while Printing or Print Preview
3575 error = "isprinting";
3576 break;
3577 case NS_ERROR_PORT_ACCESS_NOT_ALLOWED:
3578 // Port blocked for security reasons
3579 addHostPort = true;
3580 error = "deniedPortAccess";
3581 break;
3582 case NS_ERROR_UNKNOWN_PROXY_HOST:
3583 // Proxy hostname could not be resolved.
3584 error = "proxyResolveFailure";
3585 break;
3586 case NS_ERROR_PROXY_CONNECTION_REFUSED:
3587 case NS_ERROR_PROXY_FORBIDDEN:
3588 case NS_ERROR_PROXY_NOT_IMPLEMENTED:
3589 case NS_ERROR_PROXY_AUTHENTICATION_FAILED:
3590 case NS_ERROR_PROXY_TOO_MANY_REQUESTS:
3591 // Proxy connection was refused.
3592 error = "proxyConnectFailure";
3593 break;
3594 case NS_ERROR_INVALID_CONTENT_ENCODING:
3595 // Bad Content Encoding.
3596 error = "contentEncodingError";
3597 break;
3598 case NS_ERROR_UNSAFE_CONTENT_TYPE:
3599 // Channel refused to load from an unrecognized content type.
3600 error = "unsafeContentType";
3601 break;
3602 case NS_ERROR_CORRUPTED_CONTENT:
3603 // Broken Content Detected. e.g. Content-MD5 check failure.
3604 error = "corruptedContentErrorv2";
3605 break;
3606 case NS_ERROR_INTERCEPTION_FAILED:
3607 // ServiceWorker intercepted request, but something went wrong.
3608 error = "corruptedContentErrorv2";
3609 break;
3610 case NS_ERROR_NET_INADEQUATE_SECURITY:
3611 // Server negotiated bad TLS for HTTP/2.
3612 error = "inadequateSecurityError";
3613 addHostPort = true;
3614 break;
3615 case NS_ERROR_BLOCKED_BY_POLICY:
3616 case NS_ERROR_DOM_COOP_FAILED:
3617 case NS_ERROR_DOM_COEP_FAILED:
3618 // Page blocked by policy
3619 error = "blockedByPolicy";
3620 break;
3621 case NS_ERROR_NET_HTTP2_SENT_GOAWAY:
3622 case NS_ERROR_NET_HTTP3_PROTOCOL_ERROR:
3623 // HTTP/2 or HTTP/3 stack detected a protocol error
3624 error = "networkProtocolError";
3625 break;
3626
3627 default:
3628 break;
3629 }
3630 }
3631
3632 nsresult delegateErrorCode = aError;
3633 // If the HTTPS-Only Mode upgraded this request and the upgrade might have
3634 // caused this error, we replace the error-page with about:httpsonlyerror
3635 if (nsHTTPSOnlyUtils::CouldBeHttpsOnlyError(aFailedChannel, aError)) {
3636 errorPage.AssignLiteral("httpsonlyerror");
3637 delegateErrorCode = NS_ERROR_HTTPS_ONLY;
3638 } else if (isBadStsCertError) {
3639 delegateErrorCode = NS_ERROR_BAD_HSTS_CERT;
3640 }
3641
3642 if (nsCOMPtr<nsILoadURIDelegate> loadURIDelegate = GetLoadURIDelegate()) {
3643 nsCOMPtr<nsIURI> errorPageURI;
3644 rv = loadURIDelegate->HandleLoadError(
3645 aURI, delegateErrorCode, NS_ERROR_GET_MODULE(delegateErrorCode),
3646 getter_AddRefs(errorPageURI));
3647 // If the docshell is going away there's no point in showing an error page.
3648 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) || mIsBeingDestroyed) {
3649 *aDisplayedErrorPage = false;
3650 return NS_OK;
3651 }
3652
3653 if (errorPageURI) {
3654 *aDisplayedErrorPage =
3655 NS_SUCCEEDED(LoadErrorPage(errorPageURI, aURI, aFailedChannel))((bool)(__builtin_expect(!!(!NS_FAILED_impl(LoadErrorPage(errorPageURI
, aURI, aFailedChannel))), 1)))
;
3656 return NS_OK;
3657 }
3658 }
3659
3660 // Test if the error should be displayed
3661 if (!error) {
3662 return NS_OK;
3663 }
3664
3665 if (!errorDescriptionID) {
3666 errorDescriptionID = error;
3667 }
3668
3669 Telemetry::AccumulateCategoricalKeyed(
3670 IsSubframe() ? "frame"_ns : "top"_ns,
3671 mozilla::dom::LoadErrorToTelemetryLabel(aError));
3672
3673 // Test if the error needs to be formatted
3674 if (!messageStr.IsEmpty()) {
3675 // already obtained message
3676 } else {
3677 if (addHostPort) {
3678 // Build up the host:port string.
3679 nsAutoCString hostport;
3680 if (aURI) {
3681 aURI->GetHostPort(hostport);
3682 } else {
3683 hostport.Assign('?');
3684 }
3685 CopyUTF8toUTF16(hostport, *formatStrs.AppendElement());
3686 }
3687
3688 nsAutoCString spec;
3689 rv = NS_ERROR_NOT_AVAILABLE;
3690 auto& nextFormatStr = *formatStrs.AppendElement();
3691 if (aURI) {
3692 // displaying "file://" is aesthetically unpleasing and could even be
3693 // confusing to the user
3694 if (SchemeIsFile(aURI)) {
3695 aURI->GetPathQueryRef(spec);
3696 } else {
3697 aURI->GetSpec(spec);
3698 }
3699
3700 nsCOMPtr<nsITextToSubURI> textToSubURI(
3701 do_GetService(NS_ITEXTTOSUBURI_CONTRACTID"@mozilla.org/intl/texttosuburi;1", &rv));
3702 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
3703 rv = textToSubURI->UnEscapeURIForUI(spec, nextFormatStr);
3704 }
3705 } else {
3706 spec.Assign('?');
3707 }
3708 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3709 CopyUTF8toUTF16(spec, nextFormatStr);
3710 }
3711 rv = NS_OK;
3712
3713 nsAutoString str;
3714 rv =
3715 stringBundle->FormatStringFromName(errorDescriptionID, formatStrs, str);
3716 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"
, 3716); return rv; } } while (false)
;
3717 messageStr.Assign(str);
3718 }
3719
3720 // Display the error as a page or an alert prompt
3721 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"
, 3721); return NS_ERROR_FAILURE; } } while (false)
;
3722
3723 if ((NS_ERROR_NET_INTERRUPT == aError || NS_ERROR_NET_RESET == aError) &&
3724 SchemeIsHTTPS(aURI)) {
3725 // Maybe TLS intolerant. Treat this as an SSL error.
3726 error = "nssFailure2";
3727 }
3728
3729 if (mBrowsingContext->GetUseErrorPages()) {
3730 // Display an error page
3731 nsresult loadedPage =
3732 LoadErrorPage(aURI, aURL, errorPage.get(), error, messageStr.get(),
3733 cssClass.get(), aFailedChannel);
3734 *aDisplayedErrorPage = NS_SUCCEEDED(loadedPage)((bool)(__builtin_expect(!!(!NS_FAILED_impl(loadedPage)), 1))
)
;
3735 } else {
3736 // The prompter reqires that our private window has a document (or it
3737 // asserts). Satisfy that assertion now since GetDoc will force
3738 // creation of one if it hasn't already been created.
3739 if (mScriptGlobal) {
3740 Unused << mScriptGlobal->GetDoc();
3741 }
3742
3743 // Display a message box
3744 prompter->Alert(nullptr, messageStr.get());
3745 }
3746
3747 return NS_OK;
3748}
3749
3750#define PREF_SAFEBROWSING_ALLOWOVERRIDE"browser.safebrowsing.allowOverride" "browser.safebrowsing.allowOverride"
3751
3752nsresult nsDocShell::LoadErrorPage(nsIURI* aURI, const char16_t* aURL,
3753 const char* aErrorPage,
3754 const char* aErrorType,
3755 const char16_t* aDescription,
3756 const char* aCSSClass,
3757 nsIChannel* aFailedChannel) {
3758 if (mIsBeingDestroyed) {
3759 return NS_ERROR_NOT_AVAILABLE;
3760 }
3761
3762#if defined(DEBUG1)
3763 if (MOZ_LOG_TEST(gDocShellLog, LogLevel::Debug)(__builtin_expect(!!(mozilla::detail::log_test(gDocShellLog, LogLevel
::Debug)), 0))
) {
3764 nsAutoCString chanName;
3765 if (aFailedChannel) {
3766 aFailedChannel->GetName(chanName);
3767 } else {
3768 chanName.AssignLiteral("<no channel>");
3769 }
3770
3771 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)
3772 ("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)
3773 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)
3774 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)
;
3775 }
3776#endif
3777
3778 nsAutoCString url;
3779 if (aURI) {
3780 nsresult rv = aURI->GetSpec(url);
3781 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"
, 3781); return rv; } } while (false)
;
3782 } else if (aURL) {
3783 CopyUTF16toUTF8(MakeStringSpan(aURL), url);
3784 } else {
3785 return NS_ERROR_INVALID_POINTER;
3786 }
3787
3788 // Create a URL to pass all the error information through to the page.
3789
3790#undef SAFE_ESCAPE
3791#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"
, 3791)) { return NS_ERROR_OUT_OF_MEMORY; }
\
3792 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"
, 3792)
) { \
3793 return NS_ERROR_OUT_OF_MEMORY; \
3794 }
3795
3796 nsCString escapedUrl, escapedError, escapedDescription, escapedCSSClass;
3797 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"
, 3797)) { return NS_ERROR_OUT_OF_MEMORY; }
;
3798 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"
, 3798)) { return NS_ERROR_OUT_OF_MEMORY; }
;
3799 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"
, 3800)) { return NS_ERROR_OUT_OF_MEMORY; }
3800 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"
, 3800)) { return NS_ERROR_OUT_OF_MEMORY; }
;
3801 if (aCSSClass) {
3802 nsCString cssClass(aCSSClass);
3803 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"
, 3803)) { return NS_ERROR_OUT_OF_MEMORY; }
;
3804 }
3805 nsCString errorPageUrl("about:");
3806 errorPageUrl.AppendASCII(aErrorPage);
3807 errorPageUrl.AppendLiteral("?e=");
3808
3809 errorPageUrl.AppendASCII(escapedError.get());
3810 errorPageUrl.AppendLiteral("&u=");
3811 errorPageUrl.AppendASCII(escapedUrl.get());
3812 if ((strcmp(aErrorPage, "blocked") == 0) &&
3813 Preferences::GetBool(PREF_SAFEBROWSING_ALLOWOVERRIDE"browser.safebrowsing.allowOverride", true)) {
3814 errorPageUrl.AppendLiteral("&o=1");
3815 }
3816 if (!escapedCSSClass.IsEmpty()) {
3817 errorPageUrl.AppendLiteral("&s=");
3818 errorPageUrl.AppendASCII(escapedCSSClass.get());
3819 }
3820 errorPageUrl.AppendLiteral("&c=UTF-8");
3821
3822 nsCOMPtr<nsICaptivePortalService> cps = do_GetService(NS_CAPTIVEPORTAL_CID{ 0xbdbe0555, 0xfc3d, 0x4f7b, { 0x92, 0x05, 0xc3, 0x09, 0xce,
0xb2, 0xd6, 0x41 } }
);
3823 int32_t cpsState;
3824 if (cps && NS_SUCCEEDED(cps->GetState(&cpsState))((bool)(__builtin_expect(!!(!NS_FAILED_impl(cps->GetState(
&cpsState))), 1)))
&&
3825 cpsState == nsICaptivePortalService::LOCKED_PORTAL) {
3826 errorPageUrl.AppendLiteral("&captive=true");
3827 }
3828
3829 errorPageUrl.AppendLiteral("&d=");
3830 errorPageUrl.AppendASCII(escapedDescription.get());
3831
3832 nsCOMPtr<nsIURI> errorPageURI;
3833 nsresult rv = NS_NewURI(getter_AddRefs(errorPageURI), errorPageUrl);
3834 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"
, 3834); return rv; } } while (false)
;
3835
3836 return LoadErrorPage(errorPageURI, aURI, aFailedChannel);
3837}
3838
3839nsresult nsDocShell::LoadErrorPage(nsIURI* aErrorURI, nsIURI* aFailedURI,
3840 nsIChannel* aFailedChannel) {
3841 mFailedChannel = aFailedChannel;
3842 mFailedURI = aFailedURI;
3843 mFailedLoadType = mLoadType;
3844
3845 if (mLSHE) {
3846 // Abandon mLSHE's BFCache entry and create a new one. This way, if
3847 // we go back or forward to another SHEntry with the same doc
3848 // identifier, the error page won't persist.
3849 mLSHE->AbandonBFCacheEntry();
3850 }
3851
3852 RefPtr<nsDocShellLoadState> loadState = new nsDocShellLoadState(aErrorURI);
3853 loadState->SetTriggeringPrincipal(nsContentUtils::GetSystemPrincipal());
3854 if (mBrowsingContext) {
3855 loadState->SetTriggeringSandboxFlags(mBrowsingContext->GetSandboxFlags());
3856 loadState->SetTriggeringWindowId(
3857 mBrowsingContext->GetCurrentInnerWindowId());
3858 nsPIDOMWindowInner* innerWin = mScriptGlobal->GetCurrentInnerWindow();
3859 if (innerWin) {
3860 loadState->SetTriggeringStorageAccess(innerWin->UsingStorageAccess());
3861 }
3862 }
3863 loadState->SetLoadType(LOAD_ERROR_PAGE);
3864 loadState->SetFirstParty(true);
3865 loadState->SetSourceBrowsingContext(mBrowsingContext);
3866 if (mozilla::SessionHistoryInParent() && mLoadingEntry) {
3867 // We keep the loading entry for the load that failed here. If the user
3868 // reloads we want to try to reload the original load, not the error page.
3869 loadState->SetLoadingSessionHistoryInfo(
3870 MakeUnique<LoadingSessionHistoryInfo>(*mLoadingEntry));
3871 }
3872 return InternalLoad(loadState);
3873}
3874
3875NS_IMETHODIMPnsresult
3876nsDocShell::Reload(uint32_t aReloadFlags) {
3877 if (!IsNavigationAllowed()) {
3878 return NS_OK; // JS may not handle returning of an error code
3879 }
3880
3881 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"
, 3882); MOZ_PretendNoReturn(); } } while (0)
3882 "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"
, 3882); MOZ_PretendNoReturn(); } } while (0)
;
3883 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"
, 3884); MOZ_PretendNoReturn(); } } while (0)
3884 "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"
, 3884); MOZ_PretendNoReturn(); } } while (0)
;
3885
3886 uint32_t loadType = MAKE_LOAD_TYPE(LOAD_RELOAD_NORMAL, aReloadFlags)((LOAD_RELOAD_NORMAL) | ((aReloadFlags) << 16));
3887 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"
, 3887); return NS_ERROR_INVALID_ARG; } } while (false)
;
3888
3889 // Send notifications to the HistoryListener if any, about the impending
3890 // reload
3891 RefPtr<ChildSHistory> rootSH = GetRootSessionHistory();
3892 if (mozilla::SessionHistoryInParent()) {
3893 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)
;
3894 bool forceReload = IsForceReloadType(loadType);
3895 if (!XRE_IsParentProcess()) {
3896 ++mPendingReloadCount;
3897 RefPtr<nsDocShell> docShell(this);
3898 nsCOMPtr<nsIDocumentViewer> viewer(mDocumentViewer);
3899 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"
, 3899); return NS_ERROR_UNEXPECTED; } } while (false)
;
3900
3901 bool okToUnload = true;
3902 MOZ_TRY(viewer->PermitUnload(&okToUnload))do { auto mozTryTempResult_ = ::mozilla::ToResult(viewer->
PermitUnload(&okToUnload)); if ((__builtin_expect(!!(mozTryTempResult_
.isErr()), 0))) { return mozTryTempResult_.propagateErr(); } }
while (0)
;
3903 if (!okToUnload) {
3904 return NS_OK;
3905 }
3906
3907 RefPtr<Document> doc(GetDocument());
3908 RefPtr<BrowsingContext> browsingContext(mBrowsingContext);
3909 nsCOMPtr<nsIURI> currentURI(mCurrentURI);
3910 nsCOMPtr<nsIReferrerInfo> referrerInfo(mReferrerInfo);
3911 RefPtr<StopDetector> stopDetector = new StopDetector();
3912 nsCOMPtr<nsILoadGroup> loadGroup;
3913 GetLoadGroup(getter_AddRefs(loadGroup));
3914 if (loadGroup) {
3915 // loadGroup may be null in theory. In that case stopDetector just
3916 // doesn't do anything.
3917 loadGroup->AddRequest(stopDetector, nullptr);
3918 }
3919
3920 ContentChild::GetSingleton()->SendNotifyOnHistoryReload(
3921 mBrowsingContext, forceReload,
3922 [docShell, doc, loadType, browsingContext, currentURI, referrerInfo,
3923 loadGroup, stopDetector](
3924 std::tuple<bool, Maybe<NotNull<RefPtr<nsDocShellLoadState>>>,
3925 Maybe<bool>>&& aResult) {
3926 auto scopeExit = MakeScopeExit([loadGroup, stopDetector]() {
3927 if (loadGroup) {
3928 loadGroup->RemoveRequest(stopDetector, nullptr, NS_OK);
3929 }
3930 });
3931
3932 // Decrease mPendingReloadCount before any other early returns!
3933 if (--(docShell->mPendingReloadCount) > 0) {
3934 return;
3935 }
3936
3937 if (stopDetector->Canceled()) {
3938 return;
3939 }
3940 bool canReload;
3941 Maybe<NotNull<RefPtr<nsDocShellLoadState>>> loadState;
3942 Maybe<bool> reloadingActiveEntry;
3943
3944 std::tie(canReload, loadState, reloadingActiveEntry) = aResult;
3945
3946 if (!canReload) {
3947 return;
3948 }
3949
3950 if (loadState.isSome()) {
3951 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)
3952 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)
3953 ("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)
;
3954 loadState.ref()->SetNotifiedBeforeUnloadListeners(true);
3955 docShell->LoadHistoryEntry(loadState.ref(), loadType,
3956 reloadingActiveEntry.ref());
3957 } else {
3958 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)
3959 ("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)
;
3960 ReloadDocument(docShell, doc, loadType, browsingContext,
3961 currentURI, referrerInfo,
3962 /* aNotifiedBeforeUnloadListeners */ true);
3963 }
3964 },
3965 [](mozilla::ipc::ResponseRejectReason) {});
3966 } else {
3967 // Parent process
3968 bool canReload = false;
3969 Maybe<NotNull<RefPtr<nsDocShellLoadState>>> loadState;
3970 Maybe<bool> reloadingActiveEntry;
3971 if (!mBrowsingContext->IsDiscarded()) {
3972 mBrowsingContext->Canonical()->NotifyOnHistoryReload(
3973 forceReload, canReload, loadState, reloadingActiveEntry);
3974 }
3975 if (canReload) {
3976 if (loadState.isSome()) {
3977 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)
3978 ("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)
;
3979 LoadHistoryEntry(loadState.ref(), loadType,
3980 reloadingActiveEntry.ref());
3981 } else {
3982 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)
3983 ("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)
;
3984 RefPtr<Document> doc = GetDocument();
3985 RefPtr<BrowsingContext> bc = mBrowsingContext;
3986 nsCOMPtr<nsIURI> currentURI = mCurrentURI;
3987 nsCOMPtr<nsIReferrerInfo> referrerInfo = mReferrerInfo;
3988 ReloadDocument(this, doc, loadType, bc, currentURI, referrerInfo);
3989 }
3990 }
3991 }
3992 return NS_OK;
3993 }
3994
3995 bool canReload = true;
3996 if (rootSH) {
3997 rootSH->LegacySHistory()->NotifyOnHistoryReload(&canReload);
3998 }
3999
4000 if (!canReload) {
4001 return NS_OK;
4002 }
4003
4004 /* If you change this part of code, make sure bug 45297 does not re-occur */
4005 if (mOSHE) {
4006 nsCOMPtr<nsISHEntry> oshe = mOSHE;
4007 return LoadHistoryEntry(
4008 oshe, loadType,
4009 aReloadFlags & nsIWebNavigation::LOAD_FLAGS_USER_ACTIVATION);
4010 }
4011
4012 if (mLSHE) { // In case a reload happened before the current load is done
4013 nsCOMPtr<nsISHEntry> lshe = mLSHE;
4014 return LoadHistoryEntry(
4015 lshe, loadType,
4016 aReloadFlags & nsIWebNavigation::LOAD_FLAGS_USER_ACTIVATION);
4017 }
4018
4019 RefPtr<Document> doc = GetDocument();
4020 RefPtr<BrowsingContext> bc = mBrowsingContext;
4021 nsCOMPtr<nsIURI> currentURI = mCurrentURI;
4022 nsCOMPtr<nsIReferrerInfo> referrerInfo = mReferrerInfo;
4023 return ReloadDocument(this, doc, loadType, bc, currentURI, referrerInfo);
4024}
4025
4026/* static */
4027nsresult nsDocShell::ReloadDocument(nsDocShell* aDocShell, Document* aDocument,
4028 uint32_t aLoadType,
4029 BrowsingContext* aBrowsingContext,
4030 nsIURI* aCurrentURI,
4031 nsIReferrerInfo* aReferrerInfo,
4032 bool aNotifiedBeforeUnloadListeners) {
4033 if (!aDocument) {
4034 return NS_OK;
4035 }
4036
4037 // Do not inherit owner from document
4038 uint32_t flags = INTERNAL_LOAD_FLAGS_NONE;
4039 nsAutoString srcdoc;
4040 nsIURI* baseURI = nullptr;
4041 nsCOMPtr<nsIURI> originalURI;
4042 nsCOMPtr<nsIURI> resultPrincipalURI;
4043 bool loadReplace = false;
4044
4045 nsIPrincipal* triggeringPrincipal = aDocument->NodePrincipal();
4046 nsCOMPtr<nsIContentSecurityPolicy> csp = aDocument->GetCsp();
4047 uint32_t triggeringSandboxFlags = aDocument->GetSandboxFlags();
4048 uint64_t triggeringWindowId = aDocument->InnerWindowID();
4049 bool triggeringStorageAccess = aDocument->UsingStorageAccess();
4050
4051 nsAutoString contentTypeHint;
4052 aDocument->GetContentType(contentTypeHint);
4053
4054 if (aDocument->IsSrcdocDocument()) {
4055 aDocument->GetSrcdocData(srcdoc);
4056 flags |= INTERNAL_LOAD_FLAGS_IS_SRCDOC;
4057 baseURI = aDocument->GetBaseURI();
4058 } else {
4059 srcdoc = VoidString();
4060 }
4061 nsCOMPtr<nsIChannel> chan = aDocument->GetChannel();
4062 if (chan) {
4063 uint32_t loadFlags;
4064 chan->GetLoadFlags(&loadFlags);
4065 loadReplace = loadFlags & nsIChannel::LOAD_REPLACE;
4066 nsCOMPtr<nsIHttpChannel> httpChan(do_QueryInterface(chan));
4067 if (httpChan) {
4068 httpChan->GetOriginalURI(getter_AddRefs(originalURI));
4069 }
4070
4071 nsCOMPtr<nsILoadInfo> loadInfo = chan->LoadInfo();
4072 loadInfo->GetResultPrincipalURI(getter_AddRefs(resultPrincipalURI));
4073 }
4074
4075 if (!triggeringPrincipal) {
4076 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"
, 4076); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"Reload needs a valid triggeringPrincipal" ")"); do { *((volatile
int*)__null) = 4076; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
4077 return NS_ERROR_FAILURE;
4078 }
4079
4080 // Stack variables to ensure changes to the member variables don't affect to
4081 // the call.
4082 nsCOMPtr<nsIURI> currentURI = aCurrentURI;
4083
4084 // Reload always rewrites result principal URI.
4085 Maybe<nsCOMPtr<nsIURI>> emplacedResultPrincipalURI;
4086 emplacedResultPrincipalURI.emplace(std::move(resultPrincipalURI));
4087
4088 RefPtr<WindowContext> context = aBrowsingContext->GetCurrentWindowContext();
4089 RefPtr<nsDocShellLoadState> loadState = new nsDocShellLoadState(currentURI);
4090 loadState->SetReferrerInfo(aReferrerInfo);
4091 loadState->SetOriginalURI(originalURI);
4092 loadState->SetMaybeResultPrincipalURI(emplacedResultPrincipalURI);
4093 loadState->SetLoadReplace(loadReplace);
4094 loadState->SetTriggeringPrincipal(triggeringPrincipal);
4095 loadState->SetTriggeringSandboxFlags(triggeringSandboxFlags);
4096 loadState->SetTriggeringWindowId(triggeringWindowId);
4097 loadState->SetTriggeringStorageAccess(triggeringStorageAccess);
4098 loadState->SetPrincipalToInherit(triggeringPrincipal);
4099 loadState->SetCsp(csp);
4100 loadState->SetInternalLoadFlags(flags);
4101 loadState->SetTypeHint(NS_ConvertUTF16toUTF8(contentTypeHint));
4102 loadState->SetLoadType(aLoadType);
4103 loadState->SetFirstParty(true);
4104 loadState->SetSrcdocData(srcdoc);
4105 loadState->SetSourceBrowsingContext(aBrowsingContext);
4106 loadState->SetBaseURI(baseURI);
4107 loadState->SetHasValidUserGestureActivation(
4108 context && context->HasValidTransientUserGestureActivation());
4109
4110 loadState->SetTextDirectiveUserActivation(
4111 aDocument->ConsumeTextDirectiveUserActivation() ||
4112 loadState->HasValidUserGestureActivation());
4113
4114 loadState->SetNotifiedBeforeUnloadListeners(aNotifiedBeforeUnloadListeners);
4115 return aDocShell->InternalLoad(loadState);
4116}
4117
4118NS_IMETHODIMPnsresult
4119nsDocShell::Stop(uint32_t aStopFlags) {
4120 // Revoke any pending event related to content viewer restoration
4121 mRestorePresentationEvent.Revoke();
4122
4123 if (mLoadType == LOAD_ERROR_PAGE) {
4124 if (mLSHE) {
4125 // Since error page loads never unset mLSHE, do so now
4126 SetHistoryEntryAndUpdateBC(Some(nullptr), Some<nsISHEntry*>(mLSHE));
4127 }
4128 mActiveEntryIsLoadingFromSessionHistory = false;
4129
4130 mFailedChannel = nullptr;
4131 mFailedURI = nullptr;
4132 }
4133
4134 if (nsIWebNavigation::STOP_CONTENT & aStopFlags) {
4135 // Stop the document loading and animations
4136 if (mDocumentViewer) {
4137 nsCOMPtr<nsIDocumentViewer> viewer = mDocumentViewer;
4138 viewer->Stop();
4139 }
4140 } else if (nsIWebNavigation::STOP_NETWORK & aStopFlags) {
4141 // Stop the document loading only
4142 if (mDocumentViewer) {
4143 RefPtr<Document> doc = mDocumentViewer->GetDocument();
4144 if (doc) {
4145 doc->StopDocumentLoad();
4146 }
4147 }
4148 }
4149
4150 if (nsIWebNavigation::STOP_NETWORK & aStopFlags) {
4151 // Suspend any timers that were set for this loader. We'll clear
4152 // them out for good in CreateDocumentViewer.
4153 if (mRefreshURIList) {
4154 SuspendRefreshURIs();
4155 mSavedRefreshURIList.swap(mRefreshURIList);
4156 mRefreshURIList = nullptr;
4157 }
4158
4159 // XXXbz We could also pass |this| to nsIURILoader::Stop. That will
4160 // just call Stop() on us as an nsIDocumentLoader... We need fewer
4161 // redundant apis!
4162 Stop();
4163
4164 // Clear out mChannelToDisconnectOnPageHide. This page won't go in the
4165 // BFCache now, and the Stop above will have removed the DocumentChannel
4166 // from the loadgroup.
4167 mChannelToDisconnectOnPageHide = 0;
4168 }
4169
4170 for (auto* child : mChildList.ForwardRange()) {
4171 nsCOMPtr<nsIWebNavigation> shellAsNav(do_QueryObject(child));
4172 if (shellAsNav) {
4173 shellAsNav->Stop(aStopFlags);
4174 }
4175 }
4176
4177 return NS_OK;
4178}
4179
4180NS_IMETHODIMPnsresult
4181nsDocShell::GetDocument(Document** aDocument) {
4182 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"
, 4182); return NS_ERROR_INVALID_POINTER; } } while (false)
;
4183 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"
, 4183); return NS_ERROR_FAILURE; } } while (false)
;
4184
4185 RefPtr<Document> doc = mDocumentViewer->GetDocument();
4186 if (!doc) {
4187 return NS_ERROR_NOT_AVAILABLE;
4188 }
4189
4190 doc.forget(aDocument);
4191 return NS_OK;
4192}
4193
4194NS_IMETHODIMPnsresult
4195nsDocShell::GetCurrentURI(nsIURI** aURI) {
4196 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"
, 4196); return NS_ERROR_INVALID_POINTER; } } while (false)
;
4197
4198 nsCOMPtr<nsIURI> uri = mCurrentURI;
4199 uri.forget(aURI);
4200 return NS_OK;
4201}
4202
4203NS_IMETHODIMPnsresult
4204nsDocShell::GetSessionHistoryXPCOM(nsISupports** aSessionHistory) {
4205 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"
, 4205); return NS_ERROR_INVALID_POINTER; } } while (false)
;
4206 RefPtr<ChildSHistory> shistory = GetSessionHistory();
4207 shistory.forget(aSessionHistory);
4208 return NS_OK;
4209}
4210
4211//*****************************************************************************
4212// nsDocShell::nsIWebPageDescriptor
4213//*****************************************************************************
4214
4215NS_IMETHODIMPnsresult
4216nsDocShell::LoadPageAsViewSource(nsIDocShell* aOtherDocShell,
4217 const nsAString& aURI) {
4218 if (!aOtherDocShell) {
4219 return NS_ERROR_INVALID_POINTER;
4220 }
4221 nsCOMPtr<nsIURI> newURI;
4222 nsresult rv = NS_NewURI(getter_AddRefs(newURI), aURI);
4223 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
4224 return rv;
4225 }
4226
4227 RefPtr<nsDocShellLoadState> loadState;
4228 uint32_t cacheKey;
4229 auto* otherDocShell = nsDocShell::Cast(aOtherDocShell);
4230 if (mozilla::SessionHistoryInParent()) {
4231 loadState = new nsDocShellLoadState(newURI);
4232 if (!otherDocShell->FillLoadStateFromCurrentEntry(*loadState)) {
4233 return NS_ERROR_INVALID_POINTER;
4234 }
4235 cacheKey = otherDocShell->GetCacheKeyFromCurrentEntry().valueOr(0);
4236 } else {
4237 nsCOMPtr<nsISHEntry> entry;
4238 bool isOriginalSHE;
4239 otherDocShell->GetCurrentSHEntry(getter_AddRefs(entry), &isOriginalSHE);
4240 if (!entry) {
4241 return NS_ERROR_INVALID_POINTER;
4242 }
4243 rv = entry->CreateLoadInfo(getter_AddRefs(loadState));
4244 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"
, 4244); return rv; } } while (false)
;
4245 entry->GetCacheKey(&cacheKey);
4246 loadState->SetURI(newURI);
4247 loadState->SetSHEntry(nullptr);
4248 }
4249
4250 // We're doing a load of the page, via an API that
4251 // is only exposed to system code. The triggering principal for this load
4252 // should be the system principal.
4253 loadState->SetTriggeringPrincipal(nsContentUtils::GetSystemPrincipal());
4254 loadState->SetOriginalURI(nullptr);
4255 loadState->SetResultPrincipalURI(nullptr);
4256
4257 return InternalLoad(loadState, Some(cacheKey));
4258}
4259
4260NS_IMETHODIMPnsresult
4261nsDocShell::GetCurrentDescriptor(nsISupports** aPageDescriptor) {
4262 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"
, 4262); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPageDescriptor"
") (" "Null out param?" ")"); do { *((volatile int*)__null) =
4262; __attribute__((nomerge)) ::abort(); } while (false); }
} while (false)
;
4263
4264 *aPageDescriptor = nullptr;
4265
4266 nsISHEntry* src = mOSHE ? mOSHE : mLSHE;
4267 if (src) {
4268 nsCOMPtr<nsISHEntry> dest;
4269
4270 nsresult rv = src->Clone(getter_AddRefs(dest));
4271 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
4272 return rv;
4273 }
4274
4275 // null out inappropriate cloned attributes...
4276 dest->SetParent(nullptr);
4277 dest->SetIsSubFrame(false);
4278
4279 return CallQueryInterface(dest, aPageDescriptor);
4280 }
4281
4282 return NS_ERROR_NOT_AVAILABLE;
4283}
4284
4285already_AddRefed<nsIInputStream> nsDocShell::GetPostDataFromCurrentEntry()
4286 const {
4287 nsCOMPtr<nsIInputStream> postData;
4288 if (mozilla::SessionHistoryInParent()) {
4289 if (mActiveEntry) {
4290 postData = mActiveEntry->GetPostData();
4291 } else if (mLoadingEntry) {
4292 postData = mLoadingEntry->mInfo.GetPostData();
4293 }
4294 } else {
4295 if (mOSHE) {
4296 postData = mOSHE->GetPostData();
4297 } else if (mLSHE) {
4298 postData = mLSHE->GetPostData();
4299 }
4300 }
4301
4302 return postData.forget();
4303}
4304
4305Maybe<uint32_t> nsDocShell::GetCacheKeyFromCurrentEntry() const {
4306 if (mozilla::SessionHistoryInParent()) {
4307 if (mActiveEntry) {
4308 return Some(mActiveEntry->GetCacheKey());
4309 }
4310
4311 if (mLoadingEntry) {
4312 return Some(mLoadingEntry->mInfo.GetCacheKey());
4313 }
4314 } else {
4315 if (mOSHE) {
4316 return Some(mOSHE->GetCacheKey());
4317 }
4318
4319 if (mLSHE) {
4320 return Some(mLSHE->GetCacheKey());
4321 }
4322 }
4323
4324 return Nothing();
4325}
4326
4327bool nsDocShell::FillLoadStateFromCurrentEntry(
4328 nsDocShellLoadState& aLoadState) {
4329 if (mLoadingEntry) {
4330 mLoadingEntry->mInfo.FillLoadInfo(aLoadState);
4331 return true;
4332 }
4333 if (mActiveEntry) {
4334 mActiveEntry->FillLoadInfo(aLoadState);
4335 return true;
4336 }
4337 return false;
4338}
4339
4340//*****************************************************************************
4341// nsDocShell::nsIBaseWindow
4342//*****************************************************************************
4343
4344NS_IMETHODIMPnsresult
4345nsDocShell::InitWindow(nsIWidget* aParentWidget, int32_t aX, int32_t aY,
4346 int32_t aWidth, int32_t aHeight) {
4347 SetParentWidget(aParentWidget);
4348 SetPositionAndSize(aX, aY, aWidth, aHeight, 0);
4349 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"
, 4349); return NS_ERROR_FAILURE; } } while (false)
;
4350 return NS_OK;
4351}
4352
4353NS_IMETHODIMPnsresult
4354nsDocShell::Destroy() {
4355 // XXX: We allow this function to be called just once. If you are going to
4356 // reset new variables in this function, please make sure the variables will
4357 // never be re-initialized. Adding assertions to check |mIsBeingDestroyed|
4358 // in the setter functions for the variables would be enough.
4359 if (mIsBeingDestroyed) {
4360 return NS_ERROR_DOCSHELL_DYING;
4361 }
4362
4363 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"
, 4364); MOZ_PretendNoReturn(); } } while (0)
4364 "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"
, 4364); MOZ_PretendNoReturn(); } } while (0)
;
4365
4366 nsCOMPtr<nsIObserverService> serv = services::GetObserverService();
4367 if (serv) {
4368 const char* msg = mItemType == typeContent
4369 ? NS_WEBNAVIGATION_DESTROY"webnavigation-destroy"
4370 : NS_CHROME_WEBNAVIGATION_DESTROY"chrome-webnavigation-destroy";
4371 serv->NotifyObservers(GetAsSupports(this), msg, nullptr);
4372 }
4373
4374 mIsBeingDestroyed = true;
4375
4376 // Brak the cycle with the initial client, if present.
4377 mInitialClientSource.reset();
4378
4379 // Make sure to blow away our mLoadingURI just in case. No loads
4380 // from inside this pagehide.
4381 mLoadingURI = nullptr;
4382
4383 // Fire unload event before we blow anything away.
4384 (void)FirePageHideNotification(true);
4385
4386 // Clear pointers to any detached nsEditorData that's lying
4387 // around in shistory entries. Breaks cycle. See bug 430921.
4388 if (mOSHE) {
4389 mOSHE->SetEditorData(nullptr);
4390 }
4391 if (mLSHE) {
4392 mLSHE->SetEditorData(nullptr);
4393 }
4394
4395 // Note: mContentListener can be null if Init() failed and we're being
4396 // called from the destructor.
4397 if (mContentListener) {
4398 mContentListener->DropDocShellReference();
4399 mContentListener->SetParentContentListener(nullptr);
4400 // Note that we do NOT set mContentListener to null here; that
4401 // way if someone tries to do a load in us after this point
4402 // the nsDSURIContentListener will block it. All of which
4403 // means that we should do this before calling Stop(), of
4404 // course.
4405 }
4406
4407 // Stop any URLs that are currently being loaded...
4408 Stop(nsIWebNavigation::STOP_ALL);
4409
4410 mEditorData = nullptr;
4411
4412 // Save the state of the current document, before destroying the window.
4413 // This is needed to capture the state of a frameset when the new document
4414 // causes the frameset to be destroyed...
4415 PersistLayoutHistoryState();
4416
4417 // Remove this docshell from its parent's child list
4418 nsCOMPtr<nsIDocShellTreeItem> docShellParentAsItem =
4419 do_QueryInterface(GetAsSupports(mParent));
4420 if (docShellParentAsItem) {
4421 docShellParentAsItem->RemoveChild(this);
4422 }
4423
4424 if (mDocumentViewer) {
4425 mDocumentViewer->Close(nullptr);
4426 mDocumentViewer->Destroy();
4427 mDocumentViewer = nullptr;
4428 }
4429
4430 nsDocLoader::Destroy();
4431
4432 mParentWidget = nullptr;
4433 SetCurrentURIInternal(nullptr);
4434
4435 if (mScriptGlobal) {
4436 mScriptGlobal->DetachFromDocShell(!mWillChangeProcess);
4437 mScriptGlobal = nullptr;
4438 }
4439
4440 if (GetSessionHistory()) {
4441 // We want to destroy these content viewers now rather than
4442 // letting their destruction wait for the session history
4443 // entries to get garbage collected. (Bug 488394)
4444 GetSessionHistory()->EvictLocalDocumentViewers();
4445 }
4446
4447 if (mWillChangeProcess && !mBrowsingContext->IsDiscarded()) {
4448 mBrowsingContext->PrepareForProcessChange();
4449 }
4450
4451 SetTreeOwner(nullptr);
4452
4453 mBrowserChild = nullptr;
4454
4455 mChromeEventHandler = nullptr;
4456
4457 // Cancel any timers that were set for this docshell; this is needed
4458 // to break the cycle between us and the timers.
4459 CancelRefreshURITimers();
4460
4461 return NS_OK;
4462}
4463
4464double nsDocShell::GetWidgetCSSToDeviceScale() {
4465 if (mParentWidget) {
4466 return mParentWidget->GetDefaultScale().scale;
4467 }
4468 if (nsCOMPtr<nsIBaseWindow> ownerWindow = do_QueryInterface(mTreeOwner)) {
4469 return ownerWindow->GetWidgetCSSToDeviceScale();
4470 }
4471 return 1.0;
4472}
4473
4474NS_IMETHODIMPnsresult
4475nsDocShell::GetDevicePixelsPerDesktopPixel(double* aScale) {
4476 if (mParentWidget) {
4477 *aScale = mParentWidget->GetDesktopToDeviceScale().scale;
4478 return NS_OK;
4479 }
4480
4481 nsCOMPtr<nsIBaseWindow> ownerWindow(do_QueryInterface(mTreeOwner));
4482 if (ownerWindow) {
4483 return ownerWindow->GetDevicePixelsPerDesktopPixel(aScale);
4484 }
4485
4486 *aScale = 1.0;
4487 return NS_OK;
4488}
4489
4490NS_IMETHODIMPnsresult
4491nsDocShell::SetPosition(int32_t aX, int32_t aY) {
4492 mBounds.MoveTo(aX, aY);
4493
4494 if (mDocumentViewer) {
4495 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"
, 4495); return NS_ERROR_FAILURE; } } while (false)
;
4496 }
4497
4498 return NS_OK;
4499}
4500
4501NS_IMETHODIMPnsresult
4502nsDocShell::SetPositionDesktopPix(int32_t aX, int32_t aY) {
4503 nsCOMPtr<nsIBaseWindow> ownerWindow(do_QueryInterface(mTreeOwner));
4504 if (ownerWindow) {
4505 return ownerWindow->SetPositionDesktopPix(aX, aY);
4506 }
4507
4508 double scale = 1.0;
4509 GetDevicePixelsPerDesktopPixel(&scale);
4510 return SetPosition(NSToIntRound(aX * scale), NSToIntRound(aY * scale));
4511}
4512
4513NS_IMETHODIMPnsresult
4514nsDocShell::GetPosition(int32_t* aX, int32_t* aY) {
4515 return GetPositionAndSize(aX, aY, nullptr, nullptr);
4516}
4517
4518NS_IMETHODIMPnsresult
4519nsDocShell::SetSize(int32_t aWidth, int32_t aHeight, bool aRepaint) {
4520 int32_t x = 0, y = 0;
4521 GetPosition(&x, &y);
4522 return SetPositionAndSize(x, y, aWidth, aHeight,
4523 aRepaint ? nsIBaseWindow::eRepaint : 0);
4524}
4525
4526NS_IMETHODIMPnsresult
4527nsDocShell::GetSize(int32_t* aWidth, int32_t* aHeight) {
4528 return GetPositionAndSize(nullptr, nullptr, aWidth, aHeight);
4529}
4530
4531NS_IMETHODIMPnsresult
4532nsDocShell::SetPositionAndSize(int32_t aX, int32_t aY, int32_t aWidth,
4533 int32_t aHeight, uint32_t aFlags) {
4534 mBounds.SetRect(aX, aY, aWidth, aHeight);
4535
4536 // Hold strong ref, since SetBounds can make us null out mDocumentViewer
4537 nsCOMPtr<nsIDocumentViewer> viewer = mDocumentViewer;
4538 if (viewer) {
4539 uint32_t cvflags = (aFlags & nsIBaseWindow::eDelayResize)
4540 ? nsIDocumentViewer::eDelayResize
4541 : 0;
4542 // XXX Border figured in here or is that handled elsewhere?
4543 nsresult rv = viewer->SetBoundsWithFlags(mBounds, cvflags);
4544 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"
, 4544); return NS_ERROR_FAILURE; } } while (false)
;
4545 }
4546
4547 return NS_OK;
4548}
4549
4550NS_IMETHODIMPnsresult
4551nsDocShell::GetPositionAndSize(int32_t* aX, int32_t* aY, int32_t* aWidth,
4552 int32_t* aHeight) {
4553 if (mParentWidget) {
4554 // ensure size is up-to-date if window has changed resolution
4555 LayoutDeviceIntRect r = mParentWidget->GetClientBounds();
4556 SetPositionAndSize(mBounds.X(), mBounds.Y(), r.Width(), r.Height(), 0);
4557 }
4558
4559 // We should really consider just getting this information from
4560 // our window instead of duplicating the storage and code...
4561 if (aWidth || aHeight) {
4562 // Caller wants to know our size; make sure to give them up to
4563 // date information.
4564 RefPtr<Document> doc(do_GetInterface(GetAsSupports(mParent)));
4565 if (doc) {
4566 doc->FlushPendingNotifications(FlushType::Layout);
4567 }
4568 }
4569
4570 DoGetPositionAndSize(aX, aY, aWidth, aHeight);
4571 return NS_OK;
4572}
4573
4574void nsDocShell::DoGetPositionAndSize(int32_t* aX, int32_t* aY, int32_t* aWidth,
4575 int32_t* aHeight) {
4576 if (aX) {
4577 *aX = mBounds.X();
4578 }
4579 if (aY) {
4580 *aY = mBounds.Y();
4581 }
4582 if (aWidth) {
4583 *aWidth = mBounds.Width();
4584 }
4585 if (aHeight) {
4586 *aHeight = mBounds.Height();
4587 }
4588}
4589
4590NS_IMETHODIMPnsresult
4591nsDocShell::SetDimensions(DimensionRequest&& aRequest) {
4592 return NS_ERROR_NOT_IMPLEMENTED;
4593}
4594
4595NS_IMETHODIMPnsresult
4596nsDocShell::GetDimensions(DimensionKind aDimensionKind, int32_t* aX,
4597 int32_t* aY, int32_t* aCX, int32_t* aCY) {
4598 return NS_ERROR_NOT_IMPLEMENTED;
4599}
4600
4601NS_IMETHODIMPnsresult
4602nsDocShell::Repaint(bool aForce) {
4603 PresShell* presShell = GetPresShell();
4604 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"
, 4604); return NS_ERROR_FAILURE; } } while (false)
;
4605
4606 RefPtr<nsViewManager> viewManager = presShell->GetViewManager();
4607 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"
, 4607); return NS_ERROR_FAILURE; } } while (false)
;
4608
4609 viewManager->InvalidateAllViews();
4610 return NS_OK;
4611}
4612
4613NS_IMETHODIMPnsresult
4614nsDocShell::GetParentWidget(nsIWidget** aParentWidget) {
4615 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"
, 4615); return NS_ERROR_INVALID_POINTER; } } while (false)
;
4616
4617 *aParentWidget = mParentWidget;
4618 NS_IF_ADDREF(*aParentWidget)ns_if_addref(*aParentWidget);
4619
4620 return NS_OK;
4621}
4622
4623NS_IMETHODIMPnsresult
4624nsDocShell::SetParentWidget(nsIWidget* aParentWidget) {
4625 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"
, 4625); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mIsBeingDestroyed"
")"); do { *((volatile int*)__null) = 4625; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4626 mParentWidget = aParentWidget;
4627
4628 return NS_OK;
4629}
4630
4631NS_IMETHODIMPnsresult
4632nsDocShell::GetNativeHandle(nsAString& aNativeHandle) {
4633 // the nativeHandle should be accessed from nsIAppWindow
4634 return NS_ERROR_NOT_IMPLEMENTED;
4635}
4636
4637NS_IMETHODIMPnsresult
4638nsDocShell::GetVisibility(bool* aVisibility) {
4639 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"
, 4639); return NS_ERROR_INVALID_POINTER; } } while (false)
;
4640
4641 *aVisibility = false;
4642
4643 if (!mDocumentViewer) {
4644 return NS_OK;
4645 }
4646
4647 PresShell* presShell = GetPresShell();
4648 if (!presShell) {
4649 return NS_OK;
4650 }
4651
4652 // get the view manager
4653 nsViewManager* vm = presShell->GetViewManager();
4654 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"
, 4654); return NS_ERROR_FAILURE; } } while (false)
;
4655
4656 // get the root view
4657 nsView* view = vm->GetRootView(); // views are not ref counted
4658 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"
, 4658); return NS_ERROR_FAILURE; } } while (false)
;
4659
4660 // if our root view is hidden, we are not visible
4661 if (view->GetVisibility() == ViewVisibility::Hide) {
4662 return NS_OK;
4663 }
4664
4665 // otherwise, we must walk up the document and view trees checking
4666 // for a hidden view, unless we're an off screen browser, which
4667 // would make this test meaningless.
4668
4669 RefPtr<nsDocShell> docShell = this;
4670 RefPtr<nsDocShell> parentItem = docShell->GetInProcessParentDocshell();
4671 while (parentItem) {
4672 // Null-check for crash in bug 267804
4673 if (!parentItem->GetPresShell()) {
4674 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"
, 4674); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "parent docshell has null pres shell"
")"); do { *((volatile int*)__null) = 4674; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4675 return NS_OK;
4676 }
4677
4678 vm = docShell->GetPresShell()->GetViewManager();
4679 if (vm) {
4680 view = vm->GetRootView();
4681 }
4682
4683 if (view) {
4684 view = view->GetParent(); // anonymous inner view
4685 if (view) {
4686 view = view->GetParent(); // subdocumentframe's view
4687 }
4688 }
4689
4690 nsIFrame* frame = view ? view->GetFrame() : nullptr;
4691 if (frame && !frame->IsVisibleConsideringAncestors(
4692 nsIFrame::VISIBILITY_CROSS_CHROME_CONTENT_BOUNDARY)) {
4693 return NS_OK;
4694 }
4695
4696 docShell = parentItem;
4697 parentItem = docShell->GetInProcessParentDocshell();
4698 }
4699
4700 nsCOMPtr<nsIBaseWindow> treeOwnerAsWin(do_QueryInterface(mTreeOwner));
4701 if (!treeOwnerAsWin) {
4702 *aVisibility = true;
4703 return NS_OK;
4704 }
4705
4706 // Check with the tree owner as well to give embedders a chance to
4707 // expose visibility as well.
4708 nsresult rv = treeOwnerAsWin->GetVisibility(aVisibility);
4709 if (rv == NS_ERROR_NOT_IMPLEMENTED) {
4710 // The tree owner had no opinion on our visibility.
4711 *aVisibility = true;
4712 return NS_OK;
4713 }
4714 return rv;
4715}
4716
4717void nsDocShell::ActivenessMaybeChanged() {
4718 const bool isActive = mBrowsingContext->IsActive();
4719 if (RefPtr<PresShell> presShell = GetPresShell()) {
4720 presShell->ActivenessMaybeChanged();
4721 }
4722
4723 // Tell the window about it
4724 if (mScriptGlobal) {
4725 mScriptGlobal->SetIsBackground(!isActive);
4726 if (RefPtr<Document> doc = mScriptGlobal->GetExtantDoc()) {
4727 // Update orientation when the top-level browsing context becomes active.
4728 if (isActive && mBrowsingContext->IsTop()) {
4729 // We only care about the top-level browsing context.
4730 auto orientation = mBrowsingContext->GetOrientationLock();
4731 ScreenOrientation::UpdateActiveOrientationLock(orientation);
4732 }
4733
4734 doc->PostVisibilityUpdateEvent();
4735 }
4736 }
4737
4738 // Tell the nsDOMNavigationTiming about it
4739 RefPtr<nsDOMNavigationTiming> timing = mTiming;
4740 if (!timing && mDocumentViewer) {
4741 if (Document* doc = mDocumentViewer->GetDocument()) {
4742 timing = doc->GetNavigationTiming();
4743 }
4744 }
4745 if (timing) {
4746 timing->NotifyDocShellStateChanged(
4747 isActive ? nsDOMNavigationTiming::DocShellState::eActive
4748 : nsDOMNavigationTiming::DocShellState::eInactive);
4749 }
4750
4751 // Restart or stop meta refresh timers if necessary
4752 if (mDisableMetaRefreshWhenInactive) {
4753 if (isActive) {
4754 ResumeRefreshURIs();
4755 } else {
4756 SuspendRefreshURIs();
4757 }
4758 }
4759
4760 if (InputTaskManager::CanSuspendInputEvent()) {
4761 mBrowsingContext->Group()->UpdateInputTaskManagerIfNeeded(isActive);
4762 }
4763}
4764
4765NS_IMETHODIMPnsresult
4766nsDocShell::SetDefaultLoadFlags(uint32_t aDefaultLoadFlags) {
4767 if (!mWillChangeProcess) {
4768 // Intentionally ignoring handling discarded browsing contexts.
4769 Unused << mBrowsingContext->SetDefaultLoadFlags(aDefaultLoadFlags);
4770 } else {
4771 // Bug 1623565: DevTools tries to clean up defaultLoadFlags on
4772 // shutdown. Sorry DevTools, your DocShell is in another process.
4773 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"
, 4773)
;
4774 }
4775 return NS_OK;
4776}
4777
4778NS_IMETHODIMPnsresult
4779nsDocShell::GetDefaultLoadFlags(uint32_t* aDefaultLoadFlags) {
4780 *aDefaultLoadFlags = mBrowsingContext->GetDefaultLoadFlags();
4781 return NS_OK;
4782}
4783
4784NS_IMETHODIMPnsresult
4785nsDocShell::GetFailedChannel(nsIChannel** aFailedChannel) {
4786 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"
, 4786); return NS_ERROR_INVALID_POINTER; } } while (false)
;
4787 Document* doc = GetDocument();
4788 if (!doc) {
4789 *aFailedChannel = nullptr;
4790 return NS_OK;
4791 }
4792 NS_IF_ADDREF(*aFailedChannel = doc->GetFailedChannel())ns_if_addref(*aFailedChannel = doc->GetFailedChannel());
4793 return NS_OK;
4794}
4795
4796NS_IMETHODIMPnsresult
4797nsDocShell::SetVisibility(bool aVisibility) {
4798 // Show()/Hide() may change mDocumentViewer.
4799 nsCOMPtr<nsIDocumentViewer> viewer = mDocumentViewer;
4800 if (!viewer) {
4801 return NS_OK;
4802 }
4803 if (aVisibility) {
4804 viewer->Show();
4805 } else {
4806 viewer->Hide();
4807 }
4808
4809 return NS_OK;
4810}
4811
4812NS_IMETHODIMPnsresult
4813nsDocShell::GetEnabled(bool* aEnabled) {
4814 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"
, 4814); return NS_ERROR_INVALID_POINTER; } } while (false)
;
4815 *aEnabled = true;
4816 return NS_ERROR_NOT_IMPLEMENTED;
4817}
4818
4819NS_IMETHODIMPnsresult
4820nsDocShell::SetEnabled(bool aEnabled) { return NS_ERROR_NOT_IMPLEMENTED; }
4821
4822NS_IMETHODIMPnsresult
4823nsDocShell::GetMainWidget(nsIWidget** aMainWidget) {
4824 // We don't create our own widget, so simply return the parent one.
4825 return GetParentWidget(aMainWidget);
4826}
4827
4828NS_IMETHODIMPnsresult
4829nsDocShell::GetTitle(nsAString& aTitle) {
4830 aTitle = mTitle;
4831 return NS_OK;
4832}
4833
4834NS_IMETHODIMPnsresult
4835nsDocShell::SetTitle(const nsAString& aTitle) {
4836 // Avoid unnecessary updates of the title if the URI and the title haven't
4837 // changed.
4838 if (mTitleValidForCurrentURI && mTitle == aTitle) {
4839 return NS_OK;
4840 }
4841
4842 // Store local title
4843 mTitle = aTitle;
4844 mTitleValidForCurrentURI = true;
4845
4846 // When title is set on the top object it should then be passed to the
4847 // tree owner.
4848 if (mBrowsingContext->IsTop()) {
4849 nsCOMPtr<nsIBaseWindow> treeOwnerAsWin(do_QueryInterface(mTreeOwner));
4850 if (treeOwnerAsWin) {
4851 treeOwnerAsWin->SetTitle(aTitle);
4852 }
4853 }
4854
4855 if (mCurrentURI && mLoadType != LOAD_ERROR_PAGE) {
4856 UpdateGlobalHistoryTitle(mCurrentURI);
4857 }
4858
4859 // Update SessionHistory with the document's title.
4860 if (mLoadType != LOAD_BYPASS_HISTORY && mLoadType != LOAD_ERROR_PAGE) {
4861 SetTitleOnHistoryEntry(true);
4862 }
4863
4864 return NS_OK;
4865}
4866
4867void nsDocShell::SetTitleOnHistoryEntry(bool aUpdateEntryInSessionHistory) {
4868 if (mOSHE) {
4869 mOSHE->SetTitle(mTitle);
4870 }
4871
4872 if (mActiveEntry && mBrowsingContext) {
4873 mActiveEntry->SetTitle(mTitle);
4874 if (aUpdateEntryInSessionHistory) {
4875 if (XRE_IsParentProcess()) {
4876 SessionHistoryEntry* entry =
4877 mBrowsingContext->Canonical()->GetActiveSessionHistoryEntry();
4878 if (entry) {
4879 entry->SetTitle(mTitle);
4880 }
4881 } else {
4882 mozilla::Unused
4883 << ContentChild::GetSingleton()->SendSessionHistoryEntryTitle(
4884 mBrowsingContext, mTitle);
4885 }
4886 }
4887 }
4888}
4889
4890nsPoint nsDocShell::GetCurScrollPos() {
4891 nsPoint scrollPos;
4892 if (ScrollContainerFrame* sf = GetRootScrollContainerFrame()) {
4893 scrollPos = sf->GetVisualViewportOffset();
4894 }
4895 return scrollPos;
4896}
4897
4898nsresult nsDocShell::SetCurScrollPosEx(int32_t aCurHorizontalPos,
4899 int32_t aCurVerticalPos) {
4900 ScrollContainerFrame* sf = GetRootScrollContainerFrame();
4901 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"
, 4901); return NS_ERROR_FAILURE; } } while (false)
;
4902
4903 ScrollMode scrollMode =
4904 sf->IsSmoothScroll() ? ScrollMode::SmoothMsd : ScrollMode::Instant;
4905
4906 nsPoint targetPos(aCurHorizontalPos, aCurVerticalPos);
4907 sf->ScrollTo(targetPos, scrollMode);
4908
4909 // Set the visual viewport offset as well.
4910
4911 RefPtr<PresShell> presShell = GetPresShell();
4912 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"
, 4912); return NS_ERROR_FAILURE; } } while (false)
;
4913
4914 nsPresContext* presContext = presShell->GetPresContext();
4915 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"
, 4915); return NS_ERROR_FAILURE; } } while (false)
;
4916
4917 // Only the root content document can have a distinct visual viewport offset.
4918 if (!presContext->IsRootContentDocumentCrossProcess()) {
4919 return NS_OK;
4920 }
4921
4922 // Not on a platform with a distinct visual viewport - don't bother setting
4923 // the visual viewport offset.
4924 if (!presShell->IsVisualViewportSizeSet()) {
4925 return NS_OK;
4926 }
4927
4928 presShell->ScrollToVisual(targetPos, layers::FrameMetrics::eMainThread,
4929 scrollMode);
4930
4931 return NS_OK;
4932}
4933
4934void nsDocShell::SetScrollbarPreference(mozilla::ScrollbarPreference aPref) {
4935 if (mScrollbarPref == aPref) {
4936 return;
4937 }
4938 mScrollbarPref = aPref;
4939 auto* ps = GetPresShell();
4940 if (!ps) {
4941 return;
4942 }
4943 nsIFrame* rootScrollContainerFrame = ps->GetRootScrollContainerFrame();
4944 if (!rootScrollContainerFrame) {
4945 return;
4946 }
4947 ps->FrameNeedsReflow(rootScrollContainerFrame,
4948 IntrinsicDirty::FrameAncestorsAndDescendants,
4949 NS_FRAME_IS_DIRTY);
4950}
4951
4952//*****************************************************************************
4953// nsDocShell::nsIRefreshURI
4954//*****************************************************************************
4955
4956NS_IMETHODIMPnsresult
4957nsDocShell::RefreshURI(nsIURI* aURI, nsIPrincipal* aPrincipal,
4958 uint32_t aDelay) {
4959 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"
, 4959); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mIsBeingDestroyed"
")"); do { *((volatile int*)__null) = 4959; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4960
4961 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"
, 4961); return NS_ERROR_INVALID_ARG; } } while (false)
;
4962
4963 /* Check if Meta refresh/redirects are permitted. Some
4964 * embedded applications may not want to do this.
4965 * Must do this before sending out NOTIFY_REFRESH events
4966 * because listeners may have side effects (e.g. displaying a
4967 * button to manually trigger the refresh later).
4968 */
4969 bool allowRedirects = true;
4970 GetAllowMetaRedirects(&allowRedirects);
4971 if (!allowRedirects) {
4972 return NS_OK;
4973 }
4974
4975 // If any web progress listeners are listening for NOTIFY_REFRESH events,
4976 // give them a chance to block this refresh.
4977 bool sameURI;
4978 nsresult rv = aURI->Equals(mCurrentURI, &sameURI);
4979 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
4980 sameURI = false;
4981 }
4982 if (!RefreshAttempted(this, aURI, aDelay, sameURI)) {
4983 return NS_OK;
4984 }
4985
4986 nsCOMPtr<nsITimerCallback> refreshTimer =
4987 new nsRefreshTimer(this, aURI, aPrincipal, aDelay);
4988
4989 BusyFlags busyFlags = GetBusyFlags();
4990
4991 if (!mRefreshURIList) {
4992 mRefreshURIList = nsArray::Create();
4993 }
4994
4995 if (busyFlags & BUSY_FLAGS_BUSY ||
4996 (!mBrowsingContext->IsActive() && mDisableMetaRefreshWhenInactive)) {
4997 // We don't want to create the timer right now. Instead queue up the
4998 // request and trigger the timer in EndPageLoad() or whenever we become
4999 // active.
5000 mRefreshURIList->AppendElement(refreshTimer);
5001 } else {
5002 // There is no page loading going on right now. Create the
5003 // timer and fire it right away.
5004 nsCOMPtr<nsPIDOMWindowOuter> win = GetWindow();
5005 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"
, 5005); return NS_ERROR_FAILURE; } } while (false)
;
5006
5007 nsCOMPtr<nsITimer> timer;
5008 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)
5009 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)
;
5010
5011 mRefreshURIList->AppendElement(timer); // owning timer ref
5012 }
5013 return NS_OK;
5014}
5015
5016nsresult nsDocShell::ForceRefreshURIFromTimer(nsIURI* aURI,
5017 nsIPrincipal* aPrincipal,
5018 uint32_t aDelay,
5019 nsITimer* aTimer) {
5020 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"
, 5020); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aTimer" ") ("
"Must have a timer here" ")"); do { *((volatile int*)__null)
= 5020; __attribute__((nomerge)) ::abort(); } while (false);
} } while (false)
;
5021
5022 // Remove aTimer from mRefreshURIList if needed
5023 if (mRefreshURIList) {
5024 uint32_t n = 0;
5025 mRefreshURIList->GetLength(&n);
5026
5027 for (uint32_t i = 0; i < n; ++i) {
5028 nsCOMPtr<nsITimer> timer = do_QueryElementAt(mRefreshURIList, i);
5029 if (timer == aTimer) {
5030 mRefreshURIList->RemoveElementAt(i);
5031 break;
5032 }
5033 }
5034 }
5035
5036 return ForceRefreshURI(aURI, aPrincipal, aDelay);
5037}
5038
5039NS_IMETHODIMPnsresult
5040nsDocShell::ForceRefreshURI(nsIURI* aURI, nsIPrincipal* aPrincipal,
5041 uint32_t aDelay) {
5042 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"
, 5042); return NS_ERROR_INVALID_ARG; } } while (false)
;
5043
5044 RefPtr<nsDocShellLoadState> loadState = new nsDocShellLoadState(aURI);
5045 loadState->SetOriginalURI(mCurrentURI);
5046 loadState->SetResultPrincipalURI(aURI);
5047 loadState->SetResultPrincipalURIIsSome(true);
5048 loadState->SetKeepResultPrincipalURIIfSet(true);
5049 loadState->SetIsMetaRefresh(true);
5050
5051 RefPtr<Document> doc = GetDocument();
5052 NS_ENSURE_STATE(doc)do { if ((__builtin_expect(!!(!(doc)), 0))) { NS_DebugBreak(NS_DEBUG_WARNING
, "NS_ENSURE_TRUE(" "doc" ") failed", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 5052); return NS_ERROR_UNEXPECTED; } } while (false)
;
5053
5054 // Set the triggering pricipal to aPrincipal if available, or current
5055 // document's principal otherwise.
5056 nsCOMPtr<nsIPrincipal> principal = aPrincipal;
5057 if (!principal) {
5058 principal = doc->NodePrincipal();
5059 }
5060 loadState->SetTriggeringPrincipal(principal);
5061 loadState->SetCsp(doc->GetCsp());
5062 loadState->SetHasValidUserGestureActivation(
5063 doc->HasValidTransientUserGestureActivation());
5064
5065 loadState->SetTextDirectiveUserActivation(
5066 doc->ConsumeTextDirectiveUserActivation() ||
5067 loadState->HasValidUserGestureActivation());
5068 loadState->SetTriggeringSandboxFlags(doc->GetSandboxFlags());
5069 loadState->SetTriggeringWindowId(doc->InnerWindowID());
5070 loadState->SetTriggeringStorageAccess(doc->UsingStorageAccess());
5071
5072 loadState->SetPrincipalIsExplicit(true);
5073
5074 /* Check if this META refresh causes a redirection
5075 * to another site.
5076 */
5077 bool equalUri = false;
5078 nsresult rv = aURI->Equals(mCurrentURI, &equalUri);
5079
5080 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && !equalUri && aDelay <= REFRESH_REDIRECT_TIMER15000) {
5081 /* It is a META refresh based redirection within the threshold time
5082 * we have in mind (15000 ms as defined by REFRESH_REDIRECT_TIMER).
5083 * Pass a REPLACE flag to LoadURI().
5084 */
5085 loadState->SetLoadType(LOAD_REFRESH_REPLACE);
5086 } else {
5087 loadState->SetLoadType(LOAD_REFRESH);
5088 }
5089
5090 const bool sendReferrer = StaticPrefs::network_http_referer_sendFromRefresh();
5091 /* The document's referrer policy is needed instead of mReferrerInfo's
5092 * referrer policy.
5093 */
5094 const nsCOMPtr<nsIReferrerInfo> referrerInfo =
5095 new ReferrerInfo(*doc, sendReferrer);
5096 /* We mimic HTTP, which passes the original referrer. See step 3 of
5097 * <https://html.spec.whatwg.org/multipage/browsing-the-web.html#create-navigation-params-by-fetching>.
5098 */
5099 loadState->SetReferrerInfo(referrerInfo);
5100
5101 loadState->SetLoadFlags(
5102 nsIWebNavigation::LOAD_FLAGS_DISALLOW_INHERIT_PRINCIPAL);
5103 loadState->SetFirstParty(true);
5104
5105 /*
5106 * LoadURI(...) will cancel all refresh timers... This causes the
5107 * Timer and its refreshData instance to be released...
5108 */
5109 LoadURI(loadState, false);
5110
5111 return NS_OK;
5112}
5113
5114static const char16_t* SkipASCIIWhitespace(const char16_t* aStart,
5115 const char16_t* aEnd) {
5116 const char16_t* iter = aStart;
5117 while (iter != aEnd && mozilla::IsAsciiWhitespace(*iter)) {
5118 ++iter;
5119 }
5120 return iter;
5121}
5122
5123static std::tuple<const char16_t*, const char16_t*> ExtractURLString(
5124 const char16_t* aPosition, const char16_t* aEnd) {
5125 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"
, 5125); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPosition != aEnd"
")"); do { *((volatile int*)__null) = 5125; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5126
5127 // 1. Let urlString be the substring of input from the code point at
5128 // position to the end of the string.
5129 const char16_t* urlStart = aPosition;
5130 const char16_t* urlEnd = aEnd;
5131
5132 // 2. If the code point in input pointed to by position is U+0055 (U) or
5133 // U+0075 (u), then advance position to the next code point.
5134 // Otherwise, jump to the step labeled skip quotes.
5135 if (*aPosition == 'U' || *aPosition == 'u') {
5136 ++aPosition;
5137
5138 // 3. If the code point in input pointed to by position is U+0052 (R) or
5139 // U+0072 (r), then advance position to the next code point.
5140 // Otherwise, jump to the step labeled parse.
5141 if (aPosition == aEnd || (*aPosition != 'R' && *aPosition != 'r')) {
5142 return std::make_tuple(urlStart, urlEnd);
5143 }
5144
5145 ++aPosition;
5146
5147 // 4. If the code point in input pointed to by position is U+004C (L) or
5148 // U+006C (l), then advance position to the next code point.
5149 // Otherwise, jump to the step labeled parse.
5150 if (aPosition == aEnd || (*aPosition != 'L' && *aPosition != 'l')) {
5151 return std::make_tuple(urlStart, urlEnd);
5152 }
5153
5154 ++aPosition;
5155
5156 // 5. Skip ASCII whitespace within input given position.
5157 aPosition = SkipASCIIWhitespace(aPosition, aEnd);
5158
5159 // 6. If the code point in input pointed to by position is U+003D (=),
5160 // then advance position to the next code point. Otherwise, jump to
5161 // the step labeled parse.
5162 if (aPosition == aEnd || *aPosition != '=') {
5163 return std::make_tuple(urlStart, urlEnd);
5164 }
5165
5166 ++aPosition;
5167
5168 // 7. Skip ASCII whitespace within input given position.
5169 aPosition = SkipASCIIWhitespace(aPosition, aEnd);
5170 }
5171
5172 // 8. Skip quotes: If the code point in input pointed to by position is
5173 // U+0027 (') or U+0022 ("), then let quote be that code point, and
5174 // advance position to the next code point. Otherwise, let quote be
5175 // the empty string.
5176 Maybe<char> quote;
5177 if (aPosition != aEnd && (*aPosition == '\'' || *aPosition == '"')) {
5178 quote.emplace(*aPosition);
5179 ++aPosition;
5180 }
5181
5182 // 9. Set urlString to the substring of input from the code point at
5183 // position to the end of the string.
5184 urlStart = aPosition;
5185 urlEnd = aEnd;
5186
5187 // 10. If quote is not the empty string, and there is a code point in
5188 // urlString equal to quote, then truncate urlString at that code
5189 // point, so that it and all subsequent code points are removed.
5190 const char16_t* quotePos;
5191 if (quote.isSome() &&
5192 (quotePos = nsCharTraits<char16_t>::find(
5193 urlStart, std::distance(urlStart, aEnd), quote.value()))) {
5194 urlEnd = quotePos;
5195 }
5196
5197 return std::make_tuple(urlStart, urlEnd);
5198}
5199
5200void nsDocShell::SetupRefreshURIFromHeader(Document* aDocument,
5201 const nsAString& aHeader) {
5202 if (mIsBeingDestroyed) {
5203 return;
5204 }
5205
5206 const char16_t* position = aHeader.BeginReading();
5207 const char16_t* end = aHeader.EndReading();
5208
5209 // See https://html.spec.whatwg.org/#shared-declarative-refresh-steps.
5210
5211 // 3. Skip ASCII whitespace
5212 position = SkipASCIIWhitespace(position, end);
5213
5214 // 4. Let time be 0.
5215 CheckedInt<uint32_t> milliSeconds;
5216
5217 // 5. Collect a sequence of code points that are ASCII digits
5218 const char16_t* digitsStart = position;
5219 while (position != end && mozilla::IsAsciiDigit(*position)) {
5220 ++position;
5221 }
5222
5223 if (position == digitsStart) {
5224 // 6. If timeString is the empty string, then:
5225 // 1. If the code point in input pointed to by position is not U+002E
5226 // (.), then return.
5227 if (position == end || *position != '.') {
5228 return;
5229 }
5230 } else {
5231 // 7. Otherwise, set time to the result of parsing timeString using the
5232 // rules for parsing non-negative integers.
5233 nsContentUtils::ParseHTMLIntegerResultFlags result;
5234 uint32_t seconds =
5235 nsContentUtils::ParseHTMLInteger(digitsStart, position, &result);
5236 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"
, 5236); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!(result & nsContentUtils::eParseHTMLInteger_Negative)"
")"); do { *((volatile int*)__null) = 5236; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5237 if (result & nsContentUtils::eParseHTMLInteger_Error) {
5238 // The spec assumes no errors here (since we only pass ASCII digits in),
5239 // but we can still overflow, so this block should deal with that (and
5240 // only that).
5241 MOZ_ASSERT(do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!(result & ~(nsContentUtils::eParseHTMLInteger_DidNotConsumeAllInput
| nsContentUtils::eParseHTMLInteger_Error | nsContentUtils::
eParseHTMLInteger_ErrorOverflow)))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!(result & ~(nsContentUtils
::eParseHTMLInteger_DidNotConsumeAllInput | nsContentUtils::eParseHTMLInteger_Error
| nsContentUtils::eParseHTMLInteger_ErrorOverflow))))), 0)))
{ do { } while (false); MOZ_ReportAssertionFailure("!(result & ~(nsContentUtils::eParseHTMLInteger_DidNotConsumeAllInput | nsContentUtils::eParseHTMLInteger_Error | nsContentUtils::eParseHTMLInteger_ErrorOverflow))"
, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 5244); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!(result & ~(nsContentUtils::eParseHTMLInteger_DidNotConsumeAllInput | nsContentUtils::eParseHTMLInteger_Error | nsContentUtils::eParseHTMLInteger_ErrorOverflow))"
")"); do { *((volatile int*)__null) = 5244; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
5242 !(result & ~(nsContentUtils::eParseHTMLInteger_DidNotConsumeAllInput |do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!(result & ~(nsContentUtils::eParseHTMLInteger_DidNotConsumeAllInput
| nsContentUtils::eParseHTMLInteger_Error | nsContentUtils::
eParseHTMLInteger_ErrorOverflow)))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!(result & ~(nsContentUtils
::eParseHTMLInteger_DidNotConsumeAllInput | nsContentUtils::eParseHTMLInteger_Error
| nsContentUtils::eParseHTMLInteger_ErrorOverflow))))), 0)))
{ do { } while (false); MOZ_ReportAssertionFailure("!(result & ~(nsContentUtils::eParseHTMLInteger_DidNotConsumeAllInput | nsContentUtils::eParseHTMLInteger_Error | nsContentUtils::eParseHTMLInteger_ErrorOverflow))"
, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 5244); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!(result & ~(nsContentUtils::eParseHTMLInteger_DidNotConsumeAllInput | nsContentUtils::eParseHTMLInteger_Error | nsContentUtils::eParseHTMLInteger_ErrorOverflow))"
")"); do { *((volatile int*)__null) = 5244; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
5243 nsContentUtils::eParseHTMLInteger_Error |do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!(result & ~(nsContentUtils::eParseHTMLInteger_DidNotConsumeAllInput
| nsContentUtils::eParseHTMLInteger_Error | nsContentUtils::
eParseHTMLInteger_ErrorOverflow)))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!(result & ~(nsContentUtils
::eParseHTMLInteger_DidNotConsumeAllInput | nsContentUtils::eParseHTMLInteger_Error
| nsContentUtils::eParseHTMLInteger_ErrorOverflow))))), 0)))
{ do { } while (false); MOZ_ReportAssertionFailure("!(result & ~(nsContentUtils::eParseHTMLInteger_DidNotConsumeAllInput | nsContentUtils::eParseHTMLInteger_Error | nsContentUtils::eParseHTMLInteger_ErrorOverflow))"
, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 5244); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!(result & ~(nsContentUtils::eParseHTMLInteger_DidNotConsumeAllInput | nsContentUtils::eParseHTMLInteger_Error | nsContentUtils::eParseHTMLInteger_ErrorOverflow))"
")"); do { *((volatile int*)__null) = 5244; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
5244 nsContentUtils::eParseHTMLInteger_ErrorOverflow)))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!(result & ~(nsContentUtils::eParseHTMLInteger_DidNotConsumeAllInput
| nsContentUtils::eParseHTMLInteger_Error | nsContentUtils::
eParseHTMLInteger_ErrorOverflow)))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!(result & ~(nsContentUtils
::eParseHTMLInteger_DidNotConsumeAllInput | nsContentUtils::eParseHTMLInteger_Error
| nsContentUtils::eParseHTMLInteger_ErrorOverflow))))), 0)))
{ do { } while (false); MOZ_ReportAssertionFailure("!(result & ~(nsContentUtils::eParseHTMLInteger_DidNotConsumeAllInput | nsContentUtils::eParseHTMLInteger_Error | nsContentUtils::eParseHTMLInteger_ErrorOverflow))"
, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 5244); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!(result & ~(nsContentUtils::eParseHTMLInteger_DidNotConsumeAllInput | nsContentUtils::eParseHTMLInteger_Error | nsContentUtils::eParseHTMLInteger_ErrorOverflow))"
")"); do { *((volatile int*)__null) = 5244; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5245 return;
5246 }
5247 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"
, 5248); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!(result & nsContentUtils::eParseHTMLInteger_DidNotConsumeAllInput)"
")"); do { *((volatile int*)__null) = 5248; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
5248 !(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"
, 5248); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!(result & nsContentUtils::eParseHTMLInteger_DidNotConsumeAllInput)"
")"); do { *((volatile int*)__null) = 5248; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5249
5250 milliSeconds = seconds;
5251 milliSeconds *= 1000;
5252 if (!milliSeconds.isValid()) {
5253 return;
5254 }
5255 }
5256
5257 // 8. Collect a sequence of code points that are ASCII digits and U+002E FULL
5258 // STOP characters (.) from input given position. Ignore any collected
5259 // characters.
5260 while (position != end &&
5261 (mozilla::IsAsciiDigit(*position) || *position == '.')) {
5262 ++position;
5263 }
5264
5265 // 9. Let urlRecord be document's URL.
5266 nsCOMPtr<nsIURI> urlRecord(aDocument->GetDocumentURI());
5267
5268 // 10. If position is not past the end of input
5269 if (position != end) {
5270 // 1. If the code point in input pointed to by position is not U+003B (;),
5271 // U+002C (,), or ASCII whitespace, then return.
5272 if (*position != ';' && *position != ',' &&
5273 !mozilla::IsAsciiWhitespace(*position)) {
5274 return;
5275 }
5276
5277 // 2. Skip ASCII whitespace within input given position.
5278 position = SkipASCIIWhitespace(position, end);
5279
5280 // 3. If the code point in input pointed to by position is U+003B (;) or
5281 // U+002C (,), then advance position to the next code point.
5282 if (position != end && (*position == ';' || *position == ',')) {
5283 ++position;
5284
5285 // 4. Skip ASCII whitespace within input given position.
5286 position = SkipASCIIWhitespace(position, end);
5287 }
5288
5289 // 11. If position is not past the end of input, then:
5290 if (position != end) {
5291 const char16_t* urlStart;
5292 const char16_t* urlEnd;
5293
5294 // 1-10. See ExtractURLString.
5295 std::tie(urlStart, urlEnd) = ExtractURLString(position, end);
5296
5297 // 11. Parse: Parse urlString relative to document. If that fails, return.
5298 // Otherwise, set urlRecord to the resulting URL record.
5299 nsresult rv =
5300 NS_NewURI(getter_AddRefs(urlRecord),
5301 Substring(urlStart, std::distance(urlStart, urlEnd)),
5302 /* charset = */ nullptr, aDocument->GetDocBaseURI());
5303 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"
, 5303); return; } } while (false)
;
5304 }
5305 }
5306
5307 nsIPrincipal* principal = aDocument->NodePrincipal();
5308 nsCOMPtr<nsIScriptSecurityManager> securityManager =
5309 nsContentUtils::GetSecurityManager();
5310 nsresult rv = securityManager->CheckLoadURIWithPrincipal(
5311 principal, urlRecord,
5312 nsIScriptSecurityManager::LOAD_IS_AUTOMATIC_DOCUMENT_REPLACEMENT,
5313 aDocument->InnerWindowID());
5314 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"
, 5314); return; } } while (false)
;
5315
5316 bool isjs = true;
5317 rv = NS_URIChainHasFlags(
5318 urlRecord, nsIProtocolHandler::URI_OPENING_EXECUTES_SCRIPT, &isjs);
5319 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"
, 5319); return; } } while (false)
;
5320
5321 if (isjs) {
5322 return;
5323 }
5324
5325 RefreshURI(urlRecord, principal, milliSeconds.value());
5326}
5327
5328static void DoCancelRefreshURITimers(nsIMutableArray* aTimerList) {
5329 if (!aTimerList) {
5330 return;
5331 }
5332
5333 uint32_t n = 0;
5334 aTimerList->GetLength(&n);
5335
5336 while (n) {
5337 nsCOMPtr<nsITimer> timer(do_QueryElementAt(aTimerList, --n));
5338
5339 aTimerList->RemoveElementAt(n); // bye bye owning timer ref
5340
5341 if (timer) {
5342 timer->Cancel();
5343 }
5344 }
5345}
5346
5347NS_IMETHODIMPnsresult
5348nsDocShell::CancelRefreshURITimers() {
5349 DoCancelRefreshURITimers(mRefreshURIList);
5350 DoCancelRefreshURITimers(mSavedRefreshURIList);
5351 DoCancelRefreshURITimers(mBFCachedRefreshURIList);
5352 mRefreshURIList = nullptr;
5353 mSavedRefreshURIList = nullptr;
5354 mBFCachedRefreshURIList = nullptr;
5355
5356 return NS_OK;
5357}
5358
5359NS_IMETHODIMPnsresult
5360nsDocShell::GetRefreshPending(bool* aResult) {
5361 if (!mRefreshURIList) {
5362 *aResult = false;
5363 return NS_OK;
5364 }
5365
5366 uint32_t count;
5367 nsresult rv = mRefreshURIList->GetLength(&count);
5368 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
5369 *aResult = (count != 0);
5370 }
5371 return rv;
5372}
5373
5374void nsDocShell::RefreshURIToQueue() {
5375 if (mRefreshURIList) {
5376 uint32_t n = 0;
5377 mRefreshURIList->GetLength(&n);
5378
5379 for (uint32_t i = 0; i < n; ++i) {
5380 nsCOMPtr<nsITimer> timer = do_QueryElementAt(mRefreshURIList, i);
5381 if (!timer) {
5382 continue; // this must be a nsRefreshURI already
5383 }
5384
5385 // Replace this timer object with a nsRefreshTimer object.
5386 nsCOMPtr<nsITimerCallback> callback;
5387 timer->GetCallback(getter_AddRefs(callback));
5388
5389 timer->Cancel();
5390
5391 mRefreshURIList->ReplaceElementAt(callback, i);
5392 }
5393 }
5394}
5395
5396NS_IMETHODIMPnsresult
5397nsDocShell::SuspendRefreshURIs() {
5398 RefreshURIToQueue();
5399
5400 // Suspend refresh URIs for our child shells as well.
5401 for (auto* child : mChildList.ForwardRange()) {
5402 nsCOMPtr<nsIDocShell> shell = do_QueryObject(child);
5403 if (shell) {
5404 shell->SuspendRefreshURIs();
5405 }
5406 }
5407
5408 return NS_OK;
5409}
5410
5411NS_IMETHODIMPnsresult
5412nsDocShell::ResumeRefreshURIs() {
5413 RefreshURIFromQueue();
5414
5415 // Resume refresh URIs for our child shells as well.
5416 for (auto* child : mChildList.ForwardRange()) {
5417 nsCOMPtr<nsIDocShell> shell = do_QueryObject(child);
5418 if (shell) {
5419 shell->ResumeRefreshURIs();
5420 }
5421 }
5422
5423 return NS_OK;
5424}
5425
5426nsresult nsDocShell::RefreshURIFromQueue() {
5427 if (!mRefreshURIList) {
5428 return NS_OK;
5429 }
5430 uint32_t n = 0;
5431 mRefreshURIList->GetLength(&n);
5432
5433 while (n) {
5434 nsCOMPtr<nsITimerCallback> refreshInfo =
5435 do_QueryElementAt(mRefreshURIList, --n);
5436
5437 if (refreshInfo) {
5438 // This is the nsRefreshTimer object, waiting to be
5439 // setup in a timer object and fired.
5440 // Create the timer and trigger it.
5441 uint32_t delay = static_cast<nsRefreshTimer*>(
5442 static_cast<nsITimerCallback*>(refreshInfo))
5443 ->GetDelay();
5444 nsCOMPtr<nsPIDOMWindowOuter> win = GetWindow();
5445 if (win) {
5446 nsCOMPtr<nsITimer> timer;
5447 NS_NewTimerWithCallback(getter_AddRefs(timer), refreshInfo, delay,
5448 nsITimer::TYPE_ONE_SHOT);
5449
5450 if (timer) {
5451 // Replace the nsRefreshTimer element in the queue with
5452 // its corresponding timer object, so that in case another
5453 // load comes through before the timer can go off, the timer will
5454 // get cancelled in CancelRefreshURITimer()
5455 mRefreshURIList->ReplaceElementAt(timer, n);
5456 }
5457 }
5458 }
5459 }
5460
5461 return NS_OK;
5462}
5463
5464static bool IsFollowupPartOfMultipart(nsIRequest* aRequest) {
5465 nsCOMPtr<nsIMultiPartChannel> multiPartChannel = do_QueryInterface(aRequest);
5466 bool firstPart = false;
5467 return multiPartChannel &&
5468 NS_SUCCEEDED(multiPartChannel->GetIsFirstPart(&firstPart))((bool)(__builtin_expect(!!(!NS_FAILED_impl(multiPartChannel->
GetIsFirstPart(&firstPart))), 1)))
&&
5469 !firstPart;
5470}
5471
5472nsresult nsDocShell::Embed(nsIDocumentViewer* aDocumentViewer,
5473 WindowGlobalChild* aWindowActor,
5474 bool aIsTransientAboutBlank, bool aPersist,
5475 nsIRequest* aRequest, nsIURI* aPreviousURI) {
5476 // Save the LayoutHistoryState of the previous document, before
5477 // setting up new document
5478 PersistLayoutHistoryState();
5479
5480 nsresult rv = SetupNewViewer(aDocumentViewer, aWindowActor);
5481 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"
, 5481); return rv; } } while (false)
;
5482
5483 // XXX What if SetupNewViewer fails?
5484 if (mozilla::SessionHistoryInParent() ? !!mLoadingEntry : !!mLSHE) {
5485 // Set history.state
5486 SetDocCurrentStateObj(mLSHE,
5487 mLoadingEntry ? &mLoadingEntry->mInfo : nullptr);
5488 }
5489
5490 if (mLSHE) {
5491 // Restore the editing state, if it's stored in session history.
5492 if (mLSHE->HasDetachedEditor()) {
5493 ReattachEditorToWindow(mLSHE);
5494 }
5495
5496 SetHistoryEntryAndUpdateBC(Nothing(), Some<nsISHEntry*>(mLSHE));
5497 }
5498
5499 if (!aIsTransientAboutBlank && mozilla::SessionHistoryInParent() &&
5500 !IsFollowupPartOfMultipart(aRequest)) {
5501 bool expired = false;
5502 uint32_t cacheKey = 0;
5503 nsCOMPtr<nsICacheInfoChannel> cacheChannel = do_QueryInterface(aRequest);
5504 if (cacheChannel) {
5505 // Check if the page has expired from cache
5506 uint32_t expTime = 0;
5507 cacheChannel->GetCacheTokenExpirationTime(&expTime);
5508 uint32_t now = PRTimeToSeconds(PR_Now());
5509 if (expTime <= now) {
5510 expired = true;
5511 }
5512
5513 // The checks for updating cache key are similar to the old session
5514 // history in OnNewURI. Try to update the cache key if
5515 // - we should update session history and aren't doing a session
5516 // history load.
5517 // - we're doing a forced reload.
5518 if (((!mLoadingEntry || !mLoadingEntry->mLoadIsFromSessionHistory) &&
5519 mBrowsingContext->ShouldUpdateSessionHistory(mLoadType)) ||
5520 IsForceReloadType(mLoadType)) {
5521 cacheChannel->GetCacheKey(&cacheKey);
5522 }
5523 }
5524
5525 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)
;
5526 MoveLoadingToActiveEntry(aPersist, expired, cacheKey, aPreviousURI);
5527 }
5528
5529 bool updateHistory = true;
5530
5531 // Determine if this type of load should update history
5532 switch (mLoadType) {
5533 case LOAD_NORMAL_REPLACE:
5534 case LOAD_REFRESH_REPLACE:
5535 case LOAD_STOP_CONTENT_AND_REPLACE:
5536 case LOAD_RELOAD_BYPASS_CACHE:
5537 case LOAD_RELOAD_BYPASS_PROXY:
5538 case LOAD_RELOAD_BYPASS_PROXY_AND_CACHE:
5539 case LOAD_REPLACE_BYPASS_CACHE:
5540 updateHistory = false;
5541 break;
5542 default:
5543 break;
5544 }
5545
5546 if (!updateHistory) {
5547 SetLayoutHistoryState(nullptr);
5548 }
5549
5550 return NS_OK;
5551}
5552
5553//*****************************************************************************
5554// nsDocShell::nsIWebProgressListener
5555//*****************************************************************************
5556
5557NS_IMETHODIMPnsresult
5558nsDocShell::OnProgressChange(nsIWebProgress* aProgress, nsIRequest* aRequest,
5559 int32_t aCurSelfProgress, int32_t aMaxSelfProgress,
5560 int32_t aCurTotalProgress,
5561 int32_t aMaxTotalProgress) {
5562 return NS_OK;
5563}
5564
5565NS_IMETHODIMPnsresult
5566nsDocShell::OnStateChange(nsIWebProgress* aProgress, nsIRequest* aRequest,
5567 uint32_t aStateFlags, nsresult aStatus) {
5568 if ((~aStateFlags & (STATE_START | STATE_IS_NETWORK)) == 0) {
5569 // Save timing statistics.
5570 nsCOMPtr<nsIChannel> channel(do_QueryInterface(aRequest));
5571 nsCOMPtr<nsIURI> uri;
5572 channel->GetURI(getter_AddRefs(uri));
5573 nsAutoCString aURI;
5574 uri->GetAsciiSpec(aURI);
5575
5576 if (this == aProgress) {
5577 mozilla::Unused << MaybeInitTiming();
5578 mTiming->NotifyFetchStart(uri,
5579 ConvertLoadTypeToNavigationType(mLoadType));
5580 // If we are starting a DocumentChannel, we need to pass the timing
5581 // statistics so that should a process switch occur, the starting type can
5582 // be passed to the new DocShell running in the other content process.
5583 if (RefPtr<DocumentChannel> docChannel = do_QueryObject(aRequest)) {
5584 docChannel->SetNavigationTiming(mTiming);
5585 }
5586 }
5587
5588 // Page has begun to load
5589 mBusyFlags = (BusyFlags)(BUSY_FLAGS_BUSY | BUSY_FLAGS_BEFORE_PAGE_LOAD);
5590
5591 if ((aStateFlags & STATE_RESTORING) == 0) {
5592 if (SessionStorePlatformCollection()) {
5593 if (IsForceReloadType(mLoadType)) {
5594 if (WindowContext* windowContext =
5595 mBrowsingContext->GetCurrentWindowContext()) {
5596 SessionStoreChild::From(windowContext->GetWindowGlobalChild())
5597 ->ResetSessionStore(mBrowsingContext,
5598 mBrowsingContext->GetSessionStoreEpoch());
5599 }
5600 }
5601 }
5602 }
5603 } else if ((~aStateFlags & (STATE_TRANSFERRING | STATE_IS_DOCUMENT)) == 0) {
5604 // Page is loading
5605 mBusyFlags = (BusyFlags)(BUSY_FLAGS_BUSY | BUSY_FLAGS_PAGE_LOADING);
5606 } else if ((aStateFlags & STATE_STOP) && (aStateFlags & STATE_IS_NETWORK)) {
5607 // Page has finished loading
5608 mBusyFlags = BUSY_FLAGS_NONE;
5609 }
5610
5611 if ((~aStateFlags & (STATE_IS_DOCUMENT | STATE_STOP)) == 0) {
5612 nsCOMPtr<nsIWebProgress> webProgress =
5613 do_QueryInterface(GetAsSupports(this));
5614 // Is the document stop notification for this document?
5615 if (aProgress == webProgress.get()) {
5616 nsCOMPtr<nsIChannel> channel(do_QueryInterface(aRequest));
5617 EndPageLoad(aProgress, channel, aStatus);
5618 }
5619 }
5620 // note that redirect state changes will go through here as well, but it
5621 // is better to handle those in OnRedirectStateChange where more
5622 // information is available.
5623 return NS_OK;
5624}
5625
5626NS_IMETHODIMPnsresult
5627nsDocShell::OnLocationChange(nsIWebProgress* aProgress, nsIRequest* aRequest,
5628 nsIURI* aURI, uint32_t aFlags) {
5629 // Since we've now changed Documents, notify the BrowsingContext that we've
5630 // changed. Ideally we'd just let the BrowsingContext do this when it
5631 // changes the current window global, but that happens before this and we
5632 // have a lot of tests that depend on the specific ordering of messages.
5633 bool isTopLevel = false;
5634 if (XRE_IsParentProcess() &&
5635 !(aFlags & nsIWebProgressListener::LOCATION_CHANGE_SAME_DOCUMENT) &&
5636 NS_SUCCEEDED(aProgress->GetIsTopLevel(&isTopLevel))((bool)(__builtin_expect(!!(!NS_FAILED_impl(aProgress->GetIsTopLevel
(&isTopLevel))), 1)))
&& isTopLevel) {
5637 GetBrowsingContext()->Canonical()->UpdateSecurityState();
5638 }
5639 return NS_OK;
5640}
5641
5642void nsDocShell::OnRedirectStateChange(nsIChannel* aOldChannel,
5643 nsIChannel* aNewChannel,
5644 uint32_t aRedirectFlags,
5645 uint32_t aStateFlags) {
5646 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"
, 5647); MOZ_PretendNoReturn(); } } while (0)
5647 "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"
, 5647); MOZ_PretendNoReturn(); } } while (0)
;
5648
5649 if (!(aStateFlags & STATE_IS_DOCUMENT)) {
5650 return; // not a toplevel document
5651 }
5652
5653 nsCOMPtr<nsIURI> oldURI, newURI;
5654 aOldChannel->GetURI(getter_AddRefs(oldURI));
5655 aNewChannel->GetURI(getter_AddRefs(newURI));
5656 if (!oldURI || !newURI) {
5657 return;
5658 }
5659
5660 // DocumentChannel adds redirect chain to global history in the parent
5661 // process. The redirect chain can't be queried from the content process, so
5662 // there's no need to update global history here.
5663 RefPtr<DocumentChannel> docChannel = do_QueryObject(aOldChannel);
5664 if (!docChannel) {
5665 // Below a URI visit is saved (see AddURIVisit method doc).
5666 // The visit chain looks something like:
5667 // ...
5668 // Site N - 1
5669 // => Site N
5670 // (redirect to =>) Site N + 1 (we are here!)
5671
5672 // Get N - 1 and transition type
5673 nsCOMPtr<nsIURI> previousURI;
5674 uint32_t previousFlags = 0;
5675 ExtractLastVisit(aOldChannel, getter_AddRefs(previousURI), &previousFlags);
5676
5677 if (aRedirectFlags & nsIChannelEventSink::REDIRECT_INTERNAL ||
5678 net::ChannelIsPost(aOldChannel)) {
5679 // 1. Internal redirects are ignored because they are specific to the
5680 // channel implementation.
5681 // 2. POSTs are not saved by global history.
5682 //
5683 // Regardless, we need to propagate the previous visit to the new
5684 // channel.
5685 SaveLastVisit(aNewChannel, previousURI, previousFlags);
5686 } else {
5687 // Get the HTTP response code, if available.
5688 uint32_t responseStatus = 0;
5689 nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(aOldChannel);
5690 if (httpChannel) {
5691 Unused << httpChannel->GetResponseStatus(&responseStatus);
5692 }
5693
5694 // Add visit N -1 => N
5695 AddURIVisit(oldURI, previousURI, previousFlags, responseStatus);
5696
5697 // Since N + 1 could be the final destination, we will not save N => N + 1
5698 // here. OnNewURI will do that, so we will cache it.
5699 SaveLastVisit(aNewChannel, oldURI, aRedirectFlags);
5700 }
5701 }
5702
5703 if (!(aRedirectFlags & nsIChannelEventSink::REDIRECT_INTERNAL) &&
5704 mLoadType & (LOAD_CMD_RELOAD | LOAD_CMD_HISTORY)) {
5705 mLoadType = LOAD_NORMAL_REPLACE;
5706 SetHistoryEntryAndUpdateBC(Some(nullptr), Nothing());
5707 }
5708}
5709
5710NS_IMETHODIMPnsresult
5711nsDocShell::OnStatusChange(nsIWebProgress* aWebProgress, nsIRequest* aRequest,
5712 nsresult aStatus, const char16_t* aMessage) {
5713 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"
, 5713); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "notification excluded in AddProgressListener(...)"
")"); do { *((volatile int*)__null) = 5713; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5714 return NS_OK;
5715}
5716
5717NS_IMETHODIMPnsresult
5718nsDocShell::OnSecurityChange(nsIWebProgress* aWebProgress, nsIRequest* aRequest,
5719 uint32_t aState) {
5720 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"
, 5720); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "notification excluded in AddProgressListener(...)"
")"); do { *((volatile int*)__null) = 5720; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5721 return NS_OK;
5722}
5723
5724NS_IMETHODIMPnsresult
5725nsDocShell::OnContentBlockingEvent(nsIWebProgress* aWebProgress,
5726 nsIRequest* aRequest, uint32_t aEvent) {
5727 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"
, 5727); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "notification excluded in AddProgressListener(...)"
")"); do { *((volatile int*)__null) = 5727; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5728 return NS_OK;
5729}
5730
5731already_AddRefed<nsIURIFixupInfo> nsDocShell::KeywordToURI(
5732 const nsACString& aKeyword, bool aIsPrivateContext) {
5733 nsCOMPtr<nsIURIFixupInfo> info;
5734 if (!XRE_IsContentProcess()) {
5735 nsCOMPtr<nsIURIFixup> uriFixup = components::URIFixup::Service();
5736 if (uriFixup) {
5737 uriFixup->KeywordToURI(aKeyword, aIsPrivateContext, getter_AddRefs(info));
5738 }
5739 }
5740 return info.forget();
5741}
5742
5743/* static */
5744already_AddRefed<nsIURI> nsDocShell::MaybeFixBadCertDomainErrorURI(
5745 nsIChannel* aChannel, nsIURI* aUrl) {
5746 if (!aChannel) {
5747 return nullptr;
5748 }
5749
5750 nsresult rv = NS_OK;
5751 nsAutoCString host;
5752 rv = aUrl->GetAsciiHost(host);
5753 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"
, 5753)
) {
5754 return nullptr;
5755 }
5756
5757 // Return if fixup enable pref is turned off.
5758 if (!mozilla::StaticPrefs::security_bad_cert_domain_error_url_fix_enabled()) {
5759 return nullptr;
5760 }
5761
5762 // Return if scheme is not HTTPS.
5763 if (!SchemeIsHTTPS(aUrl)) {
5764 return nullptr;
5765 }
5766
5767 nsCOMPtr<nsILoadInfo> info = aChannel->LoadInfo();
5768 if (!info) {
5769 return nullptr;
5770 }
5771
5772 // Skip doing the fixup if our channel was redirected, because we
5773 // shouldn't be guessing things about the post-redirect URI.
5774 if (!info->RedirectChain().IsEmpty()) {
5775 return nullptr;
5776 }
5777
5778 int32_t port = 0;
5779 rv = aUrl->GetPort(&port);
5780 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"
, 5780)
) {
5781 return nullptr;
5782 }
5783
5784 // Don't fix up hosts with ports.
5785 if (port != -1) {
5786 return nullptr;
5787 }
5788
5789 // Don't fix up localhost url.
5790 if (host == "localhost") {
5791 return nullptr;
5792 }
5793
5794 // Don't fix up hostnames with IP address.
5795 if (net_IsValidIPv4Addr(host) || net_IsValidIPv6Addr(host)) {
5796 return nullptr;
5797 }
5798
5799 nsAutoCString userPass;
5800 rv = aUrl->GetUserPass(userPass);
5801 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"
, 5801)
) {
5802 return nullptr;
5803 }
5804
5805 // Security - URLs with user / password info should NOT be modified.
5806 if (!userPass.IsEmpty()) {
5807 return nullptr;
5808 }
5809
5810 nsCOMPtr<nsITransportSecurityInfo> tsi;
5811 rv = aChannel->GetSecurityInfo(getter_AddRefs(tsi));
5812 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"
, 5812)
) {
5813 return nullptr;
5814 }
5815
5816 if (NS_WARN_IF(!tsi)NS_warn_if_impl(!tsi, "!tsi", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 5816)
) {
5817 return nullptr;
5818 }
5819
5820 nsCOMPtr<nsIX509Cert> cert;
5821 rv = tsi->GetServerCert(getter_AddRefs(cert));
5822 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"
, 5822)
) {
5823 return nullptr;
5824 }
5825
5826 nsTArray<uint8_t> certBytes;
5827 rv = cert->GetRawDER(certBytes);
5828 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
5829 return nullptr;
5830 }
5831
5832 mozilla::pkix::Input serverCertInput;
5833 mozilla::pkix::Result result =
5834 serverCertInput.Init(certBytes.Elements(), certBytes.Length());
5835 if (result != mozilla::pkix::Success) {
5836 return nullptr;
5837 }
5838
5839 constexpr auto wwwPrefix = "www."_ns;
5840 nsAutoCString newHost;
5841 if (StringBeginsWith(host, wwwPrefix)) {
5842 // Try www.example.com -> example.com
5843 newHost.Assign(Substring(host, wwwPrefix.Length()));
5844 } else {
5845 // Try example.com -> www.example.com
5846 newHost.Assign(wwwPrefix);
5847 newHost.Append(host);
5848 }
5849
5850 mozilla::pkix::Input newHostInput;
5851 result = newHostInput.Init(
5852 BitwiseCast<const uint8_t*, const char*>(newHost.BeginReading()),
5853 newHost.Length());
5854 if (result != mozilla::pkix::Success) {
5855 return nullptr;
5856 }
5857
5858 // Because certificate verification returned Result::ERROR_BAD_CERT_DOMAIN /
5859 // SSL_ERROR_BAD_CERT_DOMAIN, a chain was built and we know whether or not
5860 // the root was a built-in.
5861 bool rootIsBuiltIn;
5862 if (NS_FAILED(tsi->GetIsBuiltCertChainRootBuiltInRoot(&rootIsBuiltIn))((bool)(__builtin_expect(!!(NS_FAILED_impl(tsi->GetIsBuiltCertChainRootBuiltInRoot
(&rootIsBuiltIn))), 0)))
) {
5863 return nullptr;
5864 }
5865 mozilla::psm::SkipInvalidSANsForNonBuiltInRootsPolicy nameMatchingPolicy(
5866 rootIsBuiltIn);
5867
5868 // Check if the certificate is valid for the new hostname.
5869 result = mozilla::pkix::CheckCertHostname(serverCertInput, newHostInput,
5870 nameMatchingPolicy);
5871 if (result != mozilla::pkix::Success) {
5872 return nullptr;
5873 }
5874
5875 nsCOMPtr<nsIURI> newURI;
5876 Unused << NS_MutateURI(aUrl).SetHost(newHost).Finalize(
5877 getter_AddRefs(newURI));
5878
5879 return newURI.forget();
5880}
5881
5882/* static */
5883already_AddRefed<nsIURI> nsDocShell::AttemptURIFixup(
5884 nsIChannel* aChannel, nsresult aStatus,
5885 const mozilla::Maybe<nsCString>& aOriginalURIString, uint32_t aLoadType,
5886 bool aIsTopFrame, bool aAllowKeywordFixup, bool aUsePrivateBrowsing,
5887 bool aNotifyKeywordSearchLoading, nsIInputStream** aNewPostData,
5888 nsILoadInfo::SchemelessInputType* outSchemelessInput) {
5889 if (aStatus != NS_ERROR_UNKNOWN_HOST && aStatus != NS_ERROR_NET_RESET &&
5890 aStatus != NS_ERROR_CONNECTION_REFUSED &&
5891 aStatus !=
5892 mozilla::psm::GetXPCOMFromNSSError(SSL_ERROR_BAD_CERT_DOMAIN)) {
5893 return nullptr;
5894 }
5895
5896 if (!(aLoadType == LOAD_NORMAL && aIsTopFrame) && !aAllowKeywordFixup) {
5897 return nullptr;
5898 }
5899
5900 nsCOMPtr<nsIURI> url;
5901 nsresult rv = aChannel->GetURI(getter_AddRefs(url));
5902 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
5903 return nullptr;
5904 }
5905
5906 //
5907 // Try and make an alternative URI from the old one
5908 //
5909 nsCOMPtr<nsIURI> newURI;
5910 nsCOMPtr<nsIInputStream> newPostData;
5911
5912 nsAutoCString oldSpec;
5913 url->GetSpec(oldSpec);
5914
5915 //
5916 // First try keyword fixup
5917 //
5918 nsAutoString keywordProviderName, keywordAsSent;
5919 if (aStatus == NS_ERROR_UNKNOWN_HOST && aAllowKeywordFixup) {
5920 // we should only perform a keyword search under the following
5921 // conditions:
5922 // (0) Pref keyword.enabled is true
5923 // (1) the url scheme is http (or https)
5924 // (2) the url does not have a protocol scheme
5925 // If we don't enforce such a policy, then we end up doing
5926 // keyword searchs on urls we don't intend like imap, file,
5927 // mailbox, etc. This could lead to a security problem where we
5928 // send data to the keyword server that we shouldn't be.
5929 // Someone needs to clean up keywords in general so we can
5930 // determine on a per url basis if we want keywords
5931 // enabled...this is just a bandaid...
5932 nsAutoCString scheme;
5933 Unused << url->GetScheme(scheme);
5934 if (Preferences::GetBool("keyword.enabled", false) &&
5935 StringBeginsWith(scheme, "http"_ns)) {
5936 bool attemptFixup = false;
5937 nsAutoCString host;
5938 Unused << url->GetHost(host);
5939 if (host.FindChar('.') == kNotFound) {
5940 attemptFixup = true;
5941 } else {
5942 // For domains with dots, we check the public suffix validity.
5943 nsCOMPtr<nsIEffectiveTLDService> tldService =
5944 do_GetService(NS_EFFECTIVETLDSERVICE_CONTRACTID"@mozilla.org/network/effective-tld-service;1");
5945 if (tldService) {
5946 nsAutoCString suffix;
5947 attemptFixup =
5948 NS_SUCCEEDED(tldService->GetKnownPublicSuffix(url, suffix))((bool)(__builtin_expect(!!(!NS_FAILED_impl(tldService->GetKnownPublicSuffix
(url, suffix))), 1)))
&&
5949 suffix.IsEmpty();
5950 }
5951 }
5952 if (attemptFixup) {
5953 nsCOMPtr<nsIURIFixupInfo> info;
5954 // only send non-qualified hosts to the keyword server
5955 if (aOriginalURIString && !aOriginalURIString->IsEmpty()) {
5956 info = KeywordToURI(*aOriginalURIString, aUsePrivateBrowsing);
5957 } else {
5958 //
5959 // If this string was passed through nsStandardURL by
5960 // chance, then it may have been converted from UTF-8 to
5961 // Punycode, which would result in a completely bogus keyword
5962 // query. Here we try to recover the original Unicode
5963 // value, but this is not 100% correct since the value may
5964 // have been normalized per the IDN normalization rules.
5965 //
5966 // Since we don't have access to the exact original string
5967 // that was entered by the user, this will just have to do.
5968 nsAutoCString utf8Host;
5969 mozilla_net_recover_keyword_from_punycode(&host, &utf8Host);
5970 info = KeywordToURI(utf8Host, aUsePrivateBrowsing);
5971 }
5972 if (info) {
5973 info->GetPreferredURI(getter_AddRefs(newURI));
5974 info->GetSchemelessInput(outSchemelessInput);
5975 if (newURI) {
5976 info->GetKeywordAsSent(keywordAsSent);
5977 info->GetKeywordProviderName(keywordProviderName);
5978 info->GetPostData(getter_AddRefs(newPostData));
5979 }
5980 }
5981 }
5982 }
5983 }
5984
5985 //
5986 // Now try change the address, e.g. turn http://foo into
5987 // http://www.foo.com, and if that doesn't work try https with
5988 // https://foo and https://www.foo.com.
5989 //
5990 if (aStatus == NS_ERROR_UNKNOWN_HOST || aStatus == NS_ERROR_NET_RESET) {
5991 // Skip fixup for anything except a normal document load
5992 // operation on the topframe.
5993 bool doCreateAlternate = aLoadType == LOAD_NORMAL && aIsTopFrame;
5994
5995 if (doCreateAlternate) {
5996 nsCOMPtr<nsILoadInfo> loadInfo = aChannel->LoadInfo();
5997 nsIPrincipal* principal = loadInfo->TriggeringPrincipal();
5998 // Only do this if our channel was loaded directly by the user from the
5999 // URL bar or similar (system principal) and not redirected, because we
6000 // shouldn't be guessing things about links from other sites, or a
6001 // post-redirect URI.
6002 doCreateAlternate = principal && principal->IsSystemPrincipal() &&
6003 loadInfo->RedirectChain().IsEmpty();
6004 }
6005 // Test if keyword lookup produced a new URI or not
6006 if (doCreateAlternate && newURI) {
6007 bool sameURI = false;
6008 url->Equals(newURI, &sameURI);
6009 if (!sameURI) {
6010 // Keyword lookup made a new URI so no need to try
6011 // an alternate one.
6012 doCreateAlternate = false;
6013 }
6014 }
6015 if (doCreateAlternate) {
6016 newURI = nullptr;
6017 newPostData = nullptr;
6018 keywordProviderName.Truncate();
6019 keywordAsSent.Truncate();
6020 nsCOMPtr<nsIURIFixup> uriFixup = components::URIFixup::Service();
6021 if (uriFixup) {
6022 nsCOMPtr<nsIURIFixupInfo> fixupInfo;
6023 uriFixup->GetFixupURIInfo(oldSpec, nsIURIFixup::FIXUP_FLAG_NONE,
6024 getter_AddRefs(fixupInfo));
6025 if (fixupInfo) {
6026 fixupInfo->GetPreferredURI(getter_AddRefs(newURI));
6027 }
6028 }
6029 }
6030 } else if (aStatus == NS_ERROR_CONNECTION_REFUSED &&
6031 Preferences::GetBool("browser.fixup.fallback-to-https", false)) {
6032 // Try HTTPS, since http didn't work
6033 if (SchemeIsHTTP(url)) {
6034 int32_t port = 0;
6035 url->GetPort(&port);
6036
6037 // Fall back to HTTPS only if port is default
6038 if (port == -1) {
6039 newURI = nullptr;
6040 newPostData = nullptr;
6041 Unused << NS_MutateURI(url)
6042 .SetScheme("https"_ns)
6043 .Finalize(getter_AddRefs(newURI));
6044 }
6045 }
6046 }
6047
6048 // If we have a SSL_ERROR_BAD_CERT_DOMAIN error, try adding or removing
6049 // "www." to/from the beginning of the domain name to see if we can avoid
6050 // showing the cert error page. For example, https://example.com ->
6051 // https://www.example.com or https://www.example.com -> https://example.com.
6052 if (aStatus ==
6053 mozilla::psm::GetXPCOMFromNSSError(SSL_ERROR_BAD_CERT_DOMAIN)) {
6054 newPostData = nullptr;
6055 newURI = MaybeFixBadCertDomainErrorURI(aChannel, url);
6056 }
6057
6058 // Did we make a new URI that is different to the old one? If so
6059 // load it.
6060 //
6061 if (newURI) {
6062 // Make sure the new URI is different from the old one,
6063 // otherwise there's little point trying to load it again.
6064 bool sameURI = false;
6065 url->Equals(newURI, &sameURI);
6066 if (!sameURI) {
6067 if (aNewPostData) {
6068 newPostData.forget(aNewPostData);
6069 }
6070 if (aNotifyKeywordSearchLoading) {
6071 // This notification is meant for Firefox Health Report so it
6072 // can increment counts from the search engine
6073 MaybeNotifyKeywordSearchLoading(keywordProviderName, keywordAsSent);
6074 }
6075 return newURI.forget();
6076 }
6077 }
6078
6079 return nullptr;
6080}
6081
6082nsresult nsDocShell::FilterStatusForErrorPage(
6083 nsresult aStatus, nsIChannel* aChannel, uint32_t aLoadType,
6084 bool aIsTopFrame, bool aUseErrorPages,
6085 bool* aSkippedUnknownProtocolNavigation) {
6086 // Errors to be shown only on top-level frames
6087 if ((aStatus == NS_ERROR_UNKNOWN_HOST ||
6088 aStatus == NS_ERROR_CONNECTION_REFUSED ||
6089 aStatus == NS_ERROR_UNKNOWN_PROXY_HOST ||
6090 aStatus == NS_ERROR_PROXY_CONNECTION_REFUSED ||
6091 aStatus == NS_ERROR_PROXY_FORBIDDEN ||
6092 aStatus == NS_ERROR_PROXY_NOT_IMPLEMENTED ||
6093 aStatus == NS_ERROR_PROXY_AUTHENTICATION_FAILED ||
6094 aStatus == NS_ERROR_PROXY_TOO_MANY_REQUESTS ||
6095 aStatus == NS_ERROR_MALFORMED_URI ||
6096 aStatus == NS_ERROR_BLOCKED_BY_POLICY ||
6097 aStatus == NS_ERROR_DOM_COOP_FAILED ||
6098 aStatus == NS_ERROR_DOM_COEP_FAILED) &&
6099 (aIsTopFrame || aUseErrorPages)) {
6100 return aStatus;
6101 }
6102
6103 if (aStatus == NS_ERROR_NET_TIMEOUT ||
6104 aStatus == NS_ERROR_NET_TIMEOUT_EXTERNAL ||
6105 aStatus == NS_ERROR_NET_ERROR_RESPONSE ||
6106 aStatus == NS_ERROR_PROXY_GATEWAY_TIMEOUT ||
6107 aStatus == NS_ERROR_REDIRECT_LOOP ||
6108 aStatus == NS_ERROR_UNKNOWN_SOCKET_TYPE ||
6109 aStatus == NS_ERROR_NET_INTERRUPT || aStatus == NS_ERROR_NET_RESET ||
6110 aStatus == NS_ERROR_PROXY_BAD_GATEWAY || aStatus == NS_ERROR_OFFLINE ||
6111 aStatus == NS_ERROR_MALWARE_URI || aStatus == NS_ERROR_PHISHING_URI ||
6112 aStatus == NS_ERROR_UNWANTED_URI || aStatus == NS_ERROR_HARMFUL_URI ||
6113 aStatus == NS_ERROR_UNSAFE_CONTENT_TYPE ||
6114 aStatus == NS_ERROR_INTERCEPTION_FAILED ||
6115 aStatus == NS_ERROR_NET_INADEQUATE_SECURITY ||
6116 aStatus == NS_ERROR_NET_HTTP2_SENT_GOAWAY ||
6117 aStatus == NS_ERROR_NET_HTTP3_PROTOCOL_ERROR ||
6118 aStatus == NS_ERROR_DOM_BAD_URI || aStatus == NS_ERROR_FILE_NOT_FOUND ||
6119 aStatus == NS_ERROR_FILE_ACCESS_DENIED ||
6120 aStatus == NS_ERROR_CORRUPTED_CONTENT ||
6121 aStatus == NS_ERROR_INVALID_CONTENT_ENCODING ||
6122 NS_ERROR_GET_MODULE(aStatus) == NS_ERROR_MODULE_SECURITY21) {
6123 // Errors to be shown for any frame
6124 return aStatus;
6125 }
6126
6127 if (aStatus == NS_ERROR_UNKNOWN_PROTOCOL) {
6128 // For unknown protocols we only display an error if the load is triggered
6129 // by the browser itself. Showing the error for page-triggered navigations
6130 // causes annoying behavior for users when a page tries to open an external
6131 // app which has not been installed, see bug 1528305. A missing WebExtension
6132 // protocol handlers will however always load the error page, as it is not
6133 // expected to be opened externally, see bug 1921426.
6134 nsCOMPtr<nsILoadInfo> info = aChannel->LoadInfo();
6135 if (!info->TriggeringPrincipal()->IsSystemPrincipal() &&
6136 !BasePrincipal::Cast(info->TriggeringPrincipal())->AddonPolicy()) {
6137 if (aSkippedUnknownProtocolNavigation) {
6138 *aSkippedUnknownProtocolNavigation = true;
6139 }
6140 return NS_OK;
6141 }
6142 return aStatus;
6143 }
6144
6145 if (aStatus == NS_ERROR_DOCUMENT_NOT_CACHED) {
6146 // Non-caching channels will simply return NS_ERROR_OFFLINE.
6147 // Caching channels would have to look at their flags to work
6148 // out which error to return. Or we can fix up the error here.
6149 if (!(aLoadType & LOAD_CMD_HISTORY)) {
6150 return NS_ERROR_OFFLINE;
6151 }
6152 return aStatus;
6153 }
6154
6155 return NS_OK;
6156}
6157
6158nsresult nsDocShell::EndPageLoad(nsIWebProgress* aProgress,
6159 nsIChannel* aChannel, nsresult aStatus) {
6160 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)
6161 ("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)
6162 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)
;
6163 if (!aChannel) {
6164 return NS_ERROR_NULL_POINTER;
6165 }
6166
6167 // Make sure to discard the initial client if we never created the initial
6168 // about:blank document. Do this before possibly returning from the method
6169 // due to an error.
6170 mInitialClientSource.reset();
6171
6172 nsCOMPtr<nsIConsoleReportCollector> reporter = do_QueryInterface(aChannel);
6173 if (reporter) {
6174 nsCOMPtr<nsILoadGroup> loadGroup;
6175 aChannel->GetLoadGroup(getter_AddRefs(loadGroup));
6176 if (loadGroup) {
6177 reporter->FlushConsoleReports(loadGroup);
6178 } else {
6179 reporter->FlushConsoleReports(GetDocument());
6180 }
6181 }
6182
6183 nsCOMPtr<nsIURI> url;
6184 nsresult rv = aChannel->GetURI(getter_AddRefs(url));
6185 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
6186 return rv;
6187 }
6188
6189 nsCOMPtr<nsITimedChannel> timingChannel = do_QueryInterface(aChannel);
6190 if (timingChannel) {
6191 TimeStamp channelCreationTime;
6192 rv = timingChannel->GetChannelCreation(&channelCreationTime);
6193 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && !channelCreationTime.IsNull()) {
6194 glean::performance_page::total_content_page_load.AccumulateRawDuration(
6195 TimeStamp::Now() - channelCreationTime);
6196 }
6197 }
6198
6199 // Timing is picked up by the window, we don't need it anymore
6200 mTiming = nullptr;
6201
6202 // clean up reload state for meta charset
6203 if (eCharsetReloadRequested == mCharsetReloadState) {
6204 mCharsetReloadState = eCharsetReloadStopOrigional;
6205 } else {
6206 mCharsetReloadState = eCharsetReloadInit;
6207 }
6208
6209 // Save a pointer to the currently-loading history entry.
6210 // nsDocShell::EndPageLoad will clear mLSHE, but we may need this history
6211 // entry further down in this method.
6212 nsCOMPtr<nsISHEntry> loadingSHE = mLSHE;
6213 mozilla::Unused << loadingSHE; // XXX: Not sure if we need this anymore
6214
6215 //
6216 // one of many safeguards that prevent death and destruction if
6217 // someone is so very very rude as to bring this window down
6218 // during this load handler.
6219 //
6220 nsCOMPtr<nsIDocShell> kungFuDeathGrip(this);
6221
6222 // Notify the DocumentViewer that the Document has finished loading. This
6223 // will cause any OnLoad(...) and PopState(...) handlers to fire.
6224 if (!mEODForCurrentDocument && mDocumentViewer) {
6225 mIsExecutingOnLoadHandler = true;
6226 nsCOMPtr<nsIDocumentViewer> viewer = mDocumentViewer;
6227 viewer->LoadComplete(aStatus);
6228 mIsExecutingOnLoadHandler = false;
6229
6230 mEODForCurrentDocument = true;
6231 }
6232 /* Check if the httpChannel has any cache-control related response headers,
6233 * like no-store, no-cache. If so, update SHEntry so that
6234 * when a user goes back/forward to this page, we appropriately do
6235 * form value restoration or load from server.
6236 */
6237 nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(aChannel));
6238 if (!httpChannel) {
6239 // HttpChannel could be hiding underneath a Multipart channel.
6240 GetHttpChannel(aChannel, getter_AddRefs(httpChannel));
6241 }
6242
6243 if (httpChannel) {
6244 // figure out if SH should be saving layout state.
6245 bool discardLayoutState = ShouldDiscardLayoutState(httpChannel);
6246 if (mLSHE && discardLayoutState && (mLoadType & LOAD_CMD_NORMAL) &&
6247 (mLoadType != LOAD_BYPASS_HISTORY) && (mLoadType != LOAD_ERROR_PAGE)) {
6248 mLSHE->SetSaveLayoutStateFlag(false);
6249 }
6250 }
6251
6252 // Clear mLSHE after calling the onLoadHandlers. This way, if the
6253 // onLoadHandler tries to load something different in
6254 // itself or one of its children, we can deal with it appropriately.
6255 if (mLSHE) {
6256 mLSHE->SetLoadType(LOAD_HISTORY);
6257
6258 // Clear the mLSHE reference to indicate document loading is done one
6259 // way or another.
6260 SetHistoryEntryAndUpdateBC(Some(nullptr), Nothing());
6261 }
6262 mActiveEntryIsLoadingFromSessionHistory = false;
6263
6264 // if there's a refresh header in the channel, this method
6265 // will set it up for us.
6266 if (mBrowsingContext->IsActive() || !mDisableMetaRefreshWhenInactive)
6267 RefreshURIFromQueue();
6268
6269 // Test whether this is the top frame or a subframe
6270 bool isTopFrame = mBrowsingContext->IsTop();
6271
6272 bool hadErrorStatus = false;
6273 // If status code indicates an error it means that DocumentChannel already
6274 // tried to fixup the uri and failed. Throw an error dialog box here.
6275 if (NS_FAILED(aStatus)((bool)(__builtin_expect(!!(NS_FAILED_impl(aStatus)), 0)))) {
6276 // If we got CONTENT_BLOCKED from EndPageLoad, then we need to fire
6277 // the error event to our embedder, since tests are relying on this.
6278 // The error event is usually fired by the caller of InternalLoad, but
6279 // this particular error can happen asynchronously.
6280 // Bug 1629201 is filed for having much clearer decision making around
6281 // which cases need error events.
6282 bool fireFrameErrorEvent = (aStatus == NS_ERROR_CONTENT_BLOCKED_SHOW_ALT ||
6283 aStatus == NS_ERROR_CONTENT_BLOCKED);
6284 UnblockEmbedderLoadEventForFailure(fireFrameErrorEvent);
6285
6286 bool skippedUnknownProtocolNavigation = false;
6287 aStatus = FilterStatusForErrorPage(aStatus, aChannel, mLoadType, isTopFrame,
6288 mBrowsingContext->GetUseErrorPages(),
6289 &skippedUnknownProtocolNavigation);
6290 hadErrorStatus = true;
6291 if (NS_FAILED(aStatus)((bool)(__builtin_expect(!!(NS_FAILED_impl(aStatus)), 0)))) {
6292 if (!mIsBeingDestroyed) {
6293 DisplayLoadError(aStatus, url, nullptr, aChannel);
6294 }
6295 } else if (skippedUnknownProtocolNavigation) {
6296 nsAutoCString sanitized;
6297 nsTArray<nsString> params;
6298 if (NS_SUCCEEDED(NS_GetSanitizedURIStringFromURI(url, sanitized))((bool)(__builtin_expect(!!(!NS_FAILED_impl(NS_GetSanitizedURIStringFromURI
(url, sanitized))), 1)))
) {
6299 params.AppendElement(NS_ConvertUTF8toUTF16(sanitized));
6300 } else {
6301 params.AppendElement(u"(unknown uri)"_ns);
6302 }
6303 nsContentUtils::ReportToConsole(
6304 nsIScriptError::warningFlag, "DOM"_ns, GetExtantDocument(),
6305 nsContentUtils::eDOM_PROPERTIES, "UnknownProtocolNavigationPrevented",
6306 params);
6307 }
6308 } else {
6309 // If we have a host
6310 nsCOMPtr<nsILoadInfo> loadInfo = aChannel->LoadInfo();
6311 PredictorLearnRedirect(url, aChannel, loadInfo->GetOriginAttributes());
6312 }
6313
6314 if (hadErrorStatus) {
6315 // Don't send session store updates if the reason EndPageLoad was called is
6316 // because we are process switching. Sometimes the update takes too long and
6317 // incorrectly overrides session store data from the following load.
6318 return NS_OK;
6319 }
6320 if (SessionStorePlatformCollection()) {
6321 if (WindowContext* windowContext =
6322 mBrowsingContext->GetCurrentWindowContext()) {
6323 using Change = SessionStoreChangeListener::Change;
6324
6325 // We've finished loading the page and now we want to collect all the
6326 // session store state that the page is initialized with.
6327 SessionStoreChangeListener::CollectSessionStoreData(
6328 windowContext,
6329 EnumSet<Change>(Change::Input, Change::Scroll, Change::SessionHistory,
6330 Change::WireFrame));
6331 }
6332 }
6333
6334 return NS_OK;
6335}
6336
6337//*****************************************************************************
6338// nsDocShell: Content Viewer Management
6339//*****************************************************************************
6340
6341nsresult nsDocShell::EnsureDocumentViewer() {
6342 if (mDocumentViewer) {
6343 return NS_OK;
6344 }
6345 if (mIsBeingDestroyed) {
6346 return NS_ERROR_FAILURE;
6347 }
6348
6349 nsCOMPtr<nsIContentSecurityPolicy> cspToInheritForAboutBlank;
6350 nsCOMPtr<nsIURI> baseURI;
6351 nsIPrincipal* principal = GetInheritedPrincipal(false);
6352 nsIPrincipal* partitionedPrincipal = GetInheritedPrincipal(false, true);
6353
6354 nsCOMPtr<nsIDocShellTreeItem> parentItem;
6355 GetInProcessSameTypeParent(getter_AddRefs(parentItem));
6356 if (parentItem) {
6357 if (nsCOMPtr<nsPIDOMWindowOuter> domWin = GetWindow()) {
6358 nsCOMPtr<Element> parentElement = domWin->GetFrameElementInternal();
6359 if (parentElement) {
6360 baseURI = parentElement->GetBaseURI();
6361 cspToInheritForAboutBlank = parentElement->GetCsp();
6362 }
6363 }
6364 }
6365
6366 nsresult rv = CreateAboutBlankDocumentViewer(
6367 principal, partitionedPrincipal, cspToInheritForAboutBlank, baseURI,
6368 /* aIsInitialDocument */ true);
6369
6370 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"
, 6370); return NS_ERROR_UNEXPECTED; } } while (false)
;
6371
6372 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
6373 RefPtr<Document> doc(GetDocument());
6374 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"
, 6376); AnnotateMozCrashReason("MOZ_ASSERT" "(" "doc" ") (" "Should have doc if CreateAboutBlankDocumentViewer "
"succeeded!" ")"); do { *((volatile int*)__null) = 6376; __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
6375 "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"
, 6376); AnnotateMozCrashReason("MOZ_ASSERT" "(" "doc" ") (" "Should have doc if CreateAboutBlankDocumentViewer "
"succeeded!" ")"); do { *((volatile int*)__null) = 6376; __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
6376 "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"
, 6376); AnnotateMozCrashReason("MOZ_ASSERT" "(" "doc" ") (" "Should have doc if CreateAboutBlankDocumentViewer "
"succeeded!" ")"); do { *((volatile int*)__null) = 6376; __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
;
6377 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"
, 6377); AnnotateMozCrashReason("MOZ_ASSERT" "(" "doc->IsInitialDocument()"
") (" "Document should be initial document" ")"); do { *((volatile
int*)__null) = 6377; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
6378
6379 // Documents created using EnsureDocumentViewer may be transient
6380 // placeholders created by framescripts before content has a
6381 // chance to load. In some cases, window.open(..., "noopener")
6382 // will create such a document and then synchronously tear it
6383 // down, firing a "pagehide" event. Doing so violates our
6384 // assertions about DocGroups. It's easier to silence the
6385 // assertion here than to avoid creating the extra document.
6386 doc->IgnoreDocGroupMismatches();
6387 }
6388
6389 return rv;
6390}
6391
6392nsresult nsDocShell::CreateAboutBlankDocumentViewer(
6393 nsIPrincipal* aPrincipal, nsIPrincipal* aPartitionedPrincipal,
6394 nsIContentSecurityPolicy* aCSP, nsIURI* aBaseURI, bool aIsInitialDocument,
6395 const Maybe<nsILoadInfo::CrossOriginEmbedderPolicy>& aCOEP,
6396 bool aTryToSaveOldPresentation, bool aCheckPermitUnload,
6397 WindowGlobalChild* aActor) {
6398 RefPtr<Document> blankDoc;
6399 nsCOMPtr<nsIDocumentViewer> viewer;
6400 nsresult rv = NS_ERROR_FAILURE;
6401
6402 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
)
6403 MarkerStack::Capture())do { ; do { if (profiler_is_collecting_markers()) { ::profiler_add_marker_impl
("CreateAboutBlankDocumentViewer", ::geckoprofiler::category::
DOM, MarkerStack::Capture()); } } while (false); } while (false
)
;
6404
6405 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"
, 6405); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aActor->DocumentPrincipal() == aPrincipal"
")"); do { *((volatile int*)__null) = 6405; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
6406
6407 /* mCreatingDocument should never be true at this point. However, it's
6408 a theoretical possibility. We want to know about it and make it stop,
6409 and this sounds like a job for an assertion. */
6410 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"
, 6411); MOZ_PretendNoReturn(); } } while (0)
6411 "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"
, 6411); MOZ_PretendNoReturn(); } } while (0)
;
6412 if (mCreatingDocument) {
6413 return NS_ERROR_FAILURE;
6414 }
6415
6416 if (!mBrowsingContext->AncestorsAreCurrent() ||
6417 (mozilla::SessionHistoryInParent() && mBrowsingContext->IsInBFCache())) {
6418 mBrowsingContext->RemoveRootFromBFCacheSync();
6419 return NS_ERROR_NOT_AVAILABLE;
6420 }
6421
6422 // mDocumentViewer->PermitUnload may release |this| docshell.
6423 nsCOMPtr<nsIDocShell> kungFuDeathGrip(this);
6424
6425 AutoRestore<bool> creatingDocument(mCreatingDocument);
6426 mCreatingDocument = true;
6427
6428 if (aPrincipal && !aPrincipal->IsSystemPrincipal() &&
6429 mItemType != typeChrome) {
6430 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"
, 6431); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPrincipal->OriginAttributesRef() == mBrowsingContext->OriginAttributesRef()"
")"); do { *((volatile int*)__null) = 6431; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6431 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"
, 6431); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPrincipal->OriginAttributesRef() == mBrowsingContext->OriginAttributesRef()"
")"); do { *((volatile int*)__null) = 6431; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6432 }
6433
6434 // Make sure timing is created. But first record whether we had it
6435 // already, so we don't clobber the timing for an in-progress load.
6436 bool hadTiming = mTiming;
6437 bool toBeReset = MaybeInitTiming();
6438 if (mDocumentViewer) {
6439 if (aCheckPermitUnload) {
6440 // We've got a content viewer already. Make sure the user
6441 // permits us to discard the current document and replace it
6442 // with about:blank. And also ensure we fire the unload events
6443 // in the current document.
6444
6445 // Unload gets fired first for
6446 // document loaded from the session history.
6447 mTiming->NotifyBeforeUnload();
6448
6449 bool okToUnload;
6450 rv = mDocumentViewer->PermitUnload(&okToUnload);
6451
6452 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && !okToUnload) {
6453 // The user chose not to unload the page, interrupt the load.
6454 MaybeResetInitTiming(toBeReset);
6455 return NS_ERROR_FAILURE;
6456 }
6457 if (mTiming) {
6458 mTiming->NotifyUnloadAccepted(mCurrentURI);
6459 }
6460 }
6461
6462 mSavingOldViewer =
6463 aTryToSaveOldPresentation &&
6464 CanSavePresentation(LOAD_NORMAL, nullptr, nullptr,
6465 /* aReportBFCacheComboTelemetry */ true);
6466
6467 // Make sure to blow away our mLoadingURI just in case. No loads
6468 // from inside this pagehide.
6469 mLoadingURI = nullptr;
6470
6471 // Stop any in-progress loading, so that we don't accidentally trigger any
6472 // PageShow notifications from Embed() interrupting our loading below.
6473 Stop();
6474
6475 // Notify the current document that it is about to be unloaded!!
6476 //
6477 // It is important to fire the unload() notification *before* any state
6478 // is changed within the DocShell - otherwise, javascript will get the
6479 // wrong information :-(
6480 //
6481 (void)FirePageHideNotification(!mSavingOldViewer);
6482 // pagehide notification might destroy this docshell.
6483 if (mIsBeingDestroyed) {
6484 return NS_ERROR_DOCSHELL_DYING;
6485 }
6486 }
6487
6488 // Now make sure we don't think we're in the middle of firing unload after
6489 // this point. This will make us fire unload when the about:blank document
6490 // unloads... but that's ok, more or less. Would be nice if it fired load
6491 // too, of course.
6492 mFiredUnloadEvent = false;
6493
6494 nsCOMPtr<nsIDocumentLoaderFactory> docFactory =
6495 nsContentUtils::FindInternalDocumentViewer("text/html"_ns);
6496
6497 if (docFactory) {
6498 nsCOMPtr<nsIPrincipal> principal, partitionedPrincipal;
6499 const uint32_t sandboxFlags =
6500 mBrowsingContext->GetHasLoadedNonInitialDocument()
6501 ? mBrowsingContext->GetSandboxFlags()
6502 : mBrowsingContext->GetInitialSandboxFlags();
6503 // If we're sandboxed, then create a new null principal. We skip
6504 // this if we're being created from WindowGlobalChild, since in
6505 // that case we already have a null principal if required.
6506 // We can't compare againt the BrowsingContext sandbox flag, since
6507 // the value was taken when the load initiated and may have since
6508 // changed.
6509 if ((sandboxFlags & SANDBOXED_ORIGIN) && !aActor) {
6510 if (aPrincipal) {
6511 principal = NullPrincipal::CreateWithInheritedAttributes(aPrincipal);
6512 } else {
6513 principal = NullPrincipal::Create(GetOriginAttributes());
6514 }
6515 partitionedPrincipal = principal;
6516 } else {
6517 principal = aPrincipal;
6518 partitionedPrincipal = aPartitionedPrincipal;
6519 }
6520
6521 // We cannot get the foreign partitioned prinicpal for the initial
6522 // about:blank page. So, we change to check if we need to use the
6523 // partitioned principal for the service worker here.
6524 MaybeCreateInitialClientSource(
6525 StoragePrincipalHelper::ShouldUsePartitionPrincipalForServiceWorker(
6526 this)
6527 ? partitionedPrincipal
6528 : principal);
6529
6530 // generate (about:blank) document to load
6531 blankDoc = nsContentDLF::CreateBlankDocument(mLoadGroup, principal,
6532 partitionedPrincipal, this);
6533 if (blankDoc) {
6534 // Hack: manually set the CSP for the new document
6535 // Please create an actual copy of the CSP (do not share the same
6536 // reference) otherwise appending a new policy within the new
6537 // document will be incorrectly propagated to the opening doc.
6538 if (aCSP) {
6539 RefPtr<nsCSPContext> cspToInherit = new nsCSPContext();
6540 cspToInherit->InitFromOther(static_cast<nsCSPContext*>(aCSP));
6541 blankDoc->SetCsp(cspToInherit);
6542 }
6543
6544 blankDoc->SetIsInitialDocument(aIsInitialDocument);
6545
6546 blankDoc->SetEmbedderPolicy(aCOEP);
6547
6548 // Hack: set the base URI manually, since this document never
6549 // got Reset() with a channel.
6550 blankDoc->SetBaseURI(aBaseURI);
6551
6552 // Copy our sandbox flags to the document. These are immutable
6553 // after being set here.
6554 blankDoc->SetSandboxFlags(sandboxFlags);
6555
6556 // create a content viewer for us and the new document
6557 docFactory->CreateInstanceForDocument(
6558 NS_ISUPPORTS_CAST(nsIDocShell*, this)static_cast<nsISupports*>(static_cast<nsIDocShell*>
(this))
, blankDoc, "view",
6559 getter_AddRefs(viewer));
6560
6561 // hook 'em up
6562 if (viewer) {
6563 viewer->SetContainer(this);
6564 rv = Embed(viewer, aActor, true, false, nullptr, mCurrentURI);
6565 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"
, 6565); return rv; } } while (false)
;
6566
6567 SetCurrentURI(blankDoc->GetDocumentURI(), nullptr,
6568 /* aFireLocationChange */ true,
6569 /* aIsInitialAboutBlank */ true,
6570 /* aLocationFlags */ 0);
6571 rv = mIsBeingDestroyed ? NS_ERROR_NOT_AVAILABLE : NS_OK;
6572 }
6573
6574 if (Element* embedderElement = blankDoc->GetEmbedderElement()) {
6575 blankDoc->InitFeaturePolicy(AsVariant(embedderElement));
6576 } else {
6577 blankDoc->InitFeaturePolicy(AsVariant(Nothing{}));
6578 }
6579 }
6580 }
6581
6582 // The transient about:blank viewer doesn't have a session history entry.
6583 SetHistoryEntryAndUpdateBC(Nothing(), Some(nullptr));
6584
6585 // Clear out our mTiming like we would in EndPageLoad, if we didn't
6586 // have one before entering this function.
6587 if (!hadTiming) {
6588 mTiming = nullptr;
6589 mBlankTiming = true;
6590 }
6591
6592 return rv;
6593}
6594
6595NS_IMETHODIMPnsresult
6596nsDocShell::CreateAboutBlankDocumentViewer(nsIPrincipal* aPrincipal,
6597 nsIPrincipal* aPartitionedPrincipal,
6598 nsIContentSecurityPolicy* aCSP) {
6599 return CreateAboutBlankDocumentViewer(aPrincipal, aPartitionedPrincipal, aCSP,
6600 nullptr,
6601 /* aIsInitialDocument */ false);
6602}
6603
6604nsresult nsDocShell::CreateDocumentViewerForActor(
6605 WindowGlobalChild* aWindowActor) {
6606 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"
, 6606); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aWindowActor"
")"); do { *((volatile int*)__null) = 6606; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6607
6608 // FIXME: WindowGlobalChild should provide the PartitionedPrincipal.
6609 // FIXME: We may want to support non-initial documents here.
6610 nsresult rv = CreateAboutBlankDocumentViewer(
6611 aWindowActor->DocumentPrincipal(), aWindowActor->DocumentPrincipal(),
6612 /* aCsp */ nullptr,
6613 /* aBaseURI */ nullptr,
6614 /* aIsInitialDocument */ true,
6615 /* aCOEP */ Nothing(),
6616 /* aTryToSaveOldPresentation */ true,
6617 /* aCheckPermitUnload */ true, aWindowActor);
6618#ifdef DEBUG1
6619 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
6620 RefPtr<Document> doc(GetDocument());
6621 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"
, 6623); AnnotateMozCrashReason("MOZ_ASSERT" "(" "doc" ") (" "Should have a document if CreateAboutBlankDocumentViewer succeeded"
")"); do { *((volatile int*)__null) = 6623; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6622 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"
, 6623); AnnotateMozCrashReason("MOZ_ASSERT" "(" "doc" ") (" "Should have a document if CreateAboutBlankDocumentViewer succeeded"
")"); do { *((volatile int*)__null) = 6623; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6623 "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"
, 6623); AnnotateMozCrashReason("MOZ_ASSERT" "(" "doc" ") (" "Should have a document if CreateAboutBlankDocumentViewer succeeded"
")"); do { *((volatile int*)__null) = 6623; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6624 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"
, 6625); AnnotateMozCrashReason("MOZ_ASSERT" "(" "doc->GetOwnerGlobal() == aWindowActor->GetWindowGlobal()"
") (" "New document should be in the same global as our actor"
")"); do { *((volatile int*)__null) = 6625; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6625 "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"
, 6625); AnnotateMozCrashReason("MOZ_ASSERT" "(" "doc->GetOwnerGlobal() == aWindowActor->GetWindowGlobal()"
") (" "New document should be in the same global as our actor"
")"); do { *((volatile int*)__null) = 6625; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6626 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"
, 6627); AnnotateMozCrashReason("MOZ_ASSERT" "(" "doc->IsInitialDocument()"
") (" "New document should be an initial document" ")"); do {
*((volatile int*)__null) = 6627; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
6627 "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"
, 6627); AnnotateMozCrashReason("MOZ_ASSERT" "(" "doc->IsInitialDocument()"
") (" "New document should be an initial document" ")"); do {
*((volatile int*)__null) = 6627; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
6628 }
6629#endif
6630
6631 return rv;
6632}
6633
6634bool nsDocShell::CanSavePresentation(uint32_t aLoadType,
6635 nsIRequest* aNewRequest,
6636 Document* aNewDocument,
6637 bool aReportBFCacheComboTelemetry) {
6638 if (!mOSHE) {
6639 return false; // no entry to save into
6640 }
6641
6642 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"
, 6643); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mozilla::SessionHistoryInParent()"
") (" "mOSHE cannot be non-null with SHIP" ")"); do { *((volatile
int*)__null) = 6643; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
6643 "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"
, 6643); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mozilla::SessionHistoryInParent()"
") (" "mOSHE cannot be non-null with SHIP" ")"); do { *((volatile
int*)__null) = 6643; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
6644 nsCOMPtr<nsIDocumentViewer> viewer = mOSHE->GetDocumentViewer();
6645 if (viewer) {
6646 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"
, 6646)
;
6647 return false;
6648 }
6649
6650 // Only save presentation for "normal" loads and link loads. Anything else
6651 // probably wants to refetch the page, so caching the old presentation
6652 // would be incorrect.
6653 if (aLoadType != LOAD_NORMAL && aLoadType != LOAD_HISTORY &&
6654 aLoadType != LOAD_LINK && aLoadType != LOAD_STOP_CONTENT &&
6655 aLoadType != LOAD_STOP_CONTENT_AND_REPLACE &&
6656 aLoadType != LOAD_ERROR_PAGE) {
6657 return false;
6658 }
6659
6660 // If the session history entry has the saveLayoutState flag set to false,
6661 // then we should not cache the presentation.
6662 if (!mOSHE->GetSaveLayoutStateFlag()) {
6663 return false;
6664 }
6665
6666 // If the document is not done loading, don't cache it.
6667 if (!mScriptGlobal || mScriptGlobal->IsLoading()) {
6668 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)
6669 ("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)
;
6670 return false;
6671 }
6672
6673 if (mScriptGlobal->WouldReuseInnerWindow(aNewDocument)) {
6674 return false;
6675 }
6676
6677 // Avoid doing the work of saving the presentation state in the case where
6678 // the content viewer cache is disabled.
6679 if (nsSHistory::GetMaxTotalViewers() == 0) {
6680 return false;
6681 }
6682
6683 // Don't cache the content viewer if we're in a subframe.
6684 if (mBrowsingContext->GetParent()) {
6685 return false; // this is a subframe load
6686 }
6687
6688 // If the document does not want its presentation cached, then don't.
6689 RefPtr<Document> doc = mScriptGlobal->GetExtantDoc();
6690
6691 uint32_t bfCacheCombo = 0;
6692 bool canSavePresentation =
6693 doc->CanSavePresentation(aNewRequest, bfCacheCombo, true);
6694 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"
, 6694); AnnotateMozCrashReason("MOZ_ASSERT" "(" "bfCacheCombo == 0"
")"); do { *((volatile int*)__null) = 6694; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
6695 if (canSavePresentation && doc->IsTopLevelContentDocument()) {
6696 auto* browsingContextGroup = mBrowsingContext->Group();
6697 nsTArray<RefPtr<BrowsingContext>>& topLevelContext =
6698 browsingContextGroup->Toplevels();
6699
6700 for (const auto& browsingContext : topLevelContext) {
6701 if (browsingContext != mBrowsingContext) {
6702 if (StaticPrefs::docshell_shistory_bfcache_require_no_opener()) {
6703 canSavePresentation = false;
6704 }
6705 bfCacheCombo |= BFCacheStatus::NOT_ONLY_TOPLEVEL_IN_BCG;
6706 break;
6707 }
6708 }
6709 }
6710
6711 if (aReportBFCacheComboTelemetry) {
6712 ReportBFCacheComboTelemetry(bfCacheCombo);
6713 }
6714 return doc && canSavePresentation;
6715}
6716
6717/* static */
6718void nsDocShell::ReportBFCacheComboTelemetry(uint32_t aCombo) {
6719 // There are 11 possible reasons to make a request fails to use BFCache
6720 // (see BFCacheStatus in dom/base/Document.h), and we'd like to record
6721 // the common combinations for reasons which make requests fail to use
6722 // BFCache. These combinations are generated based on some local browsings,
6723 // we need to adjust them when necessary.
6724 enum BFCacheStatusCombo : uint32_t {
6725 BFCACHE_SUCCESS,
6726 NOT_ONLY_TOPLEVEL = mozilla::dom::BFCacheStatus::NOT_ONLY_TOPLEVEL_IN_BCG,
6727 // If both unload and beforeunload listeners are presented, it'll be
6728 // recorded as unload
6729 UNLOAD = mozilla::dom::BFCacheStatus::UNLOAD_LISTENER,
6730 UNLOAD_REQUEST = mozilla::dom::BFCacheStatus::UNLOAD_LISTENER |
6731 mozilla::dom::BFCacheStatus::REQUEST,
6732 REQUEST = mozilla::dom::BFCacheStatus::REQUEST,
6733 UNLOAD_REQUEST_PEER = mozilla::dom::BFCacheStatus::UNLOAD_LISTENER |
6734 mozilla::dom::BFCacheStatus::REQUEST |
6735 mozilla::dom::BFCacheStatus::ACTIVE_PEER_CONNECTION,
6736 UNLOAD_REQUEST_PEER_MSE =
6737 mozilla::dom::BFCacheStatus::UNLOAD_LISTENER |
6738 mozilla::dom::BFCacheStatus::REQUEST |
6739 mozilla::dom::BFCacheStatus::ACTIVE_PEER_CONNECTION |
6740 mozilla::dom::BFCacheStatus::CONTAINS_MSE_CONTENT,
6741 UNLOAD_REQUEST_MSE = mozilla::dom::BFCacheStatus::UNLOAD_LISTENER |
6742 mozilla::dom::BFCacheStatus::REQUEST |
6743 mozilla::dom::BFCacheStatus::CONTAINS_MSE_CONTENT,
6744 SUSPENDED_UNLOAD_REQUEST_PEER =
6745 mozilla::dom::BFCacheStatus::SUSPENDED |
6746 mozilla::dom::BFCacheStatus::UNLOAD_LISTENER |
6747 mozilla::dom::BFCacheStatus::REQUEST |
6748 mozilla::dom::BFCacheStatus::ACTIVE_PEER_CONNECTION,
6749 REMOTE_SUBFRAMES = mozilla::dom::BFCacheStatus::CONTAINS_REMOTE_SUBFRAMES,
6750 BEFOREUNLOAD = mozilla::dom::BFCacheStatus::BEFOREUNLOAD_LISTENER,
6751 };
6752
6753 // Beforeunload is recorded as a blocker only if it is the only one to block
6754 // bfcache.
6755 if (aCombo != mozilla::dom::BFCacheStatus::BEFOREUNLOAD_LISTENER) {
6756 aCombo &= ~mozilla::dom::BFCacheStatus::BEFOREUNLOAD_LISTENER;
6757 }
6758 switch (aCombo) {
6759 case BFCACHE_SUCCESS:
6760 Telemetry::AccumulateCategorical(
6761 Telemetry::LABELS_BFCACHE_COMBO::BFCache_Success);
6762 break;
6763 case NOT_ONLY_TOPLEVEL:
6764 if (StaticPrefs::docshell_shistory_bfcache_require_no_opener()) {
6765 Telemetry::AccumulateCategorical(
6766 Telemetry::LABELS_BFCACHE_COMBO::Other);
6767 break;
6768 }
6769 Telemetry::AccumulateCategorical(
6770 Telemetry::LABELS_BFCACHE_COMBO::BFCache_Success);
6771 Telemetry::AccumulateCategorical(
6772 Telemetry::LABELS_BFCACHE_COMBO::Success_Not_Toplevel);
6773 break;
6774 case UNLOAD:
6775 Telemetry::AccumulateCategorical(Telemetry::LABELS_BFCACHE_COMBO::Unload);
6776 break;
6777 case BEFOREUNLOAD:
6778 Telemetry::AccumulateCategorical(
6779 Telemetry::LABELS_BFCACHE_COMBO::Beforeunload);
6780 break;
6781 case UNLOAD_REQUEST:
6782 Telemetry::AccumulateCategorical(
6783 Telemetry::LABELS_BFCACHE_COMBO::Unload_Req);
6784 break;
6785 case REQUEST:
6786 Telemetry::AccumulateCategorical(Telemetry::LABELS_BFCACHE_COMBO::Req);
6787 break;
6788 case UNLOAD_REQUEST_PEER:
6789 Telemetry::AccumulateCategorical(
6790 Telemetry::LABELS_BFCACHE_COMBO::Unload_Req_Peer);
6791 break;
6792 case UNLOAD_REQUEST_PEER_MSE:
6793 Telemetry::AccumulateCategorical(
6794 Telemetry::LABELS_BFCACHE_COMBO::Unload_Req_Peer_MSE);
6795 break;
6796 case UNLOAD_REQUEST_MSE:
6797 Telemetry::AccumulateCategorical(
6798 Telemetry::LABELS_BFCACHE_COMBO::Unload_Req_MSE);
6799 break;
6800 case SUSPENDED_UNLOAD_REQUEST_PEER:
6801 Telemetry::AccumulateCategorical(
6802 Telemetry::LABELS_BFCACHE_COMBO::SPD_Unload_Req_Peer);
6803 break;
6804 case REMOTE_SUBFRAMES:
6805 Telemetry::AccumulateCategorical(
6806 Telemetry::LABELS_BFCACHE_COMBO::Remote_Subframes);
6807 break;
6808 default:
6809 Telemetry::AccumulateCategorical(Telemetry::LABELS_BFCACHE_COMBO::Other);
6810 break;
6811 }
6812};
6813
6814void nsDocShell::ReattachEditorToWindow(nsISHEntry* aSHEntry) {
6815 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"
, 6815); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mozilla::SessionHistoryInParent()"
")"); do { *((volatile int*)__null) = 6815; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6816 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"
, 6816); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mIsBeingDestroyed"
")"); do { *((volatile int*)__null) = 6816; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6817
6818 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"
, 6819); MOZ_PretendNoReturn(); } } while (0)
6819 "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"
, 6819); MOZ_PretendNoReturn(); } } while (0)
;
6820 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"
, 6821); MOZ_PretendNoReturn(); } } while (0)
6821 "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"
, 6821); MOZ_PretendNoReturn(); } } while (0)
;
6822
6823 if (mEditorData || !aSHEntry) {
6824 return;
6825 }
6826
6827 mEditorData = WrapUnique(aSHEntry->ForgetEditorData());
6828 if (mEditorData) {
6829#ifdef DEBUG1
6830 nsresult rv =
6831#endif
6832 mEditorData->ReattachToWindow(this);
6833 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"
, 6833); MOZ_PretendNoReturn(); } } while (0)
;
6834 }
6835}
6836
6837void nsDocShell::DetachEditorFromWindow() {
6838 if (!mEditorData || mEditorData->WaitingForLoad()) {
6839 // If there's nothing to detach, or if the editor data is actually set
6840 // up for the _new_ page that's coming in, don't detach.
6841 return;
6842 }
6843
6844 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"
, 6845); MOZ_PretendNoReturn(); } } while (0)
6845 "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"
, 6845); MOZ_PretendNoReturn(); } } while (0)
;
6846
6847 nsresult res = mEditorData->DetachFromWindow();
6848 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"
, 6848); MOZ_PretendNoReturn(); } } while (0)
;
6849
6850 if (NS_SUCCEEDED(res)((bool)(__builtin_expect(!!(!NS_FAILED_impl(res)), 1)))) {
6851 // Make mOSHE hold the owning ref to the editor data.
6852 if (mOSHE) {
6853 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"
, 6855); 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) = 6855; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6854 "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"
, 6855); 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) = 6855; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6855 "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"
, 6855); 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) = 6855; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6856 mOSHE->SetEditorData(mEditorData.release());
6857 } else {
6858 mEditorData = nullptr;
6859 }
6860 }
6861
6862#ifdef DEBUG1
6863 {
6864 bool isEditable;
6865 GetEditable(&isEditable);
6866 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"
, 6867); MOZ_PretendNoReturn(); } } while (0)
6867 "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"
, 6867); MOZ_PretendNoReturn(); } } while (0)
;
6868 }
6869#endif // DEBUG
6870}
6871
6872nsresult nsDocShell::CaptureState() {
6873 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"
, 6873); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mozilla::SessionHistoryInParent()"
")"); do { *((volatile int*)__null) = 6873; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6874
6875 if (!mOSHE || mOSHE == mLSHE) {
6876 // No entry to save into, or we're replacing the existing entry.
6877 return NS_ERROR_FAILURE;
6878 }
6879
6880 if (!mScriptGlobal) {
6881 return NS_ERROR_FAILURE;
6882 }
6883
6884 nsCOMPtr<nsISupports> windowState = mScriptGlobal->SaveWindowState();
6885 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"
, 6885); return NS_ERROR_FAILURE; } } while (false)
;
6886
6887 if (MOZ_UNLIKELY(MOZ_LOG_TEST(gPageCacheLog, LogLevel::Debug))(__builtin_expect(!!((__builtin_expect(!!(mozilla::detail::log_test
(gPageCacheLog, LogLevel::Debug)), 0))), 0))
) {
6888 nsAutoCString spec;
6889 nsCOMPtr<nsIURI> uri = mOSHE->GetURI();
6890 if (uri) {
6891 uri->GetSpec(spec);
6892 }
6893 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)
6894 ("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)
;
6895 }
6896
6897 mOSHE->SetWindowState(windowState);
6898
6899 // Suspend refresh URIs and save off the timer queue
6900 mOSHE->SetRefreshURIList(mSavedRefreshURIList);
6901
6902 // Capture the current content viewer bounds.
6903 if (mDocumentViewer) {
6904 LayoutDeviceIntRect bounds;
6905 mDocumentViewer->GetBounds(bounds);
6906 mOSHE->SetViewerBounds(bounds.ToUnknownRect());
6907 }
6908
6909 // Capture the docshell hierarchy.
6910 mOSHE->ClearChildShells();
6911
6912 uint32_t childCount = mChildList.Length();
6913 for (uint32_t i = 0; i < childCount; ++i) {
6914 nsCOMPtr<nsIDocShellTreeItem> childShell = do_QueryInterface(ChildAt(i));
6915 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"
, 6915); MOZ_PretendNoReturn(); } } while (0)
;
6916
6917 mOSHE->AddChildShell(childShell);
6918 }
6919
6920 return NS_OK;
6921}
6922
6923NS_IMETHODIMPnsresult
6924nsDocShell::RestorePresentationEvent::Run() {
6925 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"
, 6925); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mozilla::SessionHistoryInParent()"
")"); do { *((volatile int*)__null) = 6925; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6926
6927 if (mDocShell && NS_FAILED(mDocShell->RestoreFromHistory())((bool)(__builtin_expect(!!(NS_FAILED_impl(mDocShell->RestoreFromHistory
())), 0)))
) {
6928 NS_WARNING("RestoreFromHistory failed")NS_DebugBreak(NS_DEBUG_WARNING, "RestoreFromHistory failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 6928)
;
6929 }
6930 return NS_OK;
6931}
6932
6933NS_IMETHODIMPnsresult
6934nsDocShell::BeginRestore(nsIDocumentViewer* aDocumentViewer, bool aTop) {
6935 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"
, 6935); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mozilla::SessionHistoryInParent()"
")"); do { *((volatile int*)__null) = 6935; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6936
6937 nsresult rv;
6938 if (!aDocumentViewer) {
6939 rv = EnsureDocumentViewer();
6940 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"
, 6940); return rv; } } while (false)
;
6941
6942 aDocumentViewer = mDocumentViewer;
6943 }
6944
6945 // Dispatch events for restoring the presentation. We try to simulate
6946 // the progress notifications loading the document would cause, so we add
6947 // the document's channel to the loadgroup to initiate stateChange
6948 // notifications.
6949
6950 RefPtr<Document> doc = aDocumentViewer->GetDocument();
6951 if (doc) {
6952 nsIChannel* channel = doc->GetChannel();
6953 if (channel) {
6954 mEODForCurrentDocument = false;
6955 mIsRestoringDocument = true;
6956 mLoadGroup->AddRequest(channel, nullptr);
6957 mIsRestoringDocument = false;
6958 }
6959 }
6960
6961 if (!aTop) {
6962 // This point corresponds to us having gotten OnStartRequest or
6963 // STATE_START, so do the same thing that CreateDocumentViewer does at
6964 // this point to ensure that unload/pagehide events for this document
6965 // will fire when it's unloaded again.
6966 mFiredUnloadEvent = false;
6967
6968 // For non-top frames, there is no notion of making sure that the
6969 // previous document is in the domwindow when STATE_START notifications
6970 // happen. We can just call BeginRestore for all of the child shells
6971 // now.
6972 rv = BeginRestoreChildren();
6973 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"
, 6973); return rv; } } while (false)
;
6974 }
6975
6976 return NS_OK;
6977}
6978
6979nsresult nsDocShell::BeginRestoreChildren() {
6980 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"
, 6980); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mozilla::SessionHistoryInParent()"
")"); do { *((volatile int*)__null) = 6980; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6981
6982 for (auto* childDocLoader : mChildList.ForwardRange()) {
6983 nsCOMPtr<nsIDocShell> child = do_QueryObject(childDocLoader);
6984 if (child) {
6985 nsresult rv = child->BeginRestore(nullptr, false);
6986 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"
, 6986); return rv; } } while (false)
;
6987 }
6988 }
6989 return NS_OK;
6990}
6991
6992NS_IMETHODIMPnsresult
6993nsDocShell::FinishRestore() {
6994 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"
, 6994); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mozilla::SessionHistoryInParent()"
")"); do { *((volatile int*)__null) = 6994; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6995
6996 // First we call finishRestore() on our children. In the simulated load,
6997 // all of the child frames finish loading before the main document.
6998
6999 for (auto* childDocLoader : mChildList.ForwardRange()) {
7000 nsCOMPtr<nsIDocShell> child = do_QueryObject(childDocLoader);
7001 if (child) {
7002 child->FinishRestore();
7003 }
7004 }
7005
7006 if (mOSHE && mOSHE->HasDetachedEditor()) {
7007 ReattachEditorToWindow(mOSHE);
7008 }
7009
7010 RefPtr<Document> doc = GetDocument();
7011 if (doc) {
7012 // Finally, we remove the request from the loadgroup. This will
7013 // cause onStateChange(STATE_STOP) to fire, which will fire the
7014 // pageshow event to the chrome.
7015
7016 nsIChannel* channel = doc->GetChannel();
7017 if (channel) {
7018 mIsRestoringDocument = true;
7019 mLoadGroup->RemoveRequest(channel, nullptr, NS_OK);
7020 mIsRestoringDocument = false;
7021 }
7022 }
7023
7024 return NS_OK;
7025}
7026
7027NS_IMETHODIMPnsresult
7028nsDocShell::GetRestoringDocument(bool* aRestoring) {
7029 *aRestoring = mIsRestoringDocument;
7030 return NS_OK;
7031}
7032
7033nsresult nsDocShell::RestorePresentation(nsISHEntry* aSHEntry,
7034 bool* aRestoring) {
7035 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"
, 7035); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mozilla::SessionHistoryInParent()"
")"); do { *((volatile int*)__null) = 7035; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7036 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"
, 7036); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mIsBeingDestroyed"
")"); do { *((volatile int*)__null) = 7036; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7037
7038 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"
, 7039); MOZ_PretendNoReturn(); } } while (0)
7039 "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"
, 7039); MOZ_PretendNoReturn(); } } while (0)
;
7040
7041 nsCOMPtr<nsIDocumentViewer> viewer = aSHEntry->GetDocumentViewer();
7042
7043 nsAutoCString spec;
7044 if (MOZ_UNLIKELY(MOZ_LOG_TEST(gPageCacheLog, LogLevel::Debug))(__builtin_expect(!!((__builtin_expect(!!(mozilla::detail::log_test
(gPageCacheLog, LogLevel::Debug)), 0))), 0))
) {
7045 nsCOMPtr<nsIURI> uri = aSHEntry->GetURI();
7046 if (uri) {
7047 uri->GetSpec(spec);
7048 }
7049 }
7050
7051 *aRestoring = false;
7052
7053 if (!viewer) {
7054 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)
7055 ("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)
;
7056 return NS_OK;
7057 }
7058
7059 // We need to make sure the content viewer's container is this docshell.
7060 // In subframe navigation, it's possible for the docshell that the
7061 // content viewer was originally loaded into to be replaced with a
7062 // different one. We don't currently support restoring the presentation
7063 // in that case.
7064
7065 nsCOMPtr<nsIDocShell> container;
7066 viewer->GetContainer(getter_AddRefs(container));
7067 if (!::SameCOMIdentity(container, GetAsSupports(this))) {
7068 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)
7069 ("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)
;
7070 aSHEntry->SetDocumentViewer(nullptr);
7071 return NS_ERROR_FAILURE;
7072 }
7073
7074 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"
, 7074); MOZ_PretendNoReturn(); } } while (0)
;
7075
7076 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)
7077 ("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)
;
7078
7079 SetHistoryEntryAndUpdateBC(Some(aSHEntry), Nothing());
7080
7081 // Post an event that will remove the request after we've returned
7082 // to the event loop. This mimics the way it is called by nsIChannel
7083 // implementations.
7084
7085 // Revoke any pending restore (just in case).
7086 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"
, 7087); MOZ_PretendNoReturn(); } } while (0)
7087 "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"
, 7087); MOZ_PretendNoReturn(); } } while (0)
;
7088 mRestorePresentationEvent.Revoke();
7089
7090 RefPtr<RestorePresentationEvent> evt = new RestorePresentationEvent(this);
7091 nsresult rv = Dispatch(do_AddRef(evt));
7092 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
7093 mRestorePresentationEvent = evt.get();
7094 // The rest of the restore processing will happen on our event
7095 // callback.
7096 *aRestoring = true;
7097 }
7098
7099 return rv;
7100}
7101
7102namespace {
7103class MOZ_STACK_CLASS PresentationEventForgetter {
7104 public:
7105 explicit PresentationEventForgetter(
7106 nsRevocableEventPtr<nsDocShell::RestorePresentationEvent>&
7107 aRestorePresentationEvent)
7108 : mRestorePresentationEvent(aRestorePresentationEvent),
7109 mEvent(aRestorePresentationEvent.get()) {}
7110
7111 ~PresentationEventForgetter() { Forget(); }
7112
7113 void Forget() {
7114 if (mRestorePresentationEvent.get() == mEvent) {
7115 mRestorePresentationEvent.Forget();
7116 mEvent = nullptr;
7117 }
7118 }
7119
7120 private:
7121 nsRevocableEventPtr<nsDocShell::RestorePresentationEvent>&
7122 mRestorePresentationEvent;
7123 RefPtr<nsDocShell::RestorePresentationEvent> mEvent;
7124};
7125
7126} // namespace
7127
7128bool nsDocShell::SandboxFlagsImplyCookies(const uint32_t& aSandboxFlags) {
7129 return (aSandboxFlags & (SANDBOXED_ORIGIN | SANDBOXED_SCRIPTS)) == 0;
7130}
7131
7132nsresult nsDocShell::RestoreFromHistory() {
7133 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"
, 7133); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mozilla::SessionHistoryInParent()"
")"); do { *((volatile int*)__null) = 7133; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7134 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"
, 7134); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mRestorePresentationEvent.IsPending()"
")"); do { *((volatile int*)__null) = 7134; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7135 PresentationEventForgetter forgetter(mRestorePresentationEvent);
7136
7137 // This section of code follows the same ordering as CreateDocumentViewer.
7138 if (!mLSHE) {
7139 return NS_ERROR_FAILURE;
7140 }
7141
7142 nsCOMPtr<nsIDocumentViewer> viewer = mLSHE->GetDocumentViewer();
7143 if (!viewer) {
7144 return NS_ERROR_FAILURE;
7145 }
7146
7147 if (mSavingOldViewer) {
7148 // We determined that it was safe to cache the document presentation
7149 // at the time we initiated the new load. We need to check whether
7150 // it's still safe to do so, since there may have been DOM mutations
7151 // or new requests initiated.
7152 RefPtr<Document> doc = viewer->GetDocument();
7153 nsIRequest* request = nullptr;
7154 if (doc) {
7155 request = doc->GetChannel();
7156 }
7157 mSavingOldViewer = CanSavePresentation(
7158 mLoadType, request, doc, /* aReportBFCacheComboTelemetry */ false);
7159 }
7160
7161 // Protect against mLSHE going away via a load triggered from
7162 // pagehide or unload.
7163 nsCOMPtr<nsISHEntry> origLSHE = mLSHE;
7164
7165 // Make sure to blow away our mLoadingURI just in case. No loads
7166 // from inside this pagehide.
7167 mLoadingURI = nullptr;
7168
7169 // Notify the old content viewer that it's being hidden.
7170 FirePageHideNotification(!mSavingOldViewer);
7171 // pagehide notification might destroy this docshell.
7172 if (mIsBeingDestroyed) {
7173 return NS_ERROR_DOCSHELL_DYING;
7174 }
7175
7176 // If mLSHE was changed as a result of the pagehide event, then
7177 // something else was loaded. Don't finish restoring.
7178 if (mLSHE != origLSHE) {
7179 return NS_OK;
7180 }
7181
7182 // Add the request to our load group. We do this before swapping out
7183 // the content viewers so that consumers of STATE_START can access
7184 // the old document. We only deal with the toplevel load at this time --
7185 // to be consistent with normal document loading, subframes cannot start
7186 // loading until after data arrives, which is after STATE_START completes.
7187
7188 RefPtr<RestorePresentationEvent> currentPresentationRestoration =
7189 mRestorePresentationEvent.get();
7190 Stop();
7191 // Make sure we're still restoring the same presentation.
7192 // If we aren't, docshell is in process doing another load already.
7193 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"
, 7194); return NS_ERROR_UNEXPECTED; } } while (false)
7194 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"
, 7194); return NS_ERROR_UNEXPECTED; } } while (false)
;
7195 BeginRestore(viewer, true);
7196 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"
, 7197); return NS_ERROR_UNEXPECTED; } } while (false)
7197 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"
, 7197); return NS_ERROR_UNEXPECTED; } } while (false)
;
7198 forgetter.Forget();
7199
7200 // Set mFiredUnloadEvent = false so that the unload handler for the
7201 // *new* document will fire.
7202 mFiredUnloadEvent = false;
7203
7204 mURIResultedInDocument = true;
7205 RefPtr<ChildSHistory> rootSH = GetRootSessionHistory();
7206 if (rootSH) {
7207 mPreviousEntryIndex = rootSH->Index();
7208 rootSH->LegacySHistory()->UpdateIndex();
7209 mLoadedEntryIndex = rootSH->Index();
7210 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)
7211 ("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)
7212 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)
;
7213 }
7214
7215 // Rather than call Embed(), we will retrieve the viewer from the session
7216 // history entry and swap it in.
7217 // XXX can we refactor this so that we can just call Embed()?
7218 PersistLayoutHistoryState();
7219 nsresult rv;
7220 if (mDocumentViewer) {
7221 if (mSavingOldViewer && NS_FAILED(CaptureState())((bool)(__builtin_expect(!!(NS_FAILED_impl(CaptureState())), 0
)))
) {
7222 if (mOSHE) {
7223 mOSHE->SyncPresentationState();
7224 }
7225 mSavingOldViewer = false;
7226 }
7227 }
7228
7229 mSavedRefreshURIList = nullptr;
7230
7231 // In cases where we use a transient about:blank viewer between loads,
7232 // we never show the transient viewer, so _its_ previous viewer is never
7233 // unhooked from the view hierarchy. Destroy any such previous viewer now,
7234 // before we grab the root view sibling, so that we don't grab a view
7235 // that's about to go away.
7236
7237 if (mDocumentViewer) {
7238 // Make sure to hold a strong ref to previousViewer here while we
7239 // drop the reference to it from mDocumentViewer.
7240 nsCOMPtr<nsIDocumentViewer> previousViewer =
7241 mDocumentViewer->GetPreviousViewer();
7242 if (previousViewer) {
7243 mDocumentViewer->SetPreviousViewer(nullptr);
7244 previousViewer->Destroy();
7245 }
7246 }
7247
7248 // Save off the root view's parent and sibling so that we can insert the
7249 // new content viewer's root view at the same position. Also save the
7250 // bounds of the root view's widget.
7251
7252 nsView* rootViewSibling = nullptr;
7253 nsView* rootViewParent = nullptr;
7254 LayoutDeviceIntRect newBounds(0, 0, 0, 0);
7255
7256 PresShell* oldPresShell = GetPresShell();
7257 if (oldPresShell) {
7258 nsViewManager* vm = oldPresShell->GetViewManager();
7259 if (vm) {
7260 nsView* oldRootView = vm->GetRootView();
7261
7262 if (oldRootView) {
7263 rootViewSibling = oldRootView->GetNextSibling();
7264 rootViewParent = oldRootView->GetParent();
7265
7266 mDocumentViewer->GetBounds(newBounds);
7267 }
7268 }
7269 }
7270
7271 nsCOMPtr<nsIContent> container;
7272 RefPtr<Document> sibling;
7273 if (rootViewParent && rootViewParent->GetParent()) {
7274 nsIFrame* frame = rootViewParent->GetParent()->GetFrame();
7275 container = frame ? frame->GetContent() : nullptr;
7276 }
7277 if (rootViewSibling) {
7278 nsIFrame* frame = rootViewSibling->GetFrame();
7279 sibling = frame ? frame->PresShell()->GetDocument() : nullptr;
7280 }
7281
7282 // Transfer ownership to mDocumentViewer. By ensuring that either the
7283 // docshell or the session history, but not both, have references to the
7284 // content viewer, we prevent the viewer from being torn down after
7285 // Destroy() is called.
7286
7287 if (mDocumentViewer) {
7288 mDocumentViewer->Close(mSavingOldViewer ? mOSHE.get() : nullptr);
7289 viewer->SetPreviousViewer(mDocumentViewer);
7290 }
7291 if (mOSHE && (!mDocumentViewer || !mSavingOldViewer)) {
7292 // We don't plan to save a viewer in mOSHE; tell it to drop
7293 // any other state it's holding.
7294 mOSHE->SyncPresentationState();
7295 }
7296
7297 // Order the mDocumentViewer setup just like Embed does.
7298 mDocumentViewer = nullptr;
7299
7300 // Now that we're about to switch documents, forget all of our children.
7301 // Note that we cached them as needed up in CaptureState above.
7302 DestroyChildren();
7303
7304 mDocumentViewer.swap(viewer);
7305
7306 // Grab all of the related presentation from the SHEntry now.
7307 // Clearing the viewer from the SHEntry will clear all of this state.
7308 nsCOMPtr<nsISupports> windowState = mLSHE->GetWindowState();
7309 mLSHE->SetWindowState(nullptr);
7310
7311 bool sticky = mLSHE->GetSticky();
7312
7313 RefPtr<Document> document = mDocumentViewer->GetDocument();
7314
7315 nsCOMArray<nsIDocShellTreeItem> childShells;
7316 int32_t i = 0;
7317 nsCOMPtr<nsIDocShellTreeItem> child;
7318 while (NS_SUCCEEDED(mLSHE->ChildShellAt(i++, getter_AddRefs(child)))((bool)(__builtin_expect(!!(!NS_FAILED_impl(mLSHE->ChildShellAt
(i++, getter_AddRefs(child)))), 1)))
&&
7319 child) {
7320 childShells.AppendObject(child);
7321 }
7322
7323 // get the previous content viewer size
7324 nsIntRect oldBounds(0, 0, 0, 0);
7325 mLSHE->GetViewerBounds(oldBounds);
7326
7327 // Restore the refresh URI list. The refresh timers will be restarted
7328 // when EndPageLoad() is called.
7329 nsCOMPtr<nsIMutableArray> refreshURIList = mLSHE->GetRefreshURIList();
7330
7331 // Reattach to the window object.
7332 mIsRestoringDocument = true; // for MediaDocument::BecomeInteractive
7333 rv = mDocumentViewer->Open(windowState, mLSHE);
7334 mIsRestoringDocument = false;
7335
7336 // Hack to keep nsDocShellEditorData alive across the
7337 // SetDocumentViewer(nullptr) call below.
7338 UniquePtr<nsDocShellEditorData> data(mLSHE->ForgetEditorData());
7339
7340 // Now remove it from the cached presentation.
7341 mLSHE->SetDocumentViewer(nullptr);
7342 mEODForCurrentDocument = false;
7343
7344 mLSHE->SetEditorData(data.release());
7345
7346#ifdef DEBUG1
7347 {
7348 nsCOMPtr<nsIMutableArray> refreshURIs = mLSHE->GetRefreshURIList();
7349 nsCOMPtr<nsIDocShellTreeItem> childShell;
7350 mLSHE->ChildShellAt(0, getter_AddRefs(childShell));
7351 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"
, 7352); MOZ_PretendNoReturn(); } } while (0)
7352 "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"
, 7352); MOZ_PretendNoReturn(); } } while (0)
;
7353 }
7354#endif
7355
7356 // Restore the sticky state of the viewer. The viewer has set this state
7357 // on the history entry in Destroy() just before marking itself non-sticky,
7358 // to avoid teardown of the presentation.
7359 mDocumentViewer->SetSticky(sticky);
7360
7361 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"
, 7361); return rv; } } while (false)
;
7362
7363 // mLSHE is now our currently-loaded document.
7364 SetHistoryEntryAndUpdateBC(Nothing(), Some<nsISHEntry*>(mLSHE));
7365
7366 // We aren't going to restore any items from the LayoutHistoryState,
7367 // but we don't want them to stay around in case the page is reloaded.
7368 SetLayoutHistoryState(nullptr);
7369
7370 // This is the end of our Embed() replacement
7371
7372 mSavingOldViewer = false;
7373 mEODForCurrentDocument = false;
7374
7375 if (document) {
7376 RefPtr<nsDocShell> parent = GetInProcessParentDocshell();
7377 if (parent) {
7378 RefPtr<Document> d = parent->GetDocument();
7379 if (d) {
7380 if (d->EventHandlingSuppressed()) {
7381 document->SuppressEventHandling(d->EventHandlingSuppressed());
7382 }
7383 }
7384 }
7385
7386 // Use the uri from the mLSHE we had when we entered this function
7387 // (which need not match the document's URI if anchors are involved),
7388 // since that's the history entry we're loading. Note that if we use
7389 // origLSHE we don't have to worry about whether the entry in question
7390 // is still mLSHE or whether it's now mOSHE.
7391 nsCOMPtr<nsIURI> uri = origLSHE->GetURI();
7392 SetCurrentURI(uri, document->GetChannel(), /* aFireLocationChange */ true,
7393 /* aIsInitialAboutBlank */ false,
7394 /* aLocationFlags */ 0);
7395 }
7396
7397 // This is the end of our CreateDocumentViewer() replacement.
7398 // Now we simulate a load. First, we restore the state of the javascript
7399 // window object.
7400 nsCOMPtr<nsPIDOMWindowOuter> privWin = GetWindow();
7401 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"
, 7401); MOZ_PretendNoReturn(); } } while (0)
;
7402
7403 // Now, dispatch a title change event which would happen as the
7404 // <head> is parsed.
7405 document->NotifyPossibleTitleChange(false);
7406
7407 // Now we simulate appending child docshells for subframes.
7408 for (i = 0; i < childShells.Count(); ++i) {
7409 nsIDocShellTreeItem* childItem = childShells.ObjectAt(i);
7410 nsCOMPtr<nsIDocShell> childShell = do_QueryInterface(childItem);
7411
7412 // Make sure to not clobber the state of the child. Since AddChild
7413 // always clobbers it, save it off first.
7414 bool allowRedirects;
7415 childShell->GetAllowMetaRedirects(&allowRedirects);
7416
7417 bool allowSubframes;
7418 childShell->GetAllowSubframes(&allowSubframes);
7419
7420 bool allowImages;
7421 childShell->GetAllowImages(&allowImages);
7422
7423 bool allowMedia = childShell->GetAllowMedia();
7424
7425 bool allowDNSPrefetch;
7426 childShell->GetAllowDNSPrefetch(&allowDNSPrefetch);
7427
7428 bool allowContentRetargeting = childShell->GetAllowContentRetargeting();
7429 bool allowContentRetargetingOnChildren =
7430 childShell->GetAllowContentRetargetingOnChildren();
7431
7432 // this.AddChild(child) calls child.SetDocLoaderParent(this), meaning that
7433 // the child inherits our state. Among other things, this means that the
7434 // child inherits our mPrivateBrowsingId, which is what we want.
7435 AddChild(childItem);
7436
7437 childShell->SetAllowMetaRedirects(allowRedirects);
7438 childShell->SetAllowSubframes(allowSubframes);
7439 childShell->SetAllowImages(allowImages);
7440 childShell->SetAllowMedia(allowMedia);
7441 childShell->SetAllowDNSPrefetch(allowDNSPrefetch);
7442 childShell->SetAllowContentRetargeting(allowContentRetargeting);
7443 childShell->SetAllowContentRetargetingOnChildren(
7444 allowContentRetargetingOnChildren);
7445
7446 rv = childShell->BeginRestore(nullptr, false);
7447 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"
, 7447); return rv; } } while (false)
;
7448 }
7449
7450 // Make sure to restore the window state after adding the child shells back
7451 // to the tree. This is necessary for Thaw() and Resume() to propagate
7452 // properly.
7453 rv = privWin->RestoreWindowState(windowState);
7454 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"
, 7454); return rv; } } while (false)
;
7455
7456 RefPtr<PresShell> presShell = GetPresShell();
7457
7458 // We may be displayed on a different monitor (or in a different
7459 // HiDPI mode) than when we got into the history list. So we need
7460 // to check if this has happened. See bug 838239.
7461
7462 // Because the prescontext normally handles resolution changes via
7463 // a runnable (see nsPresContext::UIResolutionChanged), its device
7464 // context won't be -immediately- updated as a result of calling
7465 // presShell->BackingScaleFactorChanged().
7466
7467 // But we depend on that device context when adjusting the view size
7468 // via mDocumentViewer->SetBounds(newBounds) below. So we need to
7469 // explicitly tell it to check for changed resolution here.
7470 if (presShell) {
7471 RefPtr<nsPresContext> pc = presShell->GetPresContext();
7472 if (pc->DeviceContext()->CheckDPIChange()) {
7473 presShell->BackingScaleFactorChanged();
7474 }
7475 // Recompute zoom and text-zoom and such.
7476 pc->RecomputeBrowsingContextDependentData();
7477 }
7478
7479 nsViewManager* newVM = presShell ? presShell->GetViewManager() : nullptr;
7480 nsView* newRootView = newVM ? newVM->GetRootView() : nullptr;
7481
7482 // Insert the new root view at the correct location in the view tree.
7483 if (container) {
7484 nsSubDocumentFrame* subDocFrame =
7485 do_QueryFrame(container->GetPrimaryFrame());
7486 rootViewParent = subDocFrame ? subDocFrame->EnsureInnerView() : nullptr;
7487 } else {
7488 rootViewParent = nullptr;
7489 }
7490 if (sibling && sibling->GetPresShell() &&
7491 sibling->GetPresShell()->GetViewManager()) {
7492 rootViewSibling = sibling->GetPresShell()->GetViewManager()->GetRootView();
7493 } else {
7494 rootViewSibling = nullptr;
7495 }
7496 if (rootViewParent && newRootView &&
7497 newRootView->GetParent() != rootViewParent) {
7498 nsViewManager* parentVM = rootViewParent->GetViewManager();
7499 if (parentVM) {
7500 // InsertChild(parent, child, sib, true) inserts the child after
7501 // sib in content order, which is before sib in view order. BUT
7502 // when sib is null it inserts at the end of the the document
7503 // order, i.e., first in view order. But when oldRootSibling is
7504 // null, the old root as at the end of the view list --- last in
7505 // content order --- and we want to call InsertChild(parent, child,
7506 // nullptr, false) in that case.
7507 parentVM->InsertChild(rootViewParent, newRootView, rootViewSibling,
7508 rootViewSibling ? true : false);
7509
7510 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"
, 7511); MOZ_PretendNoReturn(); } } while (0)
7511 "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"
, 7511); MOZ_PretendNoReturn(); } } while (0)
;
7512 }
7513 }
7514
7515 nsCOMPtr<nsPIDOMWindowInner> privWinInner = privWin->GetCurrentInnerWindow();
7516
7517 // If parent is suspended, increase suspension count.
7518 // This can't be done as early as event suppression since this
7519 // depends on docshell tree.
7520 privWinInner->SyncStateFromParentWindow();
7521
7522 // Now that all of the child docshells have been put into place, we can
7523 // restart the timers for the window and all of the child frames.
7524 privWinInner->Resume();
7525
7526 // Now that we have found the inner window of the page restored
7527 // from the history, we have to make sure that
7528 // performance.navigation.type is 2.
7529 Performance* performance = privWinInner->GetPerformance();
7530 if (performance) {
7531 performance->GetDOMTiming()->NotifyRestoreStart();
7532 }
7533
7534 // Restore the refresh URI list. The refresh timers will be restarted
7535 // when EndPageLoad() is called.
7536 mRefreshURIList = refreshURIList;
7537
7538 // Meta-refresh timers have been restarted for this shell, but not
7539 // for our children. Walk the child shells and restart their timers.
7540 for (auto* childDocLoader : mChildList.ForwardRange()) {
7541 nsCOMPtr<nsIDocShell> child = do_QueryObject(childDocLoader);
7542 if (child) {
7543 child->ResumeRefreshURIs();
7544 }
7545 }
7546
7547 // Make sure this presentation is the same size as the previous
7548 // presentation. If this is not the same size we showed it at last time,
7549 // then we need to resize the widget.
7550
7551 // XXXbryner This interacts poorly with Firefox's infobar. If the old
7552 // presentation had the infobar visible, then we will resize the new
7553 // presentation to that smaller size. However, firing the locationchanged
7554 // event will hide the infobar, which will immediately resize the window
7555 // back to the larger size. A future optimization might be to restore
7556 // the presentation at the "wrong" size, then fire the locationchanged
7557 // event and check whether the docshell's new size is the same as the
7558 // cached viewer size (skipping the resize if they are equal).
7559
7560 if (newRootView) {
7561 if (!newBounds.IsEmpty() &&
7562 !newBounds.ToUnknownRect().IsEqualEdges(oldBounds)) {
7563 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)
7564 ("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)
7565 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)
;
7566 mDocumentViewer->SetBounds(newBounds);
7567 } else if (ScrollContainerFrame* sf =
7568 presShell->GetRootScrollContainerFrame()) {
7569 sf->PostScrolledAreaEventForCurrentArea();
7570 }
7571 }
7572
7573 // The FinishRestore call below can kill these, null them out so we don't
7574 // have invalid pointer lying around.
7575 newRootView = rootViewSibling = rootViewParent = nullptr;
7576 newVM = nullptr;
7577
7578 // If the IsUnderHiddenEmbedderElement() state has been changed, we need to
7579 // update it.
7580 if (oldPresShell && presShell &&
7581 presShell->IsUnderHiddenEmbedderElement() !=
7582 oldPresShell->IsUnderHiddenEmbedderElement()) {
7583 presShell->SetIsUnderHiddenEmbedderElement(
7584 oldPresShell->IsUnderHiddenEmbedderElement());
7585 }
7586
7587 // Simulate the completion of the load.
7588 nsDocShell::FinishRestore();
7589
7590 // Restart plugins, and paint the content.
7591 if (presShell) {
7592 presShell->Thaw();
7593 }
7594
7595 return privWin->FireDelayedDOMEvents(true);
7596}
7597
7598nsresult nsDocShell::CreateDocumentViewer(const nsACString& aContentType,
7599 nsIRequest* aRequest,
7600 nsIStreamListener** aContentHandler) {
7601 *aContentHandler = nullptr;
7602
7603 if (!mTreeOwner || mIsBeingDestroyed) {
7604 // If we don't have a tree owner, then we're in the process of being
7605 // destroyed. Rather than continue trying to load something, just give up.
7606 return NS_ERROR_DOCSHELL_DYING;
7607 }
7608
7609 if (!mBrowsingContext->AncestorsAreCurrent() ||
7610 mBrowsingContext->IsInBFCache()) {
7611 mBrowsingContext->RemoveRootFromBFCacheSync();
7612 return NS_ERROR_NOT_AVAILABLE;
7613 }
7614
7615 // Can we check the content type of the current content viewer
7616 // and reuse it without destroying it and re-creating it?
7617
7618 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"
, 7618); MOZ_PretendNoReturn(); } } while (0)
;
7619
7620 // Instantiate the content viewer object
7621 nsCOMPtr<nsIDocumentViewer> viewer;
7622 nsresult rv = NewDocumentViewerObj(aContentType, aRequest, mLoadGroup,
7623 aContentHandler, getter_AddRefs(viewer));
7624
7625 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
7626 return rv;
7627 }
7628
7629 // Notify the current document that it is about to be unloaded!!
7630 //
7631 // It is important to fire the unload() notification *before* any state
7632 // is changed within the DocShell - otherwise, javascript will get the
7633 // wrong information :-(
7634 //
7635
7636 if (mSavingOldViewer) {
7637 // We determined that it was safe to cache the document presentation
7638 // at the time we initiated the new load. We need to check whether
7639 // it's still safe to do so, since there may have been DOM mutations
7640 // or new requests initiated.
7641 RefPtr<Document> doc = viewer->GetDocument();
7642 mSavingOldViewer = CanSavePresentation(
7643 mLoadType, aRequest, doc, /* aReportBFCacheComboTelemetry */ false);
7644 }
7645
7646 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"
, 7646); MOZ_PretendNoReturn(); } } while (0)
;
7647
7648 nsCOMPtr<nsIChannel> aOpenedChannel = do_QueryInterface(aRequest);
7649 if (aOpenedChannel) {
7650 aOpenedChannel->GetURI(getter_AddRefs(mLoadingURI));
7651 }
7652
7653 // Grab the current URI, we need to pass it to Embed, and OnNewURI will reset
7654 // it before we do call Embed.
7655 nsCOMPtr<nsIURI> previousURI = mCurrentURI;
7656
7657 FirePageHideNotification(!mSavingOldViewer);
7658 if (mIsBeingDestroyed) {
7659 // Force to stop the newly created orphaned viewer.
7660 viewer->Stop();
7661 return NS_ERROR_DOCSHELL_DYING;
7662 }
7663 mLoadingURI = nullptr;
7664
7665 // Set mFiredUnloadEvent = false so that the unload handler for the
7666 // *new* document will fire.
7667 mFiredUnloadEvent = false;
7668
7669 // we've created a new document so go ahead and call
7670 // OnNewURI(), but don't fire OnLocationChange()
7671 // notifications before we've called Embed(). See bug 284993.
7672 mURIResultedInDocument = true;
7673 bool errorOnLocationChangeNeeded = false;
7674 nsCOMPtr<nsIChannel> failedChannel = mFailedChannel;
7675 nsCOMPtr<nsIURI> failedURI;
7676
7677 if (mLoadType == LOAD_ERROR_PAGE) {
7678 // We need to set the SH entry and our current URI here and not
7679 // at the moment we load the page. We want the same behavior
7680 // of Stop() as for a normal page load. See bug 514232 for details.
7681
7682 // Revert mLoadType to load type to state the page load failed,
7683 // following function calls need it.
7684 mLoadType = mFailedLoadType;
7685
7686 Document* doc = viewer->GetDocument();
7687 if (doc) {
7688 doc->SetFailedChannel(failedChannel);
7689 }
7690
7691 nsCOMPtr<nsIPrincipal> triggeringPrincipal;
7692 if (failedChannel) {
7693 // Make sure we have a URI to set currentURI.
7694 NS_GetFinalChannelURI(failedChannel, getter_AddRefs(failedURI));
7695 } else {
7696 // if there is no failed channel we have to explicitly provide
7697 // a triggeringPrincipal for the history entry.
7698 triggeringPrincipal = nsContentUtils::GetSystemPrincipal();
7699 }
7700
7701 if (!failedURI) {
7702 failedURI = mFailedURI;
7703 }
7704 if (!failedURI) {
7705 // We need a URI object to store a session history entry, so make up a URI
7706 NS_NewURI(getter_AddRefs(failedURI), "about:blank");
7707 }
7708
7709 // When we don't have failedURI, something wrong will happen. See
7710 // bug 291876.
7711 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"
, 7711); AnnotateMozCrashReason("MOZ_ASSERT" "(" "failedURI" ") ("
"We don't have a URI for history APIs." ")"); do { *((volatile
int*)__null) = 7711; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
7712
7713 mFailedChannel = nullptr;
7714 mFailedURI = nullptr;
7715
7716 // Create an shistory entry for the old load.
7717 if (failedURI) {
7718 errorOnLocationChangeNeeded =
7719 OnNewURI(failedURI, failedChannel, triggeringPrincipal, nullptr,
7720 nullptr, nullptr, false, false);
7721 }
7722
7723 // Be sure to have a correct mLSHE, it may have been cleared by
7724 // EndPageLoad. See bug 302115.
7725 ChildSHistory* shistory = GetSessionHistory();
7726 if (!mozilla::SessionHistoryInParent() && shistory && !mLSHE) {
7727 int32_t idx = shistory->LegacySHistory()->GetRequestedIndex();
7728 if (idx == -1) {
7729 idx = shistory->Index();
7730 }
7731 shistory->LegacySHistory()->GetEntryAtIndex(idx, getter_AddRefs(mLSHE));
7732 }
7733
7734 mLoadType = LOAD_ERROR_PAGE;
7735 }
7736
7737 nsCOMPtr<nsIURI> finalURI;
7738 // If this a redirect, use the final url (uri)
7739 // else use the original url
7740 //
7741 // Note that this should match what documents do (see Document::Reset).
7742 NS_GetFinalChannelURI(aOpenedChannel, getter_AddRefs(finalURI));
7743
7744 bool onLocationChangeNeeded = false;
7745 if (finalURI) {
7746 // Pass false for aCloneSHChildren, since we're loading a new page here.
7747 onLocationChangeNeeded = OnNewURI(finalURI, aOpenedChannel, nullptr,
7748 nullptr, nullptr, nullptr, true, false);
7749 }
7750
7751 // let's try resetting the load group if we need to...
7752 nsCOMPtr<nsILoadGroup> currentLoadGroup;
7753 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"
, 7755); return NS_ERROR_FAILURE; } } while (false)
7754 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"
, 7755); return NS_ERROR_FAILURE; } } while (false)
7755 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"
, 7755); return NS_ERROR_FAILURE; } } while (false)
;
7756
7757 if (currentLoadGroup != mLoadGroup) {
7758 nsLoadFlags loadFlags = 0;
7759
7760 // Cancel any URIs that are currently loading...
7761 // XXX: Need to do this eventually Stop();
7762 //
7763 // Retarget the document to this loadgroup...
7764 //
7765 /* First attach the channel to the right loadgroup
7766 * and then remove from the old loadgroup. This
7767 * puts the notifications in the right order and
7768 * we don't null-out mLSHE in OnStateChange() for
7769 * all redirected urls
7770 */
7771 aOpenedChannel->SetLoadGroup(mLoadGroup);
7772
7773 // Mark the channel as being a document URI...
7774 aOpenedChannel->GetLoadFlags(&loadFlags);
7775 loadFlags |= nsIChannel::LOAD_DOCUMENT_URI;
7776 nsCOMPtr<nsILoadInfo> loadInfo = aOpenedChannel->LoadInfo();
7777 if (SandboxFlagsImplyCookies(loadInfo->GetSandboxFlags())) {
7778 loadFlags |= nsIRequest::LOAD_DOCUMENT_NEEDS_COOKIE;
7779 }
7780
7781 aOpenedChannel->SetLoadFlags(loadFlags);
7782
7783 mLoadGroup->AddRequest(aRequest, nullptr);
7784 if (currentLoadGroup) {
7785 currentLoadGroup->RemoveRequest(aRequest, nullptr, NS_BINDING_RETARGETED);
7786 }
7787
7788 // Update the notification callbacks, so that progress and
7789 // status information are sent to the right docshell...
7790 aOpenedChannel->SetNotificationCallbacks(this);
7791 }
7792
7793 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"
, 7796); return NS_ERROR_FAILURE; } } while (false)
7794 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"
, 7796); return NS_ERROR_FAILURE; } } while (false)
7795 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"
, 7796); return NS_ERROR_FAILURE; } } while (false)
7796 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"
, 7796); return NS_ERROR_FAILURE; } } while (false)
;
7797
7798 if (!mBrowsingContext->GetHasLoadedNonInitialDocument()) {
7799 MOZ_ALWAYS_SUCCEEDS(mBrowsingContext->SetHasLoadedNonInitialDocument(true))do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(mBrowsingContext->SetHasLoadedNonInitialDocument(true))),
1)))), 1))) { } else { do { do { } while (false); MOZ_ReportCrash
("" "NS_SUCCEEDED(mBrowsingContext->SetHasLoadedNonInitialDocument(true))"
, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 7799); AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED(mBrowsingContext->SetHasLoadedNonInitialDocument(true))"
")"); do { *((volatile int*)__null) = 7799; __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
;
7800 }
7801
7802 mSavedRefreshURIList = nullptr;
7803 mSavingOldViewer = false;
7804 mEODForCurrentDocument = false;
7805
7806 // if this document is part of a multipart document,
7807 // the ID can be used to distinguish it from the other parts.
7808 nsCOMPtr<nsIMultiPartChannel> multiPartChannel(do_QueryInterface(aRequest));
7809 if (multiPartChannel) {
7810 if (PresShell* presShell = GetPresShell()) {
7811 if (Document* doc = presShell->GetDocument()) {
7812 uint32_t partID;
7813 multiPartChannel->GetPartID(&partID);
7814 doc->SetPartID(partID);
7815 }
7816 }
7817 }
7818
7819 if (errorOnLocationChangeNeeded) {
7820 FireOnLocationChange(this, failedChannel, failedURI,
7821 LOCATION_CHANGE_ERROR_PAGE);
7822 } else if (onLocationChangeNeeded) {
7823 uint32_t locationFlags =
7824 (mLoadType & LOAD_CMD_RELOAD) ? uint32_t(LOCATION_CHANGE_RELOAD) : 0;
7825 FireOnLocationChange(this, aRequest, mCurrentURI, locationFlags);
7826 }
7827
7828 return NS_OK;
7829}
7830
7831nsresult nsDocShell::NewDocumentViewerObj(const nsACString& aContentType,
7832 nsIRequest* aRequest,
7833 nsILoadGroup* aLoadGroup,
7834 nsIStreamListener** aContentHandler,
7835 nsIDocumentViewer** aViewer) {
7836 nsCOMPtr<nsIChannel> aOpenedChannel = do_QueryInterface(aRequest);
7837
7838 nsCOMPtr<nsIDocumentLoaderFactory> docLoaderFactory =
7839 nsContentUtils::FindInternalDocumentViewer(aContentType);
7840 if (!docLoaderFactory) {
7841 return NS_ERROR_FAILURE;
7842 }
7843
7844 // Now create an instance of the content viewer nsLayoutDLF makes the
7845 // determination if it should be a "view-source" instead of "view"
7846 nsresult rv = docLoaderFactory->CreateInstance(
7847 "view", aOpenedChannel, aLoadGroup, aContentType, this, nullptr,
7848 aContentHandler, aViewer);
7849 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"
, 7849); return rv; } } while (false)
;
7850
7851 (*aViewer)->SetContainer(this);
7852 return NS_OK;
7853}
7854
7855nsresult nsDocShell::SetupNewViewer(nsIDocumentViewer* aNewViewer,
7856 WindowGlobalChild* aWindowActor) {
7857 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"
, 7857); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mIsBeingDestroyed"
")"); do { *((volatile int*)__null) = 7857; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7858
7859 //
7860 // Copy content viewer state from previous or parent content viewer.
7861 //
7862 // The following logic is mirrored in nsHTMLDocument::StartDocumentLoad!
7863 //
7864 // Do NOT to maintain a reference to the old content viewer outside
7865 // of this "copying" block, or it will not be destroyed until the end of
7866 // this routine and all <SCRIPT>s and event handlers fail! (bug 20315)
7867 //
7868 // In this block of code, if we get an error result, we return it
7869 // but if we get a null pointer, that's perfectly legal for parent
7870 // and parentDocumentViewer.
7871 //
7872
7873 int32_t x = 0;
7874 int32_t y = 0;
7875 int32_t cx = 0;
7876 int32_t cy = 0;
7877
7878 // This will get the size from the current content viewer or from the
7879 // Init settings
7880 DoGetPositionAndSize(&x, &y, &cx, &cy);
7881
7882 nsCOMPtr<nsIDocShellTreeItem> parentAsItem;
7883 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"
, 7884); return NS_ERROR_FAILURE; } } while (false)
7884 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"
, 7884); return NS_ERROR_FAILURE; } } while (false)
;
7885 nsCOMPtr<nsIDocShell> parent(do_QueryInterface(parentAsItem));
7886
7887 const Encoding* reloadEncoding = nullptr;
7888 int32_t reloadEncodingSource = kCharsetUninitialized;
7889 // |newMUDV| also serves as a flag to set the data from the above vars
7890 nsCOMPtr<nsIDocumentViewer> newViewer;
7891
7892 if (mDocumentViewer || parent) {
7893 nsCOMPtr<nsIDocumentViewer> oldViewer;
7894 if (mDocumentViewer) {
7895 // Get any interesting state from old content viewer
7896 // XXX: it would be far better to just reuse the document viewer ,
7897 // since we know we're just displaying the same document as before
7898 oldViewer = mDocumentViewer;
7899
7900 // Tell the old content viewer to hibernate in session history when
7901 // it is destroyed.
7902
7903 if (mSavingOldViewer && NS_FAILED(CaptureState())((bool)(__builtin_expect(!!(NS_FAILED_impl(CaptureState())), 0
)))
) {
7904 if (mOSHE) {
7905 mOSHE->SyncPresentationState();
7906 }
7907 mSavingOldViewer = false;
7908 }
7909 } else {
7910 // No old content viewer, so get state from parent's content viewer
7911 parent->GetDocViewer(getter_AddRefs(oldViewer));
7912 }
7913
7914 if (oldViewer) {
7915 newViewer = aNewViewer;
7916 if (newViewer) {
7917 reloadEncoding =
7918 oldViewer->GetReloadEncodingAndSource(&reloadEncodingSource);
7919 }
7920 }
7921 }
7922
7923 nscolor bgcolor = NS_RGBA(0, 0, 0, 0)((nscolor)(((0) << 24) | ((0) << 16) | ((0) <<
8) | (0)))
;
7924 bool isUnderHiddenEmbedderElement = false;
7925 // Ensure that the content viewer is destroyed *after* the GC - bug 71515
7926 nsCOMPtr<nsIDocumentViewer> viewer = mDocumentViewer;
7927 if (viewer) {
7928 // Stop any activity that may be happening in the old document before
7929 // releasing it...
7930 viewer->Stop();
7931
7932 // Try to extract the canvas background color from the old
7933 // presentation shell, so we can use it for the next document.
7934 if (PresShell* presShell = viewer->GetPresShell()) {
7935 bgcolor = presShell->GetCanvasBackground();
7936 isUnderHiddenEmbedderElement = presShell->IsUnderHiddenEmbedderElement();
7937 }
7938
7939 viewer->Close(mSavingOldViewer ? mOSHE.get() : nullptr);
7940 aNewViewer->SetPreviousViewer(viewer);
7941 }
7942 if (mOSHE && (!mDocumentViewer || !mSavingOldViewer)) {
7943 // We don't plan to save a viewer in mOSHE; tell it to drop
7944 // any other state it's holding.
7945 mOSHE->SyncPresentationState();
7946 }
7947
7948 mDocumentViewer = nullptr;
7949
7950 // Now that we're about to switch documents, forget all of our children.
7951 // Note that we cached them as needed up in CaptureState above.
7952 DestroyChildren();
7953
7954 mDocumentViewer = aNewViewer;
7955
7956 nsCOMPtr<nsIWidget> widget;
7957 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"
, 7957); return NS_ERROR_FAILURE; } } while (false)
;
7958
7959 LayoutDeviceIntRect bounds(x, y, cx, cy);
7960
7961 mDocumentViewer->SetNavigationTiming(mTiming);
7962
7963 if (NS_FAILED(mDocumentViewer->Init(widget, bounds, aWindowActor))((bool)(__builtin_expect(!!(NS_FAILED_impl(mDocumentViewer->
Init(widget, bounds, aWindowActor))), 0)))
) {
7964 nsCOMPtr<nsIDocumentViewer> viewer = mDocumentViewer;
7965 viewer->Close(nullptr);
7966 viewer->Destroy();
7967 mDocumentViewer = nullptr;
7968 SetCurrentURIInternal(nullptr);
7969 NS_WARNING("DocumentViewer Initialization failed")NS_DebugBreak(NS_DEBUG_WARNING, "DocumentViewer Initialization failed"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 7969)
;
7970 return NS_ERROR_FAILURE;
7971 }
7972
7973 // If we have old state to copy, set the old state onto the new content
7974 // viewer
7975 if (newViewer) {
7976 newViewer->SetReloadEncodingAndSource(reloadEncoding, reloadEncodingSource);
7977 }
7978
7979 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"
, 7979); return NS_ERROR_FAILURE; } } while (false)
;
7980
7981 // Stuff the bgcolor from the old pres shell into the new
7982 // pres shell. This improves page load continuity.
7983 if (RefPtr<PresShell> presShell = mDocumentViewer->GetPresShell()) {
7984 presShell->SetCanvasBackground(bgcolor);
7985 presShell->ActivenessMaybeChanged();
7986 if (isUnderHiddenEmbedderElement) {
7987 presShell->SetIsUnderHiddenEmbedderElement(isUnderHiddenEmbedderElement);
7988 }
7989 }
7990
7991 // XXX: It looks like the LayoutState gets restored again in Embed()
7992 // right after the call to SetupNewViewer(...)
7993
7994 // We don't show the mDocumentViewer yet, since we want to draw the old page
7995 // until we have enough of the new page to show. Just return with the new
7996 // viewer still set to hidden.
7997
7998 return NS_OK;
7999}
8000
8001void nsDocShell::SetDocCurrentStateObj(nsISHEntry* aShEntry,
8002 SessionHistoryInfo* aInfo) {
8003 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"
, 8003); return; } } while (false)
;
8004
8005 RefPtr<Document> document = GetDocument();
8006 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"
, 8006); return; } } while (false)
;
8007
8008 nsCOMPtr<nsIStructuredCloneContainer> scContainer;
8009 if (mozilla::SessionHistoryInParent()) {
8010 // If aInfo is null, just set the document's state object to null.
8011 if (aInfo) {
8012 scContainer = aInfo->GetStateData();
8013 }
8014 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)
8015 ("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)
;
8016 } else {
8017 if (aShEntry) {
8018 scContainer = aShEntry->GetStateData();
8019
8020 // If aShEntry is null, just set the document's state object to null.
8021 }
8022 }
8023
8024 // It's OK for scContainer too be null here; that just means there's no
8025 // state data associated with this history entry.
8026 document->SetStateObject(scContainer);
8027}
8028
8029nsresult nsDocShell::CheckLoadingPermissions() {
8030 // This method checks whether the caller may load content into
8031 // this docshell. Even though we've done our best to hide windows
8032 // from code that doesn't have the right to access them, it's
8033 // still possible for an evil site to open a window and access
8034 // frames in the new window through window.frames[] (which is
8035 // allAccess for historic reasons), so we still need to do this
8036 // check on load.
8037 nsresult rv = NS_OK;
8038
8039 if (!IsSubframe()) {
8040 // We're not a frame. Permit all loads.
8041 return rv;
8042 }
8043
8044 // Note - The check for a current JSContext here isn't necessarily sensical.
8045 // It's just designed to preserve the old semantics during a mass-conversion
8046 // patch.
8047 if (!nsContentUtils::GetCurrentJSContext()) {
8048 return NS_OK;
8049 }
8050
8051 // Check if the caller is from the same origin as this docshell,
8052 // or any of its ancestors.
8053 nsIPrincipal* subjectPrincipal = nsContentUtils::SubjectPrincipal();
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 // file: URIs are considered the same domain for the purpose of frame
8073 // navigation by clicking a targeted link, regardless of script
8074 // accessibility (bug 1934807).
8075 if (subjectPrincipal->Subsumes(p) ||
8076 (subjectPrincipal->SchemeIs("file") && p->SchemeIs("file"))) {
8077 // Same origin, permit load
8078 return NS_OK;
8079 }
8080 }
8081
8082 return NS_ERROR_DOM_PROP_ACCESS_DENIED;
8083}
8084
8085//*****************************************************************************
8086// nsDocShell: Site Loading
8087//*****************************************************************************
8088
8089void nsDocShell::CopyFavicon(nsIURI* aOldURI, nsIURI* aNewURI,
8090 bool aInPrivateBrowsing) {
8091 if (XRE_IsContentProcess()) {
8092 dom::ContentChild* contentChild = dom::ContentChild::GetSingleton();
8093 if (contentChild) {
8094 contentChild->SendCopyFavicon(aOldURI, aNewURI, aInPrivateBrowsing);
8095 }
8096 return;
8097 }
8098
8099#ifdef MOZ_PLACES1
8100 nsCOMPtr<nsIFaviconService> favSvc =
8101 do_GetService("@mozilla.org/browser/favicon-service;1");
8102 if (favSvc) {
8103 favSvc->CopyFavicons(aOldURI, aNewURI,
8104 aInPrivateBrowsing
8105 ? nsIFaviconService::FAVICON_LOAD_PRIVATE
8106 : nsIFaviconService::FAVICON_LOAD_NON_PRIVATE,
8107 nullptr);
8108 }
8109#endif
8110}
8111
8112class InternalLoadEvent : public Runnable {
8113 public:
8114 InternalLoadEvent(nsDocShell* aDocShell, nsDocShellLoadState* aLoadState)
8115 : mozilla::Runnable("InternalLoadEvent"),
8116 mDocShell(aDocShell),
8117 mLoadState(aLoadState) {
8118 // For events, both target and filename should be the version of "null" they
8119 // expect. By the time the event is fired, both window targeting and file
8120 // downloading have been handled, so we should never have an internal load
8121 // event that retargets or had a download.
8122 mLoadState->SetTarget(u""_ns);
8123 mLoadState->SetFileName(VoidString());
8124 }
8125
8126 NS_IMETHODvirtual nsresult
8127 Run() override {
8128#ifndef ANDROID
8129 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"
, 8130); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mLoadState->TriggeringPrincipal()"
") (" "InternalLoadEvent: Should always have a principal here"
")"); do { *((volatile int*)__null) = 8130; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
8130 "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"
, 8130); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mLoadState->TriggeringPrincipal()"
") (" "InternalLoadEvent: Should always have a principal here"
")"); do { *((volatile int*)__null) = 8130; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8131#endif
8132 return mDocShell->InternalLoad(mLoadState);
8133 }
8134
8135 private:
8136 RefPtr<nsDocShell> mDocShell;
8137 RefPtr<nsDocShellLoadState> mLoadState;
8138};
8139
8140/**
8141 * Returns true if we started an asynchronous load (i.e., from the network), but
8142 * the document we're loading there hasn't yet become this docshell's active
8143 * document.
8144 *
8145 * When JustStartedNetworkLoad is true, you should be careful about modifying
8146 * mLoadType and mLSHE. These are both set when the asynchronous load first
8147 * starts, and the load expects that, when it eventually runs InternalLoad,
8148 * mLoadType and mLSHE will have their original values.
8149 */
8150bool nsDocShell::JustStartedNetworkLoad() {
8151 return mDocumentRequest && mDocumentRequest != GetCurrentDocChannel();
8152}
8153
8154// The contentType will be INTERNAL_(I)FRAME if this docshell is for a
8155// non-toplevel browsing context in spec terms. (frame, iframe, <object>,
8156// <embed>, etc)
8157//
8158// This return value will be used when we call NS_CheckContentLoadPolicy, and
8159// later when we call DoURILoad.
8160nsContentPolicyType nsDocShell::DetermineContentType() {
8161 if (!IsSubframe()) {
8162 return nsIContentPolicy::TYPE_DOCUMENT;
8163 }
8164
8165 const auto& maybeEmbedderElementType =
8166 GetBrowsingContext()->GetEmbedderElementType();
8167 if (!maybeEmbedderElementType) {
8168 // If the EmbedderElementType hasn't been set yet, just assume we're
8169 // an iframe since that's more common.
8170 return nsIContentPolicy::TYPE_INTERNAL_IFRAME;
8171 }
8172
8173 return maybeEmbedderElementType->EqualsLiteral("iframe")
8174 ? nsIContentPolicy::TYPE_INTERNAL_IFRAME
8175 : nsIContentPolicy::TYPE_INTERNAL_FRAME;
8176}
8177
8178bool nsDocShell::NoopenerForceEnabled() {
8179 // If current's top-level browsing context's active document's
8180 // cross-origin-opener-policy is "same-origin" or "same-origin + COEP" then
8181 // if currentDoc's origin is not same origin with currentDoc's top-level
8182 // origin, noopener is force enabled, and name is cleared to "_blank".
8183 auto topPolicy = mBrowsingContext->Top()->GetOpenerPolicy();
8184 return (topPolicy == nsILoadInfo::OPENER_POLICY_SAME_ORIGIN ||
8185 topPolicy ==
8186 nsILoadInfo::
8187 OPENER_POLICY_SAME_ORIGIN_EMBEDDER_POLICY_REQUIRE_CORP) &&
8188 !mBrowsingContext->SameOriginWithTop();
8189}
8190
8191nsresult nsDocShell::PerformRetargeting(nsDocShellLoadState* aLoadState) {
8192 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"
, 8192); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState"
") (" "need a load state!" ")"); do { *((volatile int*)__null
) = 8192; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
;
8193 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"
, 8193); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aLoadState->Target().IsEmpty()"
") (" "should have a target here!" ")"); do { *((volatile int
*)__null) = 8193; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
8194 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"
, 8195); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->TargetBrowsingContext().IsNull()"
") (" "should not have picked target yet" ")"); do { *((volatile
int*)__null) = 8195; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
8195 "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"
, 8195); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->TargetBrowsingContext().IsNull()"
") (" "should not have picked target yet" ")"); do { *((volatile
int*)__null) = 8195; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
8196
8197 nsresult rv = NS_OK;
8198 RefPtr<BrowsingContext> targetContext;
8199
8200 // Only _self, _parent, and _top are supported in noopener case. But we
8201 // have to be careful to not apply that to the noreferrer case. See bug
8202 // 1358469.
8203 bool allowNamedTarget =
8204 !aLoadState->HasInternalLoadFlags(INTERNAL_LOAD_FLAGS_NO_OPENER) ||
8205 aLoadState->HasInternalLoadFlags(INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER);
8206 if (allowNamedTarget ||
8207 aLoadState->Target().LowerCaseEqualsLiteral("_self") ||
8208 aLoadState->Target().LowerCaseEqualsLiteral("_parent") ||
8209 aLoadState->Target().LowerCaseEqualsLiteral("_top")) {
8210 Document* document = GetDocument();
8211 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"
, 8211); return NS_ERROR_FAILURE; } } while (false)
;
8212 WindowGlobalChild* wgc = document->GetWindowGlobalChild();
8213 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"
, 8213); return NS_ERROR_FAILURE; } } while (false)
;
8214 targetContext = wgc->FindBrowsingContextWithName(
8215 aLoadState->Target(), /* aUseEntryGlobalForAccessCheck */ false);
8216 }
8217
8218 if (!targetContext) {
8219 // If the targetContext doesn't exist, then this is a new docShell and we
8220 // should consider this a TYPE_DOCUMENT load
8221 //
8222 // For example, when target="_blank"
8223
8224 // If there's no targetContext, that means we are about to create a new
8225 // window. Perform a content policy check before creating the window. Please
8226 // note for all other docshell loads content policy checks are performed
8227 // within the contentSecurityManager when the channel is about to be
8228 // openend.
8229 nsISupports* requestingContext = nullptr;
8230 if (XRE_IsContentProcess()) {
8231 // In e10s the child process doesn't have access to the element that
8232 // contains the browsing context (because that element is in the chrome
8233 // process). So we just pass mScriptGlobal.
8234 requestingContext = ToSupports(mScriptGlobal);
8235 } else {
8236 // This is for loading non-e10s tabs and toplevel windows of various
8237 // sorts.
8238 // For the toplevel window cases, requestingElement will be null.
8239 nsCOMPtr<Element> requestingElement =
8240 mScriptGlobal->GetFrameElementInternal();
8241 requestingContext = requestingElement;
8242 }
8243
8244 // Ideally we should use the same loadinfo as within DoURILoad which
8245 // should match this one when both are applicable.
8246 nsCOMPtr<nsILoadInfo> secCheckLoadInfo =
8247 new LoadInfo(mScriptGlobal, aLoadState->URI(),
8248 aLoadState->TriggeringPrincipal(), requestingContext,
8249 nsILoadInfo::SEC_ONLY_FOR_EXPLICIT_CONTENTSEC_CHECK, 0);
8250
8251 // Since Content Policy checks are performed within docShell as well as
8252 // the ContentSecurityManager we need a reliable way to let certain
8253 // nsIContentPolicy consumers ignore duplicate calls.
8254 secCheckLoadInfo->SetSkipContentPolicyCheckForWebRequest(true);
8255
8256 int16_t shouldLoad = nsIContentPolicy::ACCEPT;
8257 rv = NS_CheckContentLoadPolicy(aLoadState->URI(), secCheckLoadInfo,
8258 &shouldLoad);
8259
8260 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) || NS_CP_REJECTED(shouldLoad)((shouldLoad) != nsIContentPolicy::ACCEPT)) {
8261 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
8262 if (shouldLoad == nsIContentPolicy::REJECT_TYPE) {
8263 return NS_ERROR_CONTENT_BLOCKED_SHOW_ALT;
8264 }
8265 if (shouldLoad == nsIContentPolicy::REJECT_POLICY) {
8266 return NS_ERROR_BLOCKED_BY_POLICY;
8267 }
8268 }
8269
8270 return NS_ERROR_CONTENT_BLOCKED;
8271 }
8272 }
8273
8274 //
8275 // Resolve the window target before going any further...
8276 // If the load has been targeted to another DocShell, then transfer the
8277 // load to it...
8278 //
8279
8280 // We've already done our owner-inheriting. Mask out that bit, so we
8281 // don't try inheriting an owner from the target window if we came up
8282 // with a null owner above.
8283 aLoadState->UnsetInternalLoadFlag(INTERNAL_LOAD_FLAGS_INHERIT_PRINCIPAL);
8284
8285 if (!targetContext) {
8286 // If the docshell's document is sandboxed, only open a new window
8287 // if the document's SANDBOXED_AUXILLARY_NAVIGATION flag is not set.
8288 // (i.e. if allow-popups is specified)
8289 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"
, 8289); return NS_ERROR_FAILURE; } } while (false)
;
8290 Document* doc = mDocumentViewer->GetDocument();
8291
8292 const bool isDocumentAuxSandboxed =
8293 doc && (doc->GetSandboxFlags() & SANDBOXED_AUXILIARY_NAVIGATION);
8294
8295 if (isDocumentAuxSandboxed) {
8296 return NS_ERROR_DOM_INVALID_ACCESS_ERR;
8297 }
8298
8299 nsCOMPtr<nsPIDOMWindowOuter> win = GetWindow();
8300 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"
, 8300); return NS_ERROR_NOT_AVAILABLE; } } while (false)
;
8301
8302 RefPtr<BrowsingContext> newBC;
8303 nsAutoCString spec;
8304 aLoadState->URI()->GetSpec(spec);
8305
8306 // If we are a noopener load, we just hand the whole thing over to our
8307 // window.
8308 if (aLoadState->HasInternalLoadFlags(INTERNAL_LOAD_FLAGS_NO_OPENER) ||
8309 NoopenerForceEnabled()) {
8310 // Various asserts that we know to hold because NO_OPENER loads can only
8311 // happen for links.
8312 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"
, 8312); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aLoadState->LoadReplace()"
")"); do { *((volatile int*)__null) = 8312; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8313 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"
, 8314); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->PrincipalToInherit() == aLoadState->TriggeringPrincipal()"
")"); do { *((volatile int*)__null) = 8314; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
8314 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"
, 8314); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->PrincipalToInherit() == aLoadState->TriggeringPrincipal()"
")"); do { *((volatile int*)__null) = 8314; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8315 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"
, 8319); 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) = 8319; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
8316 ~(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"
, 8319); 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) = 8319; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
8317 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"
, 8319); 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) = 8319; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
8318 "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"
, 8319); 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) = 8319; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
8319 "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"
, 8319); 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) = 8319; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8320 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"
, 8321); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->IsFormSubmission()"
")"); do { *((volatile int*)__null) = 8321; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
8321 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"
, 8321); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->IsFormSubmission()"
")"); do { *((volatile int*)__null) = 8321; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
8322 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"
, 8322); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aLoadState->HeadersStream()"
")"); do { *((volatile int*)__null) = 8322; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8323 // If OnLinkClickSync was invoked inside the onload handler, the load
8324 // type would be set to LOAD_NORMAL_REPLACE; otherwise it should be
8325 // LOAD_LINK.
8326 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"
, 8327); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->LoadType() == LOAD_LINK || aLoadState->LoadType() == LOAD_NORMAL_REPLACE"
")"); do { *((volatile int*)__null) = 8327; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
8327 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"
, 8327); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->LoadType() == LOAD_LINK || aLoadState->LoadType() == LOAD_NORMAL_REPLACE"
")"); do { *((volatile int*)__null) = 8327; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8328 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"
, 8328); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aLoadState->LoadIsFromSessionHistory()"
")"); do { *((volatile int*)__null) = 8328; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8329 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"
, 8329); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->FirstParty()"
")"); do { *((volatile int*)__null) = 8329; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
; // Windowwatcher will assume this.
8330
8331 RefPtr<nsDocShellLoadState> loadState =
8332 new nsDocShellLoadState(aLoadState->URI());
8333
8334 // Set up our loadinfo so it will do the load as much like we would have
8335 // as possible.
8336 loadState->SetReferrerInfo(aLoadState->GetReferrerInfo());
8337 loadState->SetOriginalURI(aLoadState->OriginalURI());
8338
8339 Maybe<nsCOMPtr<nsIURI>> resultPrincipalURI;
8340 aLoadState->GetMaybeResultPrincipalURI(resultPrincipalURI);
8341
8342 loadState->SetMaybeResultPrincipalURI(resultPrincipalURI);
8343 loadState->SetKeepResultPrincipalURIIfSet(
8344 aLoadState->KeepResultPrincipalURIIfSet());
8345 // LoadReplace will always be false due to asserts above, skip setting
8346 // it.
8347 loadState->SetTriggeringPrincipal(aLoadState->TriggeringPrincipal());
8348 loadState->SetTriggeringSandboxFlags(
8349 aLoadState->TriggeringSandboxFlags());
8350 loadState->SetTriggeringWindowId(aLoadState->TriggeringWindowId());
8351 loadState->SetTriggeringStorageAccess(
8352 aLoadState->TriggeringStorageAccess());
8353 loadState->SetCsp(aLoadState->Csp());
8354 loadState->SetInheritPrincipal(aLoadState->HasInternalLoadFlags(
8355 INTERNAL_LOAD_FLAGS_INHERIT_PRINCIPAL));
8356 // Explicit principal because we do not want any guesses as to what the
8357 // principal to inherit is: it should be aTriggeringPrincipal.
8358 loadState->SetPrincipalIsExplicit(true);
8359 loadState->SetLoadType(aLoadState->LoadType());
8360 loadState->SetForceAllowDataURI(aLoadState->HasInternalLoadFlags(
8361 INTERNAL_LOAD_FLAGS_FORCE_ALLOW_DATA_URI));
8362
8363 loadState->SetHasValidUserGestureActivation(
8364 aLoadState->HasValidUserGestureActivation());
8365
8366 loadState->SetTextDirectiveUserActivation(
8367 aLoadState->GetTextDirectiveUserActivation());
8368
8369 // Propagate POST data to the new load.
8370 loadState->SetPostDataStream(aLoadState->PostDataStream());
8371 loadState->SetIsFormSubmission(aLoadState->IsFormSubmission());
8372
8373 rv = win->Open(spec,
8374 aLoadState->Target(), // window name
8375 u""_ns, // Features
8376 loadState,
8377 true, // aForceNoOpener
8378 getter_AddRefs(newBC));
8379 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"
, 8379); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!newBC" ")"
); do { *((volatile int*)__null) = 8379; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8380 return rv;
8381 }
8382
8383 rv = win->OpenNoNavigate(spec,
8384 aLoadState->Target(), // window name
8385 u""_ns, // Features
8386 getter_AddRefs(newBC));
8387
8388 // In some cases the Open call doesn't actually result in a new
8389 // window being opened. We can detect these cases by examining the
8390 // document in |newBC|, if any.
8391 nsCOMPtr<nsPIDOMWindowOuter> piNewWin =
8392 newBC ? newBC->GetDOMWindow() : nullptr;
8393 if (piNewWin) {
8394 RefPtr<Document> newDoc = piNewWin->GetExtantDoc();
8395 if (!newDoc || newDoc->IsInitialDocument()) {
8396 aLoadState->SetInternalLoadFlag(INTERNAL_LOAD_FLAGS_FIRST_LOAD);
8397 }
8398 }
8399
8400 if (newBC) {
8401 targetContext = newBC;
8402 }
8403 }
8404 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"
, 8404); return rv; } } while (false)
;
8405 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"
, 8405); return rv; } } while (false)
;
8406
8407 // If our target BrowsingContext is still pending initialization, ignore the
8408 // navigation request targeting it.
8409 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"
, 8409)
) {
8410 return NS_OK;
8411 }
8412
8413 aLoadState->SetTargetBrowsingContext(targetContext);
8414 if (aLoadState->IsFormSubmission()) {
8415 aLoadState->SetLoadType(
8416 GetLoadTypeForFormSubmission(targetContext, aLoadState));
8417 }
8418
8419 //
8420 // Transfer the load to the target BrowsingContext... Clear the window target
8421 // name to the empty string to prevent recursive retargeting!
8422 //
8423 // No window target
8424 aLoadState->SetTarget(u""_ns);
8425 // No forced download
8426 aLoadState->SetFileName(VoidString());
8427 return targetContext->InternalLoad(aLoadState);
8428}
8429
8430static nsAutoCString RefMaybeNull(nsIURI* aURI) {
8431 nsAutoCString result;
8432 if (NS_FAILED(aURI->GetRef(result))((bool)(__builtin_expect(!!(NS_FAILED_impl(aURI->GetRef(result
))), 0)))
) {
8433 result.SetIsVoid(true);
8434 }
8435 return result;
8436}
8437
8438uint32_t nsDocShell::GetSameDocumentNavigationFlags(nsIURI* aNewURI) {
8439 uint32_t flags = LOCATION_CHANGE_SAME_DOCUMENT;
8440
8441 bool equal = false;
8442 if (mCurrentURI &&
8443 NS_SUCCEEDED(mCurrentURI->EqualsExceptRef(aNewURI, &equal))((bool)(__builtin_expect(!!(!NS_FAILED_impl(mCurrentURI->EqualsExceptRef
(aNewURI, &equal))), 1)))
&& equal &&
8444 RefMaybeNull(mCurrentURI) != RefMaybeNull(aNewURI)) {
8445 flags |= LOCATION_CHANGE_HASHCHANGE;
8446 }
8447
8448 return flags;
8449}
8450
8451struct SameDocumentNavigationState {
8452 nsAutoCString mCurrentHash;
8453 nsAutoCString mNewHash;
8454 nsTArray<TextDirective> mTextDirectives;
8455 bool mCurrentURIHasRef = false;
8456 bool mNewURIHasRef = false;
8457 bool mSameExceptHashes = false;
8458 bool mSecureUpgradeURI = false;
8459 bool mHistoryNavBetweenSameDoc = false;
8460};
8461
8462bool nsDocShell::IsSameDocumentNavigation(nsDocShellLoadState* aLoadState,
8463 SameDocumentNavigationState& aState) {
8464 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"
, 8464); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState"
")"); do { *((volatile int*)__null) = 8464; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8465 if (!(aLoadState->LoadType() == LOAD_NORMAL ||
8466 aLoadState->LoadType() == LOAD_STOP_CONTENT ||
8467 LOAD_TYPE_HAS_FLAGS(aLoadState->LoadType(),((aLoadState->LoadType()) & ((LOAD_FLAGS_REPLACE_HISTORY
) << 16))
8468 LOAD_FLAGS_REPLACE_HISTORY)((aLoadState->LoadType()) & ((LOAD_FLAGS_REPLACE_HISTORY
) << 16))
||
8469 aLoadState->LoadType() == LOAD_HISTORY ||
8470 aLoadState->LoadType() == LOAD_LINK)) {
8471 return false;
8472 }
8473
8474 nsCOMPtr<nsIURI> currentURI = mCurrentURI;
8475
8476 nsresult rvURINew = aLoadState->URI()->GetRef(aState.mNewHash);
8477 if (NS_SUCCEEDED(rvURINew)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rvURINew)), 1)))) {
8478 rvURINew = aLoadState->URI()->GetHasRef(&aState.mNewURIHasRef);
8479 }
8480
8481 // A Fragment Directive must be removed from the new hash in order to allow
8482 // fallback element id scroll.
8483 FragmentDirective::ParseAndRemoveFragmentDirectiveFromFragmentString(
8484 aState.mNewHash, &aState.mTextDirectives, aLoadState->URI());
8485
8486 if (currentURI && NS_SUCCEEDED(rvURINew)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rvURINew)), 1)))) {
8487 nsresult rvURIOld = currentURI->GetRef(aState.mCurrentHash);
8488 if (NS_SUCCEEDED(rvURIOld)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rvURIOld)), 1)))) {
8489 rvURIOld = currentURI->GetHasRef(&aState.mCurrentURIHasRef);
8490 }
8491 if (NS_SUCCEEDED(rvURIOld)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rvURIOld)), 1)))) {
8492 if (NS_FAILED(currentURI->EqualsExceptRef(aLoadState->URI(),((bool)(__builtin_expect(!!(NS_FAILED_impl(currentURI->EqualsExceptRef
(aLoadState->URI(), &aState.mSameExceptHashes))), 0)))
8493 &aState.mSameExceptHashes))((bool)(__builtin_expect(!!(NS_FAILED_impl(currentURI->EqualsExceptRef
(aLoadState->URI(), &aState.mSameExceptHashes))), 0)))
) {
8494 aState.mSameExceptHashes = false;
8495 }
8496 }
8497 }
8498
8499 if (!aState.mSameExceptHashes && currentURI && NS_SUCCEEDED(rvURINew)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rvURINew)), 1)))) {
8500 // Maybe aLoadState->URI() came from the exposable form of currentURI?
8501 nsCOMPtr<nsIURI> currentExposableURI =
8502 nsIOService::CreateExposableURI(currentURI);
8503 nsresult rvURIOld = currentExposableURI->GetRef(aState.mCurrentHash);
8504 if (NS_SUCCEEDED(rvURIOld)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rvURIOld)), 1)))) {
8505 rvURIOld = currentExposableURI->GetHasRef(&aState.mCurrentURIHasRef);
8506 }
8507 if (NS_SUCCEEDED(rvURIOld)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rvURIOld)), 1)))) {
8508 if (NS_FAILED(currentExposableURI->EqualsExceptRef(((bool)(__builtin_expect(!!(NS_FAILED_impl(currentExposableURI
->EqualsExceptRef( aLoadState->URI(), &aState.mSameExceptHashes
))), 0)))
8509 aLoadState->URI(), &aState.mSameExceptHashes))((bool)(__builtin_expect(!!(NS_FAILED_impl(currentExposableURI
->EqualsExceptRef( aLoadState->URI(), &aState.mSameExceptHashes
))), 0)))
) {
8510 aState.mSameExceptHashes = false;
8511 }
8512 // HTTPS-Only Mode upgrades schemes from http to https in Necko, hence we
8513 // have to perform a special check here to avoid an actual navigation. If
8514 // HTTPS-Only Mode is enabled and the two URIs are same-origin (modulo the
8515 // fact that the new URI is currently http), then set mSameExceptHashes to
8516 // true and only perform a fragment navigation.
8517 if (!aState.mSameExceptHashes) {
8518 if (nsCOMPtr<nsIChannel> docChannel = GetCurrentDocChannel()) {
8519 nsCOMPtr<nsILoadInfo> docLoadInfo = docChannel->LoadInfo();
8520 if (!docLoadInfo->GetLoadErrorPage() &&
8521 nsHTTPSOnlyUtils::ShouldUpgradeConnection(docLoadInfo) &&
8522 nsHTTPSOnlyUtils::IsHttpDowngrade(currentExposableURI,
8523 aLoadState->URI())) {
8524 uint32_t status = docLoadInfo->GetHttpsOnlyStatus();
8525 if (status & (nsILoadInfo::HTTPS_ONLY_UPGRADED_LISTENER_REGISTERED |
8526 nsILoadInfo::HTTPS_ONLY_UPGRADED_HTTPS_FIRST)) {
8527 // At this point the requested URI is for sure a fragment
8528 // navigation via HTTP and HTTPS-Only mode or HTTPS-First is
8529 // enabled. Also it is not interfering the upgrade order of
8530 // https://searchfox.org/mozilla-central/source/netwerk/base/nsNetUtil.cpp#2948-2953.
8531 // Since we are on an HTTPS site the fragment
8532 // navigation should also be an HTTPS.
8533 // For that reason we should upgrade the URI to HTTPS.
8534 aState.mSecureUpgradeURI = true;
8535 aState.mSameExceptHashes = true;
8536 }
8537 }
8538 }
8539 }
8540 }
8541 }
8542
8543 if (mozilla::SessionHistoryInParent()) {
8544 if (mActiveEntry && aLoadState->LoadIsFromSessionHistory()) {
8545 aState.mHistoryNavBetweenSameDoc = mActiveEntry->SharesDocumentWith(
8546 aLoadState->GetLoadingSessionHistoryInfo()->mInfo);
8547 }
8548 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)
8549 ("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)
8550 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)
;
8551 } else {
8552 if (mOSHE && aLoadState->LoadIsFromSessionHistory()) {
8553 // We're doing a history load.
8554
8555 mOSHE->SharesDocumentWith(aLoadState->SHEntry(),
8556 &aState.mHistoryNavBetweenSameDoc);
8557 }
8558 }
8559
8560 // A same document navigation happens when we navigate between two SHEntries
8561 // for the same document. We do a same document navigation under two
8562 // circumstances. Either
8563 //
8564 // a) we're navigating between two different SHEntries which share a
8565 // document, or
8566 //
8567 // b) we're navigating to a new shentry whose URI differs from the
8568 // current URI only in its hash, the new hash is non-empty, and
8569 // we're not doing a POST.
8570 //
8571 // The restriction that the SHEntries in (a) must be different ensures
8572 // that history.go(0) and the like trigger full refreshes, rather than
8573 // same document navigations.
8574 if (!mozilla::SessionHistoryInParent()) {
8575 bool doSameDocumentNavigation =
8576 (aState.mHistoryNavBetweenSameDoc && mOSHE != aLoadState->SHEntry()) ||
8577 (!aLoadState->SHEntry() && !aLoadState->PostDataStream() &&
8578 aState.mSameExceptHashes && aState.mNewURIHasRef);
8579 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)
8580 ("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)
8581 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)
;
8582 return doSameDocumentNavigation;
8583 }
8584
8585 if (aState.mHistoryNavBetweenSameDoc &&
8586 !aLoadState->GetLoadingSessionHistoryInfo()->mLoadingCurrentEntry) {
8587 return true;
8588 }
8589
8590 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)
8591 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)
8592 ("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)
8593 "!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)
8594 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)
8595 !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)
8596 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)
8597 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)
;
8598 return !aLoadState->LoadIsFromSessionHistory() &&
8599 !aLoadState->PostDataStream() && aState.mSameExceptHashes &&
8600 aState.mNewURIHasRef;
8601}
8602
8603nsresult nsDocShell::HandleSameDocumentNavigation(
8604 nsDocShellLoadState* aLoadState, SameDocumentNavigationState& aState,
8605 bool& aSameDocument) {
8606 aSameDocument = true;
8607#ifdef DEBUG1
8608 SameDocumentNavigationState state;
8609 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"
, 8609); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsSameDocumentNavigation(aLoadState, state)"
")"); do { *((volatile int*)__null) = 8609; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8610#endif
8611
8612 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)
8613 ("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)
8614 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)
8615 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)
;
8616
8617 RefPtr<Document> doc = GetDocument();
8618 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"
, 8618); return NS_ERROR_FAILURE; } } while (false)
;
8619 doc->DoNotifyPossibleTitleChange();
8620
8621 // Store the pending uninvoked directives if it is a same document navigation.
8622 // We need to set it here, in case the navigation happens before the document
8623 // has actually finished loading.
8624 doc->FragmentDirective()->SetTextDirectives(
8625 std::move(aState.mTextDirectives));
8626
8627 nsCOMPtr<nsIURI> currentURI = mCurrentURI;
8628
8629 // We need to upgrade the new URI from http: to https:
8630 nsCOMPtr<nsIURI> newURI = aLoadState->URI();
8631 if (aState.mSecureUpgradeURI) {
8632 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)
;
8633 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)
8634 ("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)
;
8635 }
8636
8637 if (StaticPrefs::dom_security_setdocumenturi()) {
8638 // check if aLoadState->URI(), principalURI, mCurrentURI are same origin
8639 // skip handling otherwise
8640 nsCOMPtr<nsIPrincipal> origPrincipal = doc->NodePrincipal();
8641 nsCOMPtr<nsIURI> principalURI = origPrincipal->GetURI();
8642 if (origPrincipal->GetIsNullPrincipal()) {
8643 nsCOMPtr<nsIPrincipal> precursor = origPrincipal->GetPrecursorPrincipal();
8644 if (precursor) {
8645 principalURI = precursor->GetURI();
8646 }
8647 }
8648
8649 if (nsScriptSecurityManager::IsHttpOrHttpsAndCrossOrigin(principalURI,
8650 newURI) ||
8651 nsScriptSecurityManager::IsHttpOrHttpsAndCrossOrigin(principalURI,
8652 mCurrentURI) ||
8653 nsScriptSecurityManager::IsHttpOrHttpsAndCrossOrigin(mCurrentURI,
8654 newURI)) {
8655 aSameDocument = false;
8656 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)
8657 ("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)
8658 "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)
8659 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)
;
8660 return NS_OK;
8661 }
8662 }
8663
8664#ifdef DEBUG1
8665 if (aState.mSameExceptHashes) {
8666 bool sameExceptHashes = false;
8667 currentURI->EqualsExceptRef(newURI, &sameExceptHashes);
8668 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"
, 8668); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sameExceptHashes"
")"); do { *((volatile int*)__null) = 8668; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8669 }
8670#endif
8671 const nsCOMPtr<nsILoadInfo> loadInfo =
8672 doc->GetChannel() ? doc->GetChannel()->LoadInfo() : nullptr;
8673 if (loadInfo) {
8674 loadInfo->SetIsSameDocumentNavigation(true);
8675 }
8676 // Save the position of the scrollers.
8677 nsPoint scrollPos = GetCurScrollPos();
8678
8679 // Reset mLoadType to its original value once we exit this block, because this
8680 // same document navigation might have started after a normal, network load,
8681 // and we don't want to clobber its load type. See bug 737307.
8682 AutoRestore<uint32_t> loadTypeResetter(mLoadType);
8683
8684 // If a non-same-document-navigation (i.e., a network load) is pending, make
8685 // this a replacement load, so that we don't add a SHEntry here and the
8686 // network load goes into the SHEntry it expects to.
8687 if (JustStartedNetworkLoad() && (aLoadState->LoadType() & LOAD_CMD_NORMAL)) {
8688 mLoadType = LOAD_NORMAL_REPLACE;
8689 } else {
8690 mLoadType = aLoadState->LoadType();
8691 }
8692
8693 mURIResultedInDocument = true;
8694
8695 nsCOMPtr<nsISHEntry> oldLSHE = mLSHE;
8696
8697 // we need to assign aLoadState->SHEntry() to mLSHE right here, so that on
8698 // History loads, SetCurrentURI() called from OnNewURI() will send proper
8699 // onLocationChange() notifications to the browser to update back/forward
8700 // buttons.
8701 SetHistoryEntryAndUpdateBC(Some<nsISHEntry*>(aLoadState->SHEntry()),
8702 Nothing());
8703 UniquePtr<mozilla::dom::LoadingSessionHistoryInfo> oldLoadingEntry;
8704 mLoadingEntry.swap(oldLoadingEntry);
8705 if (aLoadState->GetLoadingSessionHistoryInfo()) {
8706 mLoadingEntry = MakeUnique<LoadingSessionHistoryInfo>(
8707 *aLoadState->GetLoadingSessionHistoryInfo());
8708 mNeedToReportActiveAfterLoadingBecomesActive = false;
8709 }
8710
8711 // Set the doc's URI according to the new history entry's URI.
8712 doc->SetDocumentURI(newURI);
8713
8714 /* This is a anchor traversal within the same page.
8715 * call OnNewURI() so that, this traversal will be
8716 * recorded in session and global history.
8717 */
8718 nsCOMPtr<nsIPrincipal> newURITriggeringPrincipal, newURIPrincipalToInherit,
8719 newURIPartitionedPrincipalToInherit;
8720 nsCOMPtr<nsIContentSecurityPolicy> newCsp;
8721 if (mozilla::SessionHistoryInParent() ? !!mActiveEntry : !!mOSHE) {
8722 if (mozilla::SessionHistoryInParent()) {
8723 newURITriggeringPrincipal = mActiveEntry->GetTriggeringPrincipal();
8724 newURIPrincipalToInherit = mActiveEntry->GetPrincipalToInherit();
8725 newURIPartitionedPrincipalToInherit =
8726 mActiveEntry->GetPartitionedPrincipalToInherit();
8727 newCsp = mActiveEntry->GetCsp();
8728 } else {
8729 newURITriggeringPrincipal = mOSHE->GetTriggeringPrincipal();
8730 newURIPrincipalToInherit = mOSHE->GetPrincipalToInherit();
8731 newURIPartitionedPrincipalToInherit =
8732 mOSHE->GetPartitionedPrincipalToInherit();
8733 newCsp = mOSHE->GetCsp();
8734 }
8735 } else {
8736 newURITriggeringPrincipal = aLoadState->TriggeringPrincipal();
8737 newURIPrincipalToInherit = doc->NodePrincipal();
8738 newURIPartitionedPrincipalToInherit = doc->PartitionedPrincipal();
8739 newCsp = doc->GetCsp();
8740 }
8741
8742 uint32_t locationChangeFlags = GetSameDocumentNavigationFlags(newURI);
8743
8744 // Pass true for aCloneSHChildren, since we're not
8745 // changing documents here, so all of our subframes are
8746 // still relevant to the new session history entry.
8747 //
8748 // It also makes OnNewURI(...) set LOCATION_CHANGE_SAME_DOCUMENT
8749 // flag on firing onLocationChange(...).
8750 // Anyway, aCloneSHChildren param is simply reflecting
8751 // doSameDocumentNavigation in this scope.
8752 //
8753 // Note: we'll actually fire onLocationChange later, in order to preserve
8754 // ordering of HistoryCommit() in the parent vs onLocationChange (bug
8755 // 1668126)
8756 bool locationChangeNeeded = OnNewURI(
8757 newURI, nullptr, newURITriggeringPrincipal, newURIPrincipalToInherit,
8758 newURIPartitionedPrincipalToInherit, newCsp, true, true);
8759
8760 nsCOMPtr<nsIInputStream> postData;
8761 nsCOMPtr<nsIReferrerInfo> referrerInfo;
8762 uint32_t cacheKey = 0;
8763
8764 bool scrollRestorationIsManual = false;
8765 if (!mozilla::SessionHistoryInParent()) {
8766 if (mOSHE) {
8767 /* save current position of scroller(s) (bug 59774) */
8768 mOSHE->SetScrollPosition(scrollPos.x, scrollPos.y);
8769 scrollRestorationIsManual = mOSHE->GetScrollRestorationIsManual();
8770 // Get the postdata, page ident and referrer info from the current page,
8771 // if the new load is being done via normal means. Note that "normal
8772 // means" can be checked for just by checking for LOAD_CMD_NORMAL, given
8773 // the loadType and allowScroll check above -- it filters out some
8774 // LOAD_CMD_NORMAL cases that we wouldn't want here.
8775 if (aLoadState->LoadType() & LOAD_CMD_NORMAL) {
8776 postData = mOSHE->GetPostData();
8777 cacheKey = mOSHE->GetCacheKey();
8778 referrerInfo = mOSHE->GetReferrerInfo();
8779 }
8780
8781 // Link our new SHEntry to the old SHEntry's back/forward
8782 // cache data, since the two SHEntries correspond to the
8783 // same document.
8784 if (mLSHE) {
8785 if (!aLoadState->LoadIsFromSessionHistory()) {
8786 // If we're not doing a history load, scroll restoration
8787 // should be inherited from the previous session history entry.
8788 SetScrollRestorationIsManualOnHistoryEntry(mLSHE,
8789 scrollRestorationIsManual);
8790 }
8791 mLSHE->AdoptBFCacheEntry(mOSHE);
8792 }
8793 }
8794 } else {
8795 if (mActiveEntry) {
8796 mActiveEntry->SetScrollPosition(scrollPos.x, scrollPos.y);
8797 if (mBrowsingContext) {
8798 CollectWireframe();
8799 if (XRE_IsParentProcess()) {
8800 SessionHistoryEntry* entry =
8801 mBrowsingContext->Canonical()->GetActiveSessionHistoryEntry();
8802 if (entry) {
8803 entry->SetScrollPosition(scrollPos.x, scrollPos.y);
8804 }
8805 } else {
8806 mozilla::Unused << ContentChild::GetSingleton()
8807 ->SendSessionHistoryEntryScrollPosition(
8808 mBrowsingContext, scrollPos.x,
8809 scrollPos.y);
8810 }
8811 }
8812 }
8813 if (mLoadingEntry) {
8814 if (!mLoadingEntry->mLoadIsFromSessionHistory) {
8815 // If we're not doing a history load, scroll restoration
8816 // should be inherited from the previous session history entry.
8817 // XXX This needs most probably tweaks once fragment navigation is
8818 // fixed to work with session-history-in-parent.
8819 SetScrollRestorationIsManualOnHistoryEntry(nullptr,
8820 scrollRestorationIsManual);
8821 }
8822 }
8823 }
8824
8825 // If we're doing a history load, use its scroll restoration state.
8826 if (aLoadState->LoadIsFromSessionHistory()) {
8827 if (mozilla::SessionHistoryInParent()) {
8828 scrollRestorationIsManual = aLoadState->GetLoadingSessionHistoryInfo()
8829 ->mInfo.GetScrollRestorationIsManual();
8830 } else {
8831 scrollRestorationIsManual =
8832 aLoadState->SHEntry()->GetScrollRestorationIsManual();
8833 }
8834 }
8835
8836 /* Assign mLSHE to mOSHE. This will either be a new entry created
8837 * by OnNewURI() for normal loads or aLoadState->SHEntry() for history
8838 * loads.
8839 */
8840 if (!mozilla::SessionHistoryInParent()) {
8841 if (mLSHE) {
8842 SetHistoryEntryAndUpdateBC(Nothing(), Some<nsISHEntry*>(mLSHE));
8843 // Save the postData obtained from the previous page
8844 // in to the session history entry created for the
8845 // anchor page, so that any history load of the anchor
8846 // page will restore the appropriate postData.
8847 if (postData) {
8848 mOSHE->SetPostData(postData);
8849 }
8850
8851 // Make sure we won't just repost without hitting the
8852 // cache first
8853 if (cacheKey != 0) {
8854 mOSHE->SetCacheKey(cacheKey);
8855 }
8856
8857 // As the document has not changed, the referrer info hasn't changed too,
8858 // so we can just copy it over.
8859 if (referrerInfo) {
8860 mOSHE->SetReferrerInfo(referrerInfo);
8861 }
8862 }
8863
8864 /* Set the title for the SH entry for this target url so that
8865 * SH menus in go/back/forward buttons won't be empty for this.
8866 * Note, this happens on mOSHE (and mActiveEntry in the future) because of
8867 * the code above.
8868 * Note, when session history lives in the parent process, this does not
8869 * update the title there.
8870 */
8871 SetTitleOnHistoryEntry(false);
8872 } else {
8873 if (aLoadState->LoadIsFromSessionHistory()) {
8874 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)
8875 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)
8876 ("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)
8877 "%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)
8878 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)
;
8879
8880 nsCOMPtr<nsILayoutHistoryState> currentLayoutHistoryState;
8881 if (mActiveEntry) {
8882 currentLayoutHistoryState = mActiveEntry->GetLayoutHistoryState();
8883 }
8884
8885 UniquePtr<SessionHistoryInfo> previousActiveEntry(mActiveEntry.release());
8886 mActiveEntry = MakeUnique<SessionHistoryInfo>(mLoadingEntry->mInfo);
8887 if (currentLayoutHistoryState) {
8888 // Restore the existing nsILayoutHistoryState object, since it is
8889 // possibly being used by the layout. When doing a new load, the
8890 // shared state is copied from the existing active entry, so this
8891 // special case is needed only with the history loads.
8892 mActiveEntry->SetLayoutHistoryState(currentLayoutHistoryState);
8893 }
8894
8895 if (cacheKey != 0) {
8896 mActiveEntry->SetCacheKey(cacheKey);
8897 }
8898 // We're passing in mCurrentURI, which could be null. SessionHistoryCommit
8899 // does require a non-null uri if this is for a refresh load of the same
8900 // URI, but in that case mCurrentURI won't be null here.
8901 mBrowsingContext->SessionHistoryCommit(
8902 *mLoadingEntry, mLoadType, mCurrentURI, previousActiveEntry.get(),
8903 true, true,
8904 /* No expiration update on the same document loads*/
8905 false, cacheKey);
8906 // FIXME Need to set postdata.
8907
8908 // Set the title for the SH entry for this target url so that
8909 // SH menus in go/back/forward buttons won't be empty for this.
8910 // Note, when session history lives in the parent process, this does not
8911 // update the title there.
8912 SetTitleOnHistoryEntry(false);
8913 } else {
8914 Maybe<bool> scrollRestorationIsManual;
8915 if (mActiveEntry) {
8916 scrollRestorationIsManual.emplace(
8917 mActiveEntry->GetScrollRestorationIsManual());
8918
8919 // Get the postdata, page ident and referrer info from the current page,
8920 // if the new load is being done via normal means. Note that "normal
8921 // means" can be checked for just by checking for LOAD_CMD_NORMAL, given
8922 // the loadType and allowScroll check above -- it filters out some
8923 // LOAD_CMD_NORMAL cases that we wouldn't want here.
8924 if (aLoadState->LoadType() & LOAD_CMD_NORMAL) {
8925 postData = mActiveEntry->GetPostData();
8926 cacheKey = mActiveEntry->GetCacheKey();
8927 referrerInfo = mActiveEntry->GetReferrerInfo();
8928 }
8929 }
8930
8931 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)
8932 ("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)
8933 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)
;
8934 if (mActiveEntry) {
8935 mActiveEntry = MakeUnique<SessionHistoryInfo>(*mActiveEntry, newURI);
8936 } else {
8937 mActiveEntry = MakeUnique<SessionHistoryInfo>(
8938 newURI, newURITriggeringPrincipal, newURIPrincipalToInherit,
8939 newURIPartitionedPrincipalToInherit, newCsp, mContentTypeHint);
8940 }
8941
8942 // Save the postData obtained from the previous page in to the session
8943 // history entry created for the anchor page, so that any history load of
8944 // the anchor page will restore the appropriate postData.
8945 if (postData) {
8946 mActiveEntry->SetPostData(postData);
8947 }
8948
8949 // Make sure we won't just repost without hitting the
8950 // cache first
8951 if (cacheKey != 0) {
8952 mActiveEntry->SetCacheKey(cacheKey);
8953 }
8954
8955 // As the document has not changed, the referrer info hasn't changed too,
8956 // so we can just copy it over.
8957 if (referrerInfo) {
8958 mActiveEntry->SetReferrerInfo(referrerInfo);
8959 }
8960
8961 // Set the title for the SH entry for this target url so that
8962 // SH menus in go/back/forward buttons won't be empty for this.
8963 mActiveEntry->SetTitle(mTitle);
8964
8965 if (scrollRestorationIsManual.isSome()) {
8966 mActiveEntry->SetScrollRestorationIsManual(
8967 scrollRestorationIsManual.value());
8968 }
8969
8970 if (LOAD_TYPE_HAS_FLAGS(mLoadType, LOAD_FLAGS_REPLACE_HISTORY)((mLoadType) & ((LOAD_FLAGS_REPLACE_HISTORY) << 16)
)
) {
8971 mBrowsingContext->ReplaceActiveSessionHistoryEntry(mActiveEntry.get());
8972 } else {
8973 mBrowsingContext->IncrementHistoryEntryCountForBrowsingContext();
8974 // FIXME We should probably just compute mChildOffset in the parent
8975 // instead of passing it over IPC here.
8976 mBrowsingContext->SetActiveSessionHistoryEntry(
8977 Some(scrollPos), mActiveEntry.get(), mLoadType, cacheKey);
8978 // FIXME Do we need to update mPreviousEntryIndex and mLoadedEntryIndex?
8979 }
8980 }
8981 }
8982
8983 if (locationChangeNeeded) {
8984 FireOnLocationChange(this, nullptr, newURI, locationChangeFlags);
8985 }
8986
8987 /* Restore the original LSHE if we were loading something
8988 * while same document navigation was initiated.
8989 */
8990 SetHistoryEntryAndUpdateBC(Some<nsISHEntry*>(oldLSHE), Nothing());
8991 mLoadingEntry.swap(oldLoadingEntry);
8992
8993 /* Set the title for the Global History entry for this anchor url.
8994 */
8995 UpdateGlobalHistoryTitle(newURI);
8996
8997 SetDocCurrentStateObj(mOSHE, mActiveEntry.get());
8998
8999 // Inform the favicon service that the favicon for oldURI also
9000 // applies to newURI.
9001 CopyFavicon(currentURI, newURI, UsePrivateBrowsing());
9002
9003 RefPtr<nsGlobalWindowOuter> scriptGlobal = mScriptGlobal;
9004 nsCOMPtr<nsPIDOMWindowInner> win =
9005 scriptGlobal ? scriptGlobal->GetCurrentInnerWindow() : nullptr;
9006
9007 // The check for uninvoked directives must come before ScrollToAnchor() is
9008 // called.
9009 const bool hasTextDirectives =
9010 doc->FragmentDirective()->HasUninvokedDirectives();
9011
9012 // ScrollToAnchor doesn't necessarily cause us to scroll the window;
9013 // the function decides whether a scroll is appropriate based on the
9014 // arguments it receives. But even if we don't end up scrolling,
9015 // ScrollToAnchor performs other important tasks, such as informing
9016 // the presShell that we have a new hash. See bug 680257.
9017 nsresult rv = ScrollToAnchor(aState.mCurrentURIHasRef, aState.mNewURIHasRef,
9018 aState.mNewHash, aLoadState->LoadType());
9019 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"
, 9019); return rv; } } while (false)
;
9020
9021 /* restore previous position of scroller(s), if we're moving
9022 * back in history (bug 59774)
9023 */
9024 nscoord bx = 0;
9025 nscoord by = 0;
9026 bool needsScrollPosUpdate = false;
9027 if ((mozilla::SessionHistoryInParent() ? !!mActiveEntry : !!mOSHE) &&
9028 (aLoadState->LoadType() == LOAD_HISTORY ||
9029 aLoadState->LoadType() == LOAD_RELOAD_NORMAL) &&
9030 !scrollRestorationIsManual) {
9031 needsScrollPosUpdate = true;
9032 if (mozilla::SessionHistoryInParent()) {
9033 mActiveEntry->GetScrollPosition(&bx, &by);
9034 } else {
9035 mOSHE->GetScrollPosition(&bx, &by);
9036 }
9037 }
9038
9039 // Dispatch the popstate and hashchange events, as appropriate.
9040 //
9041 // The event dispatch below can cause us to re-enter script and
9042 // destroy the docshell, nulling out mScriptGlobal. Hold a stack
9043 // reference to avoid null derefs. See bug 914521.
9044 if (win) {
9045 // Fire a hashchange event URIs differ, and only in their hashes.
9046 // If the fragment contains a directive, compare hasRef.
9047 bool doHashchange = aState.mSameExceptHashes &&
9048 (!aState.mCurrentHash.Equals(aState.mNewHash) ||
9049 (hasTextDirectives &&
9050 aState.mCurrentURIHasRef != aState.mNewURIHasRef));
9051
9052 if (aState.mHistoryNavBetweenSameDoc || doHashchange) {
9053 win->DispatchSyncPopState();
9054 }
9055
9056 if (needsScrollPosUpdate && win->HasActiveDocument()) {
9057 SetCurScrollPosEx(bx, by);
9058 }
9059
9060 if (doHashchange) {
9061 // Note that currentURI hasn't changed because it's on the
9062 // stack, so we can just use it directly as the old URI.
9063 win->DispatchAsyncHashchange(currentURI, newURI);
9064 }
9065 }
9066
9067 return NS_OK;
9068}
9069
9070static bool NavigationShouldTakeFocus(nsDocShell* aDocShell,
9071 nsDocShellLoadState* aLoadState) {
9072 if (!aLoadState->AllowFocusMove()) {
9073 return false;
9074 }
9075 if (!aLoadState->HasValidUserGestureActivation()) {
9076 return false;
9077 }
9078 const auto& sourceBC = aLoadState->SourceBrowsingContext();
9079 if (!sourceBC || !sourceBC->IsActive()) {
9080 // If the navigation didn't come from a foreground tab, then we don't steal
9081 // focus.
9082 return false;
9083 }
9084 auto* bc = aDocShell->GetBrowsingContext();
9085 if (sourceBC.get() == bc) {
9086 // If it comes from the same tab / frame, don't steal focus either.
9087 return false;
9088 }
9089 auto* fm = nsFocusManager::GetFocusManager();
9090 if (fm && bc->IsActive() && fm->IsInActiveWindow(bc)) {
9091 // If we're already on the foreground tab of the foreground window, then we
9092 // don't need to do this. This helps to e.g. not steal focus from the
9093 // browser chrome unnecessarily.
9094 return false;
9095 }
9096 if (auto* doc = aDocShell->GetExtantDocument()) {
9097 if (doc->IsInitialDocument()) {
9098 // If we're the initial load for the browsing context, the browser
9099 // chrome determines what to focus. This is important because the
9100 // browser chrome may want to e.g focus the url-bar
9101 return false;
9102 }
9103 }
9104 // Take loadDivertedInBackground into account so the behavior would be the
9105 // same as how the tab first opened.
9106 return !Preferences::GetBool("browser.tabs.loadDivertedInBackground", false);
9107}
9108
9109uint32_t nsDocShell::GetLoadTypeForFormSubmission(
9110 BrowsingContext* aTargetBC, nsDocShellLoadState* aLoadState) {
9111 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"
, 9111); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->IsFormSubmission()"
")"); do { *((volatile int*)__null) = 9111; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9112
9113 // https://html.spec.whatwg.org/#form-submission-algorithm
9114 // 22. Let historyHandling be "push".
9115 // 23. If form document equals targetNavigable's active document, and
9116 // form document has not yet completely loaded, then set
9117 // historyHandling to "replace".
9118 return GetBrowsingContext() == aTargetBC && !mEODForCurrentDocument
9119 ? LOAD_NORMAL_REPLACE
9120 : LOAD_LINK;
9121}
9122
9123nsresult nsDocShell::InternalLoad(nsDocShellLoadState* aLoadState,
9124 Maybe<uint32_t> aCacheKey) {
9125 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"
, 9125); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState"
") (" "need a load state!" ")"); do { *((volatile int*)__null
) = 9125; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
;
9126 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"
, 9127); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->TriggeringPrincipal()"
") (" "need a valid TriggeringPrincipal" ")"); do { *((volatile
int*)__null) = 9127; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
9127 "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"
, 9127); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->TriggeringPrincipal()"
") (" "need a valid TriggeringPrincipal" ")"); do { *((volatile
int*)__null) = 9127; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
9128
9129 if (!aLoadState->TriggeringPrincipal()) {
9130 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"
, 9130); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"InternalLoad needs a valid triggeringPrincipal" ")"); do { *
((volatile int*)__null) = 9130; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
;
9131 return NS_ERROR_FAILURE;
9132 }
9133 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"
, 9133)
) {
9134 return NS_ERROR_NOT_AVAILABLE;
9135 }
9136
9137 const bool shouldTakeFocus = NavigationShouldTakeFocus(this, aLoadState);
9138
9139 mOriginalUriString.Truncate();
9140
9141 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)
9142 ("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)
9143 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)
;
9144
9145 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"
, 9145); return NS_ERROR_INVALID_ARG; } } while (false)
;
9146
9147 // Cancel loads coming from Docshells that are being destroyed.
9148 if (mIsBeingDestroyed) {
9149 return NS_ERROR_NOT_AVAILABLE;
9150 }
9151
9152 nsresult rv = EnsureScriptEnvironment();
9153 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
9154 return rv;
9155 }
9156
9157 // If we have a target to move to, do that now.
9158 if (!aLoadState->Target().IsEmpty()) {
9159 return PerformRetargeting(aLoadState);
9160 }
9161
9162 // This is the non-retargeting load path, we've already set the right loadtype
9163 // for form submissions in nsDocShell::OnLinkClickSync.
9164 if (aLoadState->TargetBrowsingContext().IsNull()) {
9165 aLoadState->SetTargetBrowsingContext(GetBrowsingContext());
9166 }
9167
9168 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"
, 9170); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "aLoadState->TargetBrowsingContext() == GetBrowsingContext()"
") (" "Load must be targeting this BrowsingContext" ")"); do
{ *((volatile int*)__null) = 9170; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
9169 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"
, 9170); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "aLoadState->TargetBrowsingContext() == GetBrowsingContext()"
") (" "Load must be targeting this BrowsingContext" ")"); do
{ *((volatile int*)__null) = 9170; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
9170 "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"
, 9170); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "aLoadState->TargetBrowsingContext() == GetBrowsingContext()"
") (" "Load must be targeting this BrowsingContext" ")"); do
{ *((volatile int*)__null) = 9170; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
9171
9172 MOZ_TRY(CheckDisallowedJavascriptLoad(aLoadState))do { auto mozTryTempResult_ = ::mozilla::ToResult(CheckDisallowedJavascriptLoad
(aLoadState)); if ((__builtin_expect(!!(mozTryTempResult_.isErr
()), 0))) { return mozTryTempResult_.propagateErr(); } } while
(0)
;
9173
9174 // If we don't have a target, we're loading into ourselves, and our load
9175 // delegate may want to intercept that load.
9176 SameDocumentNavigationState sameDocumentNavigationState;
9177 bool sameDocument =
9178 IsSameDocumentNavigation(aLoadState, sameDocumentNavigationState) &&
9179 !aLoadState->GetPendingRedirectedChannel();
9180
9181 // Note: We do this check both here and in BrowsingContext::
9182 // LoadURI/InternalLoad, since document-specific sandbox flags are only
9183 // available in the process triggering the load, and we don't want the target
9184 // process to have to trust the triggering process to do the appropriate
9185 // checks for the BrowsingContext's sandbox flags.
9186 MOZ_TRY(mBrowsingContext->CheckSandboxFlags(aLoadState))do { auto mozTryTempResult_ = ::mozilla::ToResult(mBrowsingContext
->CheckSandboxFlags(aLoadState)); if ((__builtin_expect(!!
(mozTryTempResult_.isErr()), 0))) { return mozTryTempResult_.
propagateErr(); } } while (0)
;
9187
9188 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"
, 9188); return NS_ERROR_UNEXPECTED; } } while (false)
;
9189
9190 rv = CheckLoadingPermissions();
9191 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
9192 return rv;
9193 }
9194
9195 if (mFiredUnloadEvent) {
9196 if (IsOKToLoadURI(aLoadState->URI())) {
9197 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"
, 9198); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->Target().IsEmpty()"
") (" "Shouldn't have a window target here!" ")"); do { *((volatile
int*)__null) = 9198; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
9198 "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"
, 9198); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->Target().IsEmpty()"
") (" "Shouldn't have a window target here!" ")"); do { *((volatile
int*)__null) = 9198; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
9199
9200 // If this is a replace load, make whatever load triggered
9201 // the unload event also a replace load, so we don't
9202 // create extra history entries.
9203 if (LOAD_TYPE_HAS_FLAGS(aLoadState->LoadType(),((aLoadState->LoadType()) & ((LOAD_FLAGS_REPLACE_HISTORY
) << 16))
9204 LOAD_FLAGS_REPLACE_HISTORY)((aLoadState->LoadType()) & ((LOAD_FLAGS_REPLACE_HISTORY
) << 16))
) {
9205 mLoadType = LOAD_NORMAL_REPLACE;
9206 }
9207
9208 // Do this asynchronously
9209 nsCOMPtr<nsIRunnable> ev = new InternalLoadEvent(this, aLoadState);
9210 return Dispatch(ev.forget());
9211 }
9212
9213 // Just ignore this load attempt
9214 return NS_OK;
9215 }
9216
9217 // If we are loading a URI that should inherit a security context (basically
9218 // javascript: at this point), and the caller has said that principal
9219 // inheritance is allowed, there are a few possible cases:
9220 //
9221 // 1) We are provided with the principal to inherit. In that case, we just use
9222 // it.
9223 //
9224 // 2) The load is coming from some other application. In this case we don't
9225 // want to inherit from whatever document we have loaded now, since the
9226 // load is unrelated to it.
9227 //
9228 // 3) It's a load from our application, but does not provide an explicit
9229 // principal to inherit. In that case, we want to inherit the principal of
9230 // our current document, or of our parent document (if any) if we don't
9231 // have a current document.
9232 {
9233 bool inherits;
9234
9235 if (!aLoadState->HasLoadFlags(LOAD_FLAGS_FROM_EXTERNAL) &&
9236 !aLoadState->PrincipalToInherit() &&
9237 (aLoadState->HasInternalLoadFlags(
9238 INTERNAL_LOAD_FLAGS_INHERIT_PRINCIPAL)) &&
9239 NS_SUCCEEDED(nsContentUtils::URIInheritsSecurityContext(((bool)(__builtin_expect(!!(!NS_FAILED_impl(nsContentUtils::URIInheritsSecurityContext
( aLoadState->URI(), &inherits))), 1)))
9240 aLoadState->URI(), &inherits))((bool)(__builtin_expect(!!(!NS_FAILED_impl(nsContentUtils::URIInheritsSecurityContext
( aLoadState->URI(), &inherits))), 1)))
&&
9241 inherits) {
9242 aLoadState->SetPrincipalToInherit(GetInheritedPrincipal(true));
9243 }
9244 // If principalToInherit is still null (e.g. if some of the conditions of
9245 // were not satisfied), then no inheritance of any sort will happen: the
9246 // load will just get a principal based on the URI being loaded.
9247 }
9248
9249 // If this docshell is owned by a frameloader, make sure to cancel
9250 // possible frameloader initialization before loading a new page.
9251 nsCOMPtr<nsIDocShellTreeItem> parent = GetInProcessParentDocshell();
9252 if (parent) {
9253 RefPtr<Document> doc = parent->GetDocument();
9254 if (doc) {
9255 doc->TryCancelFrameLoaderInitialization(this);
9256 }
9257 }
9258
9259 // Before going any further vet loads initiated by external programs.
9260 if (aLoadState->HasLoadFlags(LOAD_FLAGS_FROM_EXTERNAL)) {
9261 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"
, 9261); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "aLoadState->LoadType() == LOAD_NORMAL"
")"); do { *((volatile int*)__null) = 9261; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9262
9263 // Disallow external chrome: loads targetted at content windows
9264 if (SchemeIsChrome(aLoadState->URI())) {
9265 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"
, 9265)
;
9266 return NS_ERROR_FAILURE;
9267 }
9268
9269 // clear the decks to prevent context bleed-through (bug 298255)
9270 rv = CreateAboutBlankDocumentViewer(nullptr, nullptr, nullptr, nullptr,
9271 /* aIsInitialDocument */ false);
9272 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
9273 return NS_ERROR_FAILURE;
9274 }
9275 }
9276
9277 mAllowKeywordFixup = aLoadState->HasInternalLoadFlags(
9278 INTERNAL_LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP);
9279 mURIResultedInDocument = false; // reset the clock...
9280
9281 // See if this is actually a load between two history entries for the same
9282 // document. If the process fails, or if we successfully navigate within the
9283 // same document, return.
9284 if (sameDocument) {
9285 nsresult rv = HandleSameDocumentNavigation(
9286 aLoadState, sameDocumentNavigationState, sameDocument);
9287 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"
, 9287); return rv; } } while (false)
;
9288 if (shouldTakeFocus) {
9289 mBrowsingContext->Focus(CallerType::System, IgnoreErrors());
9290 }
9291 if (sameDocument) {
9292 return rv;
9293 }
9294 }
9295
9296 // mDocumentViewer->PermitUnload can destroy |this| docShell, which
9297 // causes the next call of CanSavePresentation to crash.
9298 // Hold onto |this| until we return, to prevent a crash from happening.
9299 // (bug#331040)
9300 nsCOMPtr<nsIDocShell> kungFuDeathGrip(this);
9301
9302 // Don't init timing for javascript:, since it generally doesn't
9303 // actually start a load or anything. If it does, we'll init
9304 // timing then, from OnStateChange.
9305
9306 // XXXbz mTiming should know what channel it's for, so we don't
9307 // need this hackery.
9308 const bool isJavaScript = SchemeIsJavascript(aLoadState->URI());
9309 const bool isExternalProtocol =
9310 nsContentUtils::IsExternalProtocol(aLoadState->URI());
9311 const bool isDownload = !aLoadState->FileName().IsVoid();
9312 const bool toBeReset = !isJavaScript && MaybeInitTiming();
9313
9314 // FIXME(emilio): Should this be done by javascript: uris? What about external
9315 // protocols?
9316 if (mTiming && !isDownload) {
9317 mTiming->NotifyBeforeUnload();
9318 }
9319 // Check if the page doesn't want to be unloaded. The javascript:
9320 // protocol handler deals with this for javascript: URLs.
9321 // NOTE(emilio): As of this writing, other browsers fire beforeunload for
9322 // external protocols, so keep doing that even though they don't return data
9323 // and thus we won't really unload this...
9324 if (!isJavaScript && !isDownload &&
9325 !aLoadState->NotifiedBeforeUnloadListeners() && mDocumentViewer) {
9326 // Check if request is exempted from HTTPSOnlyMode and if https-first is
9327 // enabled, if so it means:
9328 // * https-first failed to upgrade request to https
9329 // * we already asked for permission to unload and the user accepted
9330 // otherwise we wouldn't be here.
9331 const bool isPrivateWin = GetOriginAttributes().IsPrivateBrowsing();
9332 const uint32_t loadType = aLoadState->LoadType();
9333
9334 // Check if request is a reload.
9335 const bool isHistoryOrReload =
9336 loadType == LOAD_RELOAD_NORMAL ||
9337 loadType == LOAD_RELOAD_BYPASS_CACHE ||
9338 loadType == LOAD_RELOAD_BYPASS_PROXY ||
9339 loadType == LOAD_RELOAD_BYPASS_PROXY_AND_CACHE ||
9340 loadType == LOAD_HISTORY;
9341
9342 // If it isn't a reload, the request already failed to be upgraded and
9343 // https-first is enabled then don't ask the user again for permission to
9344 // unload and just unload.
9345 bool okToUnload;
9346 if (!isHistoryOrReload && aLoadState->IsExemptFromHTTPSFirstMode() &&
9347 nsHTTPSOnlyUtils::IsHttpsFirstModeEnabled(isPrivateWin)) {
9348 rv = mDocumentViewer->PermitUnload(
9349 nsIDocumentViewer::PermitUnloadAction::eDontPromptAndUnload,
9350 &okToUnload);
9351 } else {
9352 rv = mDocumentViewer->PermitUnload(&okToUnload);
9353 }
9354
9355 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && !okToUnload) {
9356 // The user chose not to unload the page, interrupt the
9357 // load.
9358 MaybeResetInitTiming(toBeReset);
9359 return NS_OK;
9360 }
9361 }
9362
9363 if (mTiming && !isDownload) {
9364 mTiming->NotifyUnloadAccepted(mCurrentURI);
9365 }
9366
9367 // In e10s, in the parent process, we refuse to load anything other than
9368 // "safe" resources that we ship or trust enough to give "special" URLs.
9369 // Similar check will be performed by the ParentProcessDocumentChannel if in
9370 // use.
9371 if (XRE_IsE10sParentProcess() &&
9372 !DocumentChannel::CanUseDocumentChannel(aLoadState->URI()) &&
9373 !CanLoadInParentProcess(aLoadState->URI())) {
9374 return NS_ERROR_FAILURE;
9375 }
9376
9377 // Whenever a top-level browsing context is navigated, the user agent MUST
9378 // lock the orientation of the document to the document's default
9379 // orientation. We don't explicitly check for a top-level browsing context
9380 // here because orientation is only set on top-level browsing contexts.
9381 if (mBrowsingContext->GetOrientationLock() != hal::ScreenOrientation::None) {
9382 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"
, 9382); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mBrowsingContext->IsTop()"
")"); do { *((volatile int*)__null) = 9382; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9383 MOZ_ALWAYS_SUCCEEDS(do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(mBrowsingContext->SetOrientationLock(hal::ScreenOrientation
::None))), 1)))), 1))) { } else { do { do { } while (false); MOZ_ReportCrash
("" "NS_SUCCEEDED(mBrowsingContext->SetOrientationLock(hal::ScreenOrientation::None))"
, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 9384); AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED(mBrowsingContext->SetOrientationLock(hal::ScreenOrientation::None))"
")"); do { *((volatile int*)__null) = 9384; __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
9384 mBrowsingContext->SetOrientationLock(hal::ScreenOrientation::None))do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(mBrowsingContext->SetOrientationLock(hal::ScreenOrientation
::None))), 1)))), 1))) { } else { do { do { } while (false); MOZ_ReportCrash
("" "NS_SUCCEEDED(mBrowsingContext->SetOrientationLock(hal::ScreenOrientation::None))"
, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 9384); AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED(mBrowsingContext->SetOrientationLock(hal::ScreenOrientation::None))"
")"); do { *((volatile int*)__null) = 9384; __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
;
9385 if (mBrowsingContext->IsActive()) {
9386 ScreenOrientation::UpdateActiveOrientationLock(
9387 hal::ScreenOrientation::None);
9388 }
9389 }
9390
9391 // Check for saving the presentation here, before calling Stop().
9392 // This is necessary so that we can catch any pending requests.
9393 // Since the new request has not been created yet, we pass null for the
9394 // new request parameter.
9395 // Also pass nullptr for the document, since it doesn't affect the return
9396 // value for our purposes here.
9397 const bool savePresentation =
9398 CanSavePresentation(aLoadState->LoadType(), nullptr, nullptr,
9399 /* aReportBFCacheComboTelemetry */ true);
9400
9401 // nsDocShell::CanSavePresentation is for non-SHIP version only. Do a
9402 // separate check for SHIP so that we know if there are ongoing requests
9403 // before calling Stop() below.
9404 if (mozilla::SessionHistoryInParent()) {
9405 Document* document = GetDocument();
9406 uint32_t flags = 0;
9407 if (document && !document->CanSavePresentation(nullptr, flags, true)) {
9408 // This forces some flags into the WindowGlobalParent's mBFCacheStatus,
9409 // which we'll then use in CanonicalBrowsingContext::AllowedInBFCache,
9410 // and in particular we'll store BFCacheStatus::REQUEST if needed.
9411 // Also, we want to report all the flags to the parent process here (and
9412 // not just BFCacheStatus::NOT_ALLOWED), so that it can update the
9413 // telemetry data correctly.
9414 document->DisallowBFCaching(flags);
9415 }
9416 }
9417
9418 // Don't stop current network activity for javascript: URL's since they might
9419 // not result in any data, and thus nothing should be stopped in those cases.
9420 // In the case where they do result in data, the javascript: URL channel takes
9421 // care of stopping current network activity. Similarly, downloads don't
9422 // unload this document...
9423 if (!isJavaScript && !isDownload && !isExternalProtocol) {
9424 // Stop any current network activity.
9425 // Also stop content if this is a zombie doc. otherwise
9426 // the onload will be delayed by other loads initiated in the
9427 // background by the first document that
9428 // didn't fully load before the next load was initiated.
9429 // If not a zombie, don't stop content until data
9430 // starts arriving from the new URI...
9431 if ((mDocumentViewer && mDocumentViewer->GetPreviousViewer()) ||
9432 LOAD_TYPE_HAS_FLAGS(aLoadState->LoadType(), LOAD_FLAGS_STOP_CONTENT)((aLoadState->LoadType()) & ((LOAD_FLAGS_STOP_CONTENT)
<< 16))
) {
9433 rv = Stop(nsIWebNavigation::STOP_ALL);
9434 } else {
9435 rv = Stop(nsIWebNavigation::STOP_NETWORK);
9436 }
9437
9438 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
9439 return rv;
9440 }
9441 }
9442
9443 mLoadType = aLoadState->LoadType();
9444
9445 // aLoadState->SHEntry() should be assigned to mLSHE, only after Stop() has
9446 // been called. But when loading an error page, do not clear the
9447 // mLSHE for the real page.
9448 if (mLoadType != LOAD_ERROR_PAGE) {
9449 SetHistoryEntryAndUpdateBC(Some<nsISHEntry*>(aLoadState->SHEntry()),
9450 Nothing());
9451 if (aLoadState->LoadIsFromSessionHistory() &&
9452 !mozilla::SessionHistoryInParent()) {
9453 // We're making history navigation or a reload. Make sure our history ID
9454 // points to the same ID as SHEntry's docshell ID.
9455 nsID historyID = {};
9456 aLoadState->SHEntry()->GetDocshellID(historyID);
9457
9458 Unused << mBrowsingContext->SetHistoryID(historyID);
9459 }
9460 }
9461
9462 mSavingOldViewer = savePresentation;
9463
9464 // If we have a saved content viewer in history, restore and show it now.
9465 if (aLoadState->LoadIsFromSessionHistory() &&
9466 (mLoadType & LOAD_CMD_HISTORY)) {
9467 // https://html.spec.whatwg.org/#history-traversal:
9468 // To traverse the history
9469 // "If entry has a different Document object than the current entry, then
9470 // run the following substeps: Remove any tasks queued by the history
9471 // traversal task source..."
9472 // Same document object case was handled already above with
9473 // HandleSameDocumentNavigation call.
9474 RefPtr<ChildSHistory> shistory = GetRootSessionHistory();
9475 if (shistory) {
9476 shistory->RemovePendingHistoryNavigations();
9477 }
9478 if (!mozilla::SessionHistoryInParent()) {
9479 // It's possible that the previous viewer of mDocumentViewer is the
9480 // viewer that will end up in aLoadState->SHEntry() when it gets closed.
9481 // If that's the case, we need to go ahead and force it into its shentry
9482 // so we can restore it.
9483 if (mDocumentViewer) {
9484 nsCOMPtr<nsIDocumentViewer> prevViewer =
9485 mDocumentViewer->GetPreviousViewer();
9486 if (prevViewer) {
9487#ifdef DEBUG1
9488 nsCOMPtr<nsIDocumentViewer> prevPrevViewer =
9489 prevViewer->GetPreviousViewer();
9490 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"
, 9490); MOZ_PretendNoReturn(); } } while (0)
;
9491#endif
9492 nsCOMPtr<nsISHEntry> viewerEntry;
9493 prevViewer->GetHistoryEntry(getter_AddRefs(viewerEntry));
9494 if (viewerEntry == aLoadState->SHEntry()) {
9495 // Make sure this viewer ends up in the right place
9496 mDocumentViewer->SetPreviousViewer(nullptr);
9497 prevViewer->Destroy();
9498 }
9499 }
9500 }
9501 nsCOMPtr<nsISHEntry> oldEntry = mOSHE;
9502 bool restoring;
9503 rv = RestorePresentation(aLoadState->SHEntry(), &restoring);
9504 if (restoring) {
9505 Telemetry::Accumulate(Telemetry::BFCACHE_PAGE_RESTORED, true);
9506 return rv;
9507 }
9508 Telemetry::Accumulate(Telemetry::BFCACHE_PAGE_RESTORED, false);
9509
9510 // We failed to restore the presentation, so clean up.
9511 // Both the old and new history entries could potentially be in
9512 // an inconsistent state.
9513 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
9514 if (oldEntry) {
9515 oldEntry->SyncPresentationState();
9516 }
9517
9518 aLoadState->SHEntry()->SyncPresentationState();
9519 }
9520 }
9521 }
9522
9523 bool isTopLevelDoc = mBrowsingContext->IsTopContent();
9524
9525 OriginAttributes attrs = GetOriginAttributes();
9526 attrs.SetFirstPartyDomain(isTopLevelDoc, aLoadState->URI());
9527
9528 PredictorLearn(aLoadState->URI(), nullptr,
9529 nsINetworkPredictor::LEARN_LOAD_TOPLEVEL, attrs);
9530 PredictorPredict(aLoadState->URI(), nullptr,
9531 nsINetworkPredictor::PREDICT_LOAD, attrs, nullptr);
9532
9533 nsCOMPtr<nsIRequest> req;
9534 rv = DoURILoad(aLoadState, aCacheKey, getter_AddRefs(req));
9535
9536 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
9537 if (shouldTakeFocus) {
9538 mBrowsingContext->Focus(CallerType::System, IgnoreErrors());
9539 }
9540 }
9541
9542 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
9543 nsCOMPtr<nsIChannel> chan(do_QueryInterface(req));
9544 UnblockEmbedderLoadEventForFailure();
9545 nsCOMPtr<nsIURI> uri = aLoadState->URI();
9546 if (DisplayLoadError(rv, uri, nullptr, chan) &&
9547 // FIXME: At this point code was using internal load flags, but checking
9548 // non-internal load flags?
9549 aLoadState->HasLoadFlags(LOAD_FLAGS_ERROR_LOAD_CHANGES_RV)) {
9550 return NS_ERROR_LOAD_SHOWED_ERRORPAGE;
9551 }
9552
9553 // We won't report any error if this is an unknown protocol error. The
9554 // reason behind this is that it will allow enumeration of external
9555 // protocols if we report an error for each unknown protocol.
9556 if (NS_ERROR_UNKNOWN_PROTOCOL == rv) {
9557 return NS_OK;
9558 }
9559 }
9560
9561 return rv;
9562}
9563
9564/* static */
9565bool nsDocShell::CanLoadInParentProcess(nsIURI* aURI) {
9566 nsCOMPtr<nsIURI> uri = aURI;
9567 // In e10s, in the parent process, we refuse to load anything other than
9568 // "safe" resources that we ship or trust enough to give "special" URLs.
9569 bool canLoadInParent = false;
9570 if (NS_SUCCEEDED(NS_URIChainHasFlags(((bool)(__builtin_expect(!!(!NS_FAILED_impl(NS_URIChainHasFlags
( uri, nsIProtocolHandler::URI_IS_UI_RESOURCE, &canLoadInParent
))), 1)))
9571 uri, nsIProtocolHandler::URI_IS_UI_RESOURCE, &canLoadInParent))((bool)(__builtin_expect(!!(!NS_FAILED_impl(NS_URIChainHasFlags
( uri, nsIProtocolHandler::URI_IS_UI_RESOURCE, &canLoadInParent
))), 1)))
&&
9572 canLoadInParent) {
9573 // We allow UI resources.
9574 return true;
9575 }
9576 // For about: and extension-based URIs, which don't get
9577 // URI_IS_UI_RESOURCE, first remove layers of view-source:, if present.
9578 while (uri && uri->SchemeIs("view-source")) {
9579 nsCOMPtr<nsINestedURI> nested = do_QueryInterface(uri);
9580 if (nested) {
9581 nested->GetInnerURI(getter_AddRefs(uri));
9582 } else {
9583 break;
9584 }
9585 }
9586 // Allow about: URIs, and allow moz-extension ones if we're running
9587 // extension content in the parent process.
9588 if (!uri || uri->SchemeIs("about") ||
9589 (!StaticPrefs::extensions_webextensions_remote() &&
9590 uri->SchemeIs("moz-extension"))) {
9591 return true;
9592 }
9593#ifdef MOZ_THUNDERBIRD
9594 if (uri->SchemeIs("imap") || uri->SchemeIs("mailbox") ||
9595 uri->SchemeIs("news") || uri->SchemeIs("nntp") ||
9596 uri->SchemeIs("snews") || uri->SchemeIs("x-moz-ews")) {
9597 return true;
9598 }
9599#endif
9600 nsAutoCString scheme;
9601 uri->GetScheme(scheme);
9602 // Allow ext+foo URIs (extension-registered custom protocols). See
9603 // https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/protocol_handlers
9604 if (StringBeginsWith(scheme, "ext+"_ns) &&
9605 !StaticPrefs::extensions_webextensions_remote()) {
9606 return true;
9607 }
9608 // Final exception for some legacy automated tests:
9609 if (xpc::IsInAutomation() &&
9610 StaticPrefs::security_allow_unsafe_parent_loads()) {
9611 return true;
9612 }
9613 return false;
9614}
9615
9616nsIPrincipal* nsDocShell::GetInheritedPrincipal(
9617 bool aConsiderCurrentDocument, bool aConsiderPartitionedPrincipal) {
9618 RefPtr<Document> document;
9619 bool inheritedFromCurrent = false;
9620
9621 if (aConsiderCurrentDocument && mDocumentViewer) {
9622 document = mDocumentViewer->GetDocument();
9623 inheritedFromCurrent = true;
9624 }
9625
9626 if (!document) {
9627 nsCOMPtr<nsIDocShellTreeItem> parentItem;
9628 GetInProcessSameTypeParent(getter_AddRefs(parentItem));
9629 if (parentItem) {
9630 document = parentItem->GetDocument();
9631 }
9632 }
9633
9634 if (!document) {
9635 if (!aConsiderCurrentDocument) {
9636 return nullptr;
9637 }
9638
9639 // Make sure we end up with _something_ as the principal no matter
9640 // what.If this fails, we'll just get a null docViewer and bail.
9641 EnsureDocumentViewer();
9642 if (!mDocumentViewer) {
9643 return nullptr;
9644 }
9645 document = mDocumentViewer->GetDocument();
9646 }
9647
9648 //-- Get the document's principal
9649 if (document) {
9650 nsIPrincipal* docPrincipal = aConsiderPartitionedPrincipal
9651 ? document->PartitionedPrincipal()
9652 : document->NodePrincipal();
9653
9654 // Don't allow loads in typeContent docShells to inherit the system
9655 // principal from existing documents.
9656 if (inheritedFromCurrent && mItemType == typeContent &&
9657 docPrincipal->IsSystemPrincipal()) {
9658 return nullptr;
9659 }
9660
9661 return docPrincipal;
9662 }
9663
9664 return nullptr;
9665}
9666
9667/* static */ nsresult nsDocShell::CreateRealChannelForDocument(
9668 nsIChannel** aChannel, nsIURI* aURI, nsILoadInfo* aLoadInfo,
9669 nsIInterfaceRequestor* aCallbacks, nsLoadFlags aLoadFlags,
9670 const nsAString& aSrcdoc, nsIURI* aBaseURI) {
9671 nsCOMPtr<nsIChannel> channel;
9672 if (aSrcdoc.IsVoid()) {
9673 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)
9674 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)
9675 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)
9676 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)
;
9677
9678 if (aBaseURI) {
9679 nsCOMPtr<nsIViewSourceChannel> vsc = do_QueryInterface(channel);
9680 if (vsc) {
9681 MOZ_ALWAYS_SUCCEEDS(vsc->SetBaseURI(aBaseURI))do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(vsc->SetBaseURI(aBaseURI))), 1)))), 1))) { } else { do { do
{ } while (false); MOZ_ReportCrash("" "NS_SUCCEEDED(vsc->SetBaseURI(aBaseURI))"
, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 9681); AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED(vsc->SetBaseURI(aBaseURI))"
")"); do { *((volatile int*)__null) = 9681; __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
;
9682 }
9683 }
9684 } else if (SchemeIsViewSource(aURI)) {
9685 // Instantiate view source handler protocol, if it doesn't exist already.
9686 nsCOMPtr<nsIIOService> io(do_GetIOService());
9687 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"
, 9687); AnnotateMozCrashReason("MOZ_ASSERT" "(" "io" ")"); do
{ *((volatile int*)__null) = 9687; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
9688 nsCOMPtr<nsIProtocolHandler> handler;
9689 nsresult rv =
9690 io->GetProtocolHandler("view-source", getter_AddRefs(handler));
9691 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
9692 return rv;
9693 }
9694
9695 nsViewSourceHandler* vsh = nsViewSourceHandler::GetInstance();
9696 if (!vsh) {
9697 return NS_ERROR_FAILURE;
9698 }
9699
9700 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)
9701 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)
;
9702 } else {
9703 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)
9704 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)
9705 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)
;
9706 nsCOMPtr<nsIInputStreamChannel> isc = do_QueryInterface(channel);
9707 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"
, 9707); AnnotateMozCrashReason("MOZ_ASSERT" "(" "isc" ")"); do
{ *((volatile int*)__null) = 9707; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
9708 isc->SetBaseURI(aBaseURI);
9709 }
9710
9711 if (aLoadFlags != nsIRequest::LOAD_NORMAL) {
9712 nsresult rv = channel->SetLoadFlags(aLoadFlags);
9713 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"
, 9713); return rv; } } while (false)
;
9714 }
9715
9716 channel.forget(aChannel);
9717 return NS_OK;
9718}
9719
9720/* static */ bool nsDocShell::CreateAndConfigureRealChannelForLoadState(
9721 BrowsingContext* aBrowsingContext, nsDocShellLoadState* aLoadState,
9722 LoadInfo* aLoadInfo, nsIInterfaceRequestor* aCallbacks,
9723 nsDocShell* aDocShell, const OriginAttributes& aOriginAttributes,
9724 nsLoadFlags aLoadFlags, uint32_t aCacheKey, nsresult& aRv,
9725 nsIChannel** aChannel) {
9726 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"
, 9726); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadInfo" ")"
); do { *((volatile int*)__null) = 9726; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9727
9728 nsString srcdoc = VoidString();
9729 bool isSrcdoc =
9730 aLoadState->HasInternalLoadFlags(INTERNAL_LOAD_FLAGS_IS_SRCDOC);
9731 if (isSrcdoc) {
9732 srcdoc = aLoadState->SrcdocData();
9733 }
9734
9735 aLoadInfo->SetTriggeringRemoteType(
9736 aLoadState->GetEffectiveTriggeringRemoteType());
9737
9738 if (aLoadState->PrincipalToInherit()) {
9739 aLoadInfo->SetPrincipalToInherit(aLoadState->PrincipalToInherit());
9740 }
9741 aLoadInfo->SetLoadTriggeredFromExternal(
9742 aLoadState->HasLoadFlags(LOAD_FLAGS_FROM_EXTERNAL));
9743 aLoadInfo->SetForceAllowDataURI(aLoadState->HasInternalLoadFlags(
9744 INTERNAL_LOAD_FLAGS_FORCE_ALLOW_DATA_URI));
9745 aLoadInfo->SetOriginalFrameSrcLoad(
9746 aLoadState->HasInternalLoadFlags(INTERNAL_LOAD_FLAGS_ORIGINAL_FRAME_SRC));
9747 aLoadInfo->SetIsNewWindowTarget(
9748 aLoadState->HasInternalLoadFlags(INTERNAL_LOAD_FLAGS_FIRST_LOAD));
9749
9750 bool inheritAttrs = false;
9751 if (aLoadState->PrincipalToInherit()) {
9752 inheritAttrs = nsContentUtils::ChannelShouldInheritPrincipal(
9753 aLoadState->PrincipalToInherit(), aLoadState->URI(),
9754 true, // aInheritForAboutBlank
9755 isSrcdoc);
9756 }
9757
9758 // Strip the target query parameters before creating the channel.
9759 aLoadState->MaybeStripTrackerQueryStrings(aBrowsingContext);
9760
9761 OriginAttributes attrs;
9762
9763 // Inherit origin attributes from PrincipalToInherit if inheritAttrs is
9764 // true. Otherwise we just use the origin attributes from docshell.
9765 if (inheritAttrs) {
9766 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"
, 9767); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->PrincipalToInherit()"
") (" "We should have PrincipalToInherit here." ")"); do { *
((volatile int*)__null) = 9767; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
9767 "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"
, 9767); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->PrincipalToInherit()"
") (" "We should have PrincipalToInherit here." ")"); do { *
((volatile int*)__null) = 9767; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
;
9768 attrs = aLoadState->PrincipalToInherit()->OriginAttributesRef();
9769 // If firstPartyIsolation is not enabled, then PrincipalToInherit should
9770 // have the same origin attributes with docshell.
9771 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"
, 9772); AnnotateMozCrashReason("MOZ_ASSERT" "(" "attrs == aOriginAttributes"
")"); do { *((volatile int*)__null) = 9772; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
9772 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"
, 9772); AnnotateMozCrashReason("MOZ_ASSERT" "(" "attrs == aOriginAttributes"
")"); do { *((volatile int*)__null) = 9772; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
9773 } else {
9774 attrs = aOriginAttributes;
9775 attrs.SetFirstPartyDomain(IsTopLevelDoc(aBrowsingContext, aLoadInfo),
9776 aLoadState->URI());
9777 }
9778
9779 aRv = aLoadInfo->SetOriginAttributes(attrs);
9780 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"
, 9780)
) {
9781 return false;
9782 }
9783
9784 if (aLoadState->GetIsFromProcessingFrameAttributes()) {
9785 aLoadInfo->SetIsFromProcessingFrameAttributes();
9786 }
9787
9788 // Propagate the IsFormSubmission flag to the loadInfo.
9789 if (aLoadState->IsFormSubmission()) {
9790 aLoadInfo->SetIsFormSubmission(true);
9791 }
9792
9793 aLoadInfo->SetUnstrippedURI(aLoadState->GetUnstrippedURI());
9794
9795 nsCOMPtr<nsIChannel> channel;
9796 aRv = CreateRealChannelForDocument(getter_AddRefs(channel), aLoadState->URI(),
9797 aLoadInfo, aCallbacks, aLoadFlags, srcdoc,
9798 aLoadState->BaseURI());
9799 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"
, 9799); return false; } } while (false)
;
9800
9801 if (!channel) {
9802 return false;
9803 }
9804
9805 // If the HTTPS-Only mode is enabled, every insecure request gets upgraded to
9806 // HTTPS by default. This behavior can be disabled through the loadinfo flag
9807 // HTTPS_ONLY_EXEMPT.
9808 nsHTTPSOnlyUtils::TestSitePermissionAndPotentiallyAddExemption(channel);
9809
9810 // hack
9811 nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(channel));
9812 nsCOMPtr<nsIHttpChannelInternal> httpChannelInternal(
9813 do_QueryInterface(channel));
9814 nsCOMPtr<nsIURI> referrer;
9815 nsIReferrerInfo* referrerInfo = aLoadState->GetReferrerInfo();
9816 if (referrerInfo) {
9817 referrerInfo->GetOriginalReferrer(getter_AddRefs(referrer));
9818 }
9819 if (httpChannelInternal) {
9820 if (aLoadState->HasInternalLoadFlags(
9821 INTERNAL_LOAD_FLAGS_FORCE_ALLOW_COOKIES)) {
9822 aRv = httpChannelInternal->SetThirdPartyFlags(
9823 nsIHttpChannelInternal::THIRD_PARTY_FORCE_ALLOW);
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 if (aLoadState->FirstParty()) {
9827 aRv = httpChannelInternal->SetDocumentURI(aLoadState->URI());
9828 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"
, 9828); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(aRv)), 1)))"
")"); do { *((volatile int*)__null) = 9828; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9829 } else {
9830 aRv = httpChannelInternal->SetDocumentURI(referrer);
9831 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"
, 9831); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(aRv)), 1)))"
")"); do { *((volatile int*)__null) = 9831; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9832 }
9833 aRv = httpChannelInternal->SetRedirectMode(
9834 nsIHttpChannelInternal::REDIRECT_MODE_MANUAL);
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 if (httpChannel) {
9839 if (aLoadState->HeadersStream()) {
9840 aRv = AddHeadersToChannel(aLoadState->HeadersStream(), httpChannel);
9841 }
9842 // Set the referrer explicitly
9843 // Referrer is currenly only set for link clicks here.
9844 if (referrerInfo) {
9845 aRv = httpChannel->SetReferrerInfo(referrerInfo);
9846 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"
, 9846); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(aRv)), 1)))"
")"); do { *((volatile int*)__null) = 9846; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9847 }
9848
9849 // Mark the http channel as UrgentStart for top level document loading in
9850 // active tab.
9851 if (IsUrgentStart(aBrowsingContext, aLoadInfo, aLoadState->LoadType())) {
9852 nsCOMPtr<nsIClassOfService> cos(do_QueryInterface(channel));
9853 if (cos) {
9854 cos->AddClassFlags(nsIClassOfService::UrgentStart);
9855 if (StaticPrefs::dom_document_priority_incremental()) {
9856 cos->SetIncremental(true);
9857 }
9858 }
9859 }
9860 }
9861
9862 channel->SetOriginalURI(aLoadState->OriginalURI() ? aLoadState->OriginalURI()
9863 : aLoadState->URI());
9864
9865 const nsACString& typeHint = aLoadState->TypeHint();
9866 if (!typeHint.IsVoid()) {
9867 channel->SetContentType(typeHint);
9868 }
9869
9870 const nsAString& fileName = aLoadState->FileName();
9871 if (!fileName.IsVoid()) {
9872 aRv = channel->SetContentDisposition(nsIChannel::DISPOSITION_ATTACHMENT);
9873 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"
, 9873); return false; } } while (false)
;
9874 if (!fileName.IsEmpty()) {
9875 aRv = channel->SetContentDispositionFilename(fileName);
9876 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"
, 9876); return false; } } while (false)
;
9877 }
9878 }
9879
9880 if (nsCOMPtr<nsIWritablePropertyBag2> props = do_QueryInterface(channel)) {
9881 nsCOMPtr<nsIURI> referrer;
9882 nsIReferrerInfo* referrerInfo = aLoadState->GetReferrerInfo();
9883 if (referrerInfo) {
9884 referrerInfo->GetOriginalReferrer(getter_AddRefs(referrer));
9885 }
9886 // save true referrer for those who need it (e.g. xpinstall whitelisting)
9887 // Currently only http and ftp channels support this.
9888 props->SetPropertyAsInterface(u"docshell.internalReferrer"_ns, referrer);
9889 }
9890
9891 nsCOMPtr<nsICacheInfoChannel> cacheChannel(do_QueryInterface(channel));
9892 auto loadType = aLoadState->LoadType();
9893
9894 if (loadType == LOAD_RELOAD_NORMAL &&
9895 StaticPrefs::
9896 browser_soft_reload_only_force_validate_top_level_document()) {
9897 nsCOMPtr<nsICacheInfoChannel> cachingChannel = do_QueryInterface(channel);
9898 if (cachingChannel) {
9899 cachingChannel->SetForceValidateCacheContent(true);
9900 }
9901 }
9902
9903 // figure out if we need to set the post data stream on the channel...
9904 if (aLoadState->PostDataStream()) {
9905 if (nsCOMPtr<nsIFormPOSTActionChannel> postChannel =
9906 do_QueryInterface(channel)) {
9907 // XXX it's a bit of a hack to rewind the postdata stream here but
9908 // it has to be done in case the post data is being reused multiple
9909 // times.
9910 nsCOMPtr<nsISeekableStream> postDataSeekable =
9911 do_QueryInterface(aLoadState->PostDataStream());
9912 if (postDataSeekable) {
9913 aRv = postDataSeekable->Seek(nsISeekableStream::NS_SEEK_SET, 0);
9914 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"
, 9914); return false; } } while (false)
;
9915 }
9916
9917 // we really need to have a content type associated with this stream!!
9918 postChannel->SetUploadStream(aLoadState->PostDataStream(), ""_ns, -1);
9919
9920 // Ownership of the stream has transferred to the channel, clear our
9921 // reference.
9922 aLoadState->SetPostDataStream(nullptr);
9923 }
9924
9925 /* If there is a valid postdata *and* it is a History Load,
9926 * set up the cache key on the channel, to retrieve the
9927 * data *only* from the cache. If it is a normal reload, the
9928 * cache is free to go to the server for updated postdata.
9929 */
9930 if (cacheChannel && aCacheKey != 0) {
9931 if (loadType == LOAD_HISTORY || loadType == LOAD_RELOAD_CHARSET_CHANGE) {
9932 cacheChannel->SetCacheKey(aCacheKey);
9933 uint32_t loadFlags;
9934 if (NS_SUCCEEDED(channel->GetLoadFlags(&loadFlags))((bool)(__builtin_expect(!!(!NS_FAILED_impl(channel->GetLoadFlags
(&loadFlags))), 1)))
) {
9935 channel->SetLoadFlags(loadFlags |
9936 nsICachingChannel::LOAD_ONLY_FROM_CACHE);
9937 }
9938 } else if (loadType == LOAD_RELOAD_NORMAL) {
9939 cacheChannel->SetCacheKey(aCacheKey);
9940 }
9941 }
9942 } else {
9943 /* If there is no postdata, set the cache key on the channel, and
9944 * do not set the LOAD_ONLY_FROM_CACHE flag, so that the channel
9945 * will be free to get it from net if it is not found in cache.
9946 * New cache may use it creatively on CGI pages with GET
9947 * method and even on those that say "no-cache"
9948 */
9949 if (loadType == LOAD_HISTORY || loadType == LOAD_RELOAD_NORMAL ||
9950 loadType == LOAD_RELOAD_CHARSET_CHANGE ||
9951 loadType == LOAD_RELOAD_CHARSET_CHANGE_BYPASS_CACHE ||
9952 loadType == LOAD_RELOAD_CHARSET_CHANGE_BYPASS_PROXY_AND_CACHE) {
9953 if (cacheChannel && aCacheKey != 0) {
9954 cacheChannel->SetCacheKey(aCacheKey);
9955 }
9956 }
9957 }
9958
9959 if (nsCOMPtr<nsIScriptChannel> scriptChannel = do_QueryInterface(channel)) {
9960 // Allow execution against our context if the principals match
9961 scriptChannel->SetExecutionPolicy(nsIScriptChannel::EXECUTE_NORMAL);
9962 }
9963
9964 if (nsCOMPtr<nsITimedChannel> timedChannel = do_QueryInterface(channel)) {
9965 nsString initiatorType;
9966 switch (aLoadInfo->InternalContentPolicyType()) {
9967 case nsIContentPolicy::TYPE_INTERNAL_EMBED:
9968 initiatorType = u"embed"_ns;
9969 break;
9970 case nsIContentPolicy::TYPE_INTERNAL_OBJECT:
9971 initiatorType = u"object"_ns;
9972 break;
9973 default: {
9974 const auto& embedderElementType =
9975 aBrowsingContext->GetEmbedderElementType();
9976 if (embedderElementType) {
9977 initiatorType = *embedderElementType;
9978 }
9979 break;
9980 }
9981 }
9982
9983 if (!initiatorType.IsEmpty()) {
9984 timedChannel->SetInitiatorType(initiatorType);
9985 }
9986 }
9987
9988 nsCOMPtr<nsIURI> rpURI;
9989 aLoadInfo->GetResultPrincipalURI(getter_AddRefs(rpURI));
9990 Maybe<nsCOMPtr<nsIURI>> originalResultPrincipalURI;
9991 aLoadState->GetMaybeResultPrincipalURI(originalResultPrincipalURI);
9992 if (originalResultPrincipalURI &&
9993 (!aLoadState->KeepResultPrincipalURIIfSet() || !rpURI)) {
9994 // Unconditionally override, we want the replay to be equal to what has
9995 // been captured.
9996 aLoadInfo->SetResultPrincipalURI(originalResultPrincipalURI.ref());
9997 }
9998
9999 if (aLoadState->OriginalURI() && aLoadState->LoadReplace()) {
10000 // The LOAD_REPLACE flag and its handling here will be removed as part
10001 // of bug 1319110. For now preserve its restoration here to not break
10002 // any code expecting it being set specially on redirected channels.
10003 // If the flag has originally been set to change result of
10004 // NS_GetFinalChannelURI it won't have any effect and also won't cause
10005 // any harm.
10006 uint32_t loadFlags;
10007 aRv = channel->GetLoadFlags(&loadFlags);
10008 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"
, 10008); return false; } } while (false)
;
10009 channel->SetLoadFlags(loadFlags | nsIChannel::LOAD_REPLACE);
10010 }
10011
10012 nsCOMPtr<nsIContentSecurityPolicy> csp = aLoadState->Csp();
10013 if (csp) {
10014 // Navigational requests that are same origin need to be upgraded in case
10015 // upgrade-insecure-requests is present. Please note that for document
10016 // navigations that bit is re-computed in case we encounter a server
10017 // side redirect so the navigation is not same-origin anymore.
10018 bool upgradeInsecureRequests = false;
10019 csp->GetUpgradeInsecureRequests(&upgradeInsecureRequests);
10020 if (upgradeInsecureRequests) {
10021 // only upgrade if the navigation is same origin
10022 nsCOMPtr<nsIPrincipal> resultPrincipal;
10023 aRv = nsContentUtils::GetSecurityManager()->GetChannelResultPrincipal(
10024 channel, getter_AddRefs(resultPrincipal));
10025 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"
, 10025); return false; } } while (false)
;
10026 if (nsContentSecurityUtils::IsConsideredSameOriginForUIR(
10027 aLoadState->TriggeringPrincipal(), resultPrincipal)) {
10028 aLoadInfo->SetUpgradeInsecureRequests(true);
10029 }
10030 }
10031
10032 // For document loads we store the CSP that potentially needs to
10033 // be inherited by the new document, e.g. in case we are loading
10034 // an opaque origin like a data: URI. The actual inheritance
10035 // check happens within Document::InitCSP().
10036 // Please create an actual copy of the CSP (do not share the same
10037 // reference) otherwise a Meta CSP of an opaque origin will
10038 // incorrectly be propagated to the embedding document.
10039 RefPtr<nsCSPContext> cspToInherit = new nsCSPContext();
10040 cspToInherit->InitFromOther(static_cast<nsCSPContext*>(csp.get()));
10041 aLoadInfo->SetCSPToInherit(cspToInherit);
10042 }
10043
10044 channel.forget(aChannel);
10045 return true;
10046}
10047
10048bool nsDocShell::IsAboutBlankLoadOntoInitialAboutBlank(
10049 nsIURI* aURI, bool aInheritPrincipal, nsIPrincipal* aPrincipalToInherit) {
10050 return NS_IsAboutBlankAllowQueryAndFragment(aURI) && aInheritPrincipal &&
10051 (aPrincipalToInherit == GetInheritedPrincipal(false)) &&
10052 (!mDocumentViewer || !mDocumentViewer->GetDocument() ||
10053 mDocumentViewer->GetDocument()->IsInitialDocument());
10054}
10055
10056nsresult nsDocShell::DoURILoad(nsDocShellLoadState* aLoadState,
10057 Maybe<uint32_t> aCacheKey,
10058 nsIRequest** aRequest) {
10059 // Double-check that we're still around to load this URI.
10060 if (mIsBeingDestroyed) {
10061 // Return NS_OK despite not doing anything to avoid throwing exceptions
10062 // from nsLocation::SetHref if the unload handler of the existing page
10063 // tears us down.
10064 return NS_OK;
10065 }
10066
10067 nsCOMPtr<nsIURILoader> uriLoader = components::URILoader::Service();
10068 if (NS_WARN_IF(!uriLoader)NS_warn_if_impl(!uriLoader, "!uriLoader", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 10068)
) {
10069 return NS_ERROR_UNEXPECTED;
10070 }
10071
10072 // Persist and sync layout history state before we load a new uri, as this
10073 // might be our last chance to do so, in the content process.
10074 PersistLayoutHistoryState();
10075 SynchronizeLayoutHistoryState();
10076
10077 nsresult rv;
10078 nsContentPolicyType contentPolicyType = DetermineContentType();
10079
10080 if (IsSubframe()) {
10081 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"
, 10083); 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) = 10083; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
10082 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"
, 10083); 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) = 10083; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
10083 "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"
, 10083); 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) = 10083; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10084
10085 if (auto* iframe = HTMLIFrameElement::FromNodeOrNull(
10086 mBrowsingContext->GetEmbedderElement())) {
10087 // Per spec, reload doesn't cacel lazy loading iframes.
10088 if (!(aLoadState->LoadType() & LOAD_RELOAD_NORMAL)) {
10089 iframe->CancelLazyLoading(true /* aClearLazyLoadState */);
10090 }
10091 }
10092
10093 if (StaticPrefs::dom_block_external_protocol_in_iframes()) {
10094 // Only allow URLs able to return data in iframes.
10095 if (nsContentUtils::IsExternalProtocol(aLoadState->URI())) {
10096 // The context to check user-interaction with for the purposes of
10097 // popup-blocking.
10098 //
10099 // We generally want to check the context that initiated the navigation.
10100 WindowContext* sourceWindowContext = [&] {
10101 const MaybeDiscardedBrowsingContext& sourceBC =
10102 aLoadState->SourceBrowsingContext();
10103 if (!sourceBC.IsNullOrDiscarded()) {
10104 if (WindowContext* wc = sourceBC.get()->GetCurrentWindowContext()) {
10105 return wc;
10106 }
10107 }
10108 return mBrowsingContext->GetParentWindowContext();
10109 }();
10110
10111 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"
, 10111); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sourceWindowContext"
")"); do { *((volatile int*)__null) = 10111; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10112 // FIXME: We can't check user-interaction against an OOP window. This is
10113 // the next best thing we can really do. The load state keeps whether
10114 // the navigation had a user interaction in process
10115 // (aLoadState->HasValidUserGestureActivation()), but we can't really
10116 // consume it, which we want to prevent popup-spamming from the same
10117 // click event.
10118 WindowContext* context =
10119 sourceWindowContext->IsInProcess()
10120 ? sourceWindowContext
10121 : mBrowsingContext->GetCurrentWindowContext();
10122 const bool popupBlocked = [&] {
10123 const bool active = mBrowsingContext->IsActive();
10124
10125 // For same-origin-with-top windows, we grant a single free popup
10126 // without user activation, see bug 1680721.
10127 //
10128 // We consume the flag now even if there's no user activation.
10129 const bool hasFreePass = [&] {
10130 if (!active ||
10131 !(context->IsInProcess() && context->SameOriginWithTop())) {
10132 return false;
10133 }
10134 nsGlobalWindowInner* win =
10135 context->TopWindowContext()->GetInnerWindow();
10136 return win && win->TryOpenExternalProtocolIframe();
10137 }();
10138
10139 if (context->IsInProcess() &&
10140 context->ConsumeTransientUserGestureActivation()) {
10141 // If the user has interacted with the page, consume it.
10142 return false;
10143 }
10144
10145 // TODO(emilio): Can we remove this check? It seems like what prompted
10146 // this code (bug 1514547) should be covered by transient user
10147 // activation, see bug 1514547.
10148 if (active &&
10149 PopupBlocker::ConsumeTimerTokenForExternalProtocolIframe()) {
10150 return false;
10151 }
10152
10153 if (sourceWindowContext->CanShowPopup()) {
10154 return false;
10155 }
10156
10157 if (hasFreePass) {
10158 return false;
10159 }
10160
10161 return true;
10162 }();
10163
10164 // No error must be returned when iframes are blocked.
10165 if (popupBlocked) {
10166 nsAutoString message;
10167 nsresult rv = nsContentUtils::GetLocalizedString(
10168 nsContentUtils::eDOM_PROPERTIES,
10169 "ExternalProtocolFrameBlockedNoUserActivation", message);
10170 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
10171 nsContentUtils::ReportToConsoleByWindowID(
10172 message, nsIScriptError::warningFlag, "DOM"_ns,
10173 context->InnerWindowId());
10174 }
10175 return NS_OK;
10176 }
10177 }
10178 }
10179
10180 // Only allow view-source scheme in top-level docshells. view-source is
10181 // the only scheme to which this applies at the moment due to potential
10182 // timing attacks to read data from cross-origin iframes. If this widens
10183 // we should add a protocol flag for whether the scheme is allowed in
10184 // frames and use something like nsNetUtil::NS_URIChainHasFlags.
10185 nsCOMPtr<nsIURI> tempURI = aLoadState->URI();
10186 nsCOMPtr<nsINestedURI> nestedURI = do_QueryInterface(tempURI);
10187 while (nestedURI) {
10188 // view-source should always be an nsINestedURI, loop and check the
10189 // scheme on this and all inner URIs that are also nested URIs.
10190 if (SchemeIsViewSource(tempURI)) {
10191 return NS_ERROR_UNKNOWN_PROTOCOL;
10192 }
10193 nestedURI->GetInnerURI(getter_AddRefs(tempURI));
10194 nestedURI = do_QueryInterface(tempURI);
10195 }
10196 } else {
10197 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"
, 10198); AnnotateMozCrashReason("MOZ_ASSERT" "(" "contentPolicyType == nsIContentPolicy::TYPE_DOCUMENT"
") (" "DoURILoad thinks this is a document and InternalLoad does not"
")"); do { *((volatile int*)__null) = 10198; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
10198 "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"
, 10198); AnnotateMozCrashReason("MOZ_ASSERT" "(" "contentPolicyType == nsIContentPolicy::TYPE_DOCUMENT"
") (" "DoURILoad thinks this is a document and InternalLoad does not"
")"); do { *((volatile int*)__null) = 10198; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10199 }
10200
10201 // We want to inherit aLoadState->PrincipalToInherit() when:
10202 // 1. ChannelShouldInheritPrincipal returns true.
10203 // 2. aLoadState->URI() is not data: URI, or data: URI is not
10204 // configured as unique opaque origin.
10205 bool inheritPrincipal = false;
10206
10207 if (aLoadState->PrincipalToInherit()) {
10208 bool isSrcdoc =
10209 aLoadState->HasInternalLoadFlags(INTERNAL_LOAD_FLAGS_IS_SRCDOC);
10210 bool inheritAttrs = nsContentUtils::ChannelShouldInheritPrincipal(
10211 aLoadState->PrincipalToInherit(), aLoadState->URI(),
10212 true, // aInheritForAboutBlank
10213 isSrcdoc);
10214
10215 inheritPrincipal = inheritAttrs && !SchemeIsData(aLoadState->URI());
10216 }
10217
10218 // See https://bugzilla.mozilla.org/show_bug.cgi?id=1736570
10219 const bool isAboutBlankLoadOntoInitialAboutBlank =
10220 IsAboutBlankLoadOntoInitialAboutBlank(aLoadState->URI(), inheritPrincipal,
10221 aLoadState->PrincipalToInherit());
10222
10223 // FIXME We still have a ton of codepaths that don't pass through
10224 // DocumentLoadListener, so probably need to create session history info
10225 // in more places.
10226 if (aLoadState->GetLoadingSessionHistoryInfo()) {
10227 SetLoadingSessionHistoryInfo(*aLoadState->GetLoadingSessionHistoryInfo());
10228 } else if (isAboutBlankLoadOntoInitialAboutBlank &&
10229 mozilla::SessionHistoryInParent()) {
10230 // Materialize LoadingSessionHistoryInfo here, because DocumentChannel
10231 // loads have it, and later history behavior depends on it existing.
10232 UniquePtr<SessionHistoryInfo> entry = MakeUnique<SessionHistoryInfo>(
10233 aLoadState->URI(), aLoadState->TriggeringPrincipal(),
10234 aLoadState->PrincipalToInherit(),
10235 aLoadState->PartitionedPrincipalToInherit(), aLoadState->Csp(),
10236 mContentTypeHint);
10237 mozilla::dom::LoadingSessionHistoryInfo info(*entry);
10238 SetLoadingSessionHistoryInfo(info, true);
10239 }
10240
10241 // open a channel for the url
10242
10243 // If we have a pending channel, use the channel we've already created here.
10244 // We don't need to set up load flags for our channel, as it has already been
10245 // created.
10246
10247 if (nsCOMPtr<nsIChannel> channel =
10248 aLoadState->GetPendingRedirectedChannel()) {
10249 // If we have a request outparameter, shove our channel into it.
10250 if (aRequest) {
10251 nsCOMPtr<nsIRequest> outRequest = channel;
10252 outRequest.forget(aRequest);
10253 }
10254
10255 return OpenRedirectedChannel(aLoadState);
10256 }
10257
10258 // There are two cases we care about:
10259 // * Top-level load: In this case, loadingNode is null, but loadingWindow
10260 // is our mScriptGlobal. We pass null for loadingPrincipal in this case.
10261 // * Subframe load: loadingWindow is null, but loadingNode is the frame
10262 // element for the load. loadingPrincipal is the NodePrincipal of the
10263 // frame element.
10264 nsCOMPtr<nsINode> loadingNode;
10265 nsCOMPtr<nsPIDOMWindowOuter> loadingWindow;
10266 nsCOMPtr<nsIPrincipal> loadingPrincipal;
10267 nsCOMPtr<nsISupports> topLevelLoadingContext;
10268
10269 if (contentPolicyType == nsIContentPolicy::TYPE_DOCUMENT) {
10270 loadingNode = nullptr;
10271 loadingPrincipal = nullptr;
10272 loadingWindow = mScriptGlobal;
10273 if (XRE_IsContentProcess()) {
10274 // In e10s the child process doesn't have access to the element that
10275 // contains the browsing context (because that element is in the chrome
10276 // process).
10277 nsCOMPtr<nsIBrowserChild> browserChild = GetBrowserChild();
10278 topLevelLoadingContext = ToSupports(browserChild);
10279 } else {
10280 // This is for loading non-e10s tabs and toplevel windows of various
10281 // sorts.
10282 // For the toplevel window cases, requestingElement will be null.
10283 nsCOMPtr<Element> requestingElement =
10284 loadingWindow->GetFrameElementInternal();
10285 topLevelLoadingContext = requestingElement;
10286 }
10287 } else {
10288 loadingWindow = nullptr;
10289 loadingNode = mScriptGlobal->GetFrameElementInternal();
10290 if (loadingNode) {
10291 // If we have a loading node, then use that as our loadingPrincipal.
10292 loadingPrincipal = loadingNode->NodePrincipal();
10293#ifdef DEBUG1
10294 // Get the docshell type for requestingElement.
10295 RefPtr<Document> requestingDoc = loadingNode->OwnerDoc();
10296 nsCOMPtr<nsIDocShell> elementDocShell = requestingDoc->GetDocShell();
10297 // requestingElement docshell type = current docshell type.
10298 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"
, 10300); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mItemType == elementDocShell->ItemType()"
") (" "subframes should have the same docshell type as their parent"
")"); do { *((volatile int*)__null) = 10300; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
10299 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"
, 10300); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mItemType == elementDocShell->ItemType()"
") (" "subframes should have the same docshell type as their parent"
")"); do { *((volatile int*)__null) = 10300; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
10300 "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"
, 10300); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mItemType == elementDocShell->ItemType()"
") (" "subframes should have the same docshell type as their parent"
")"); do { *((volatile int*)__null) = 10300; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10301#endif
10302 } else {
10303 if (mIsBeingDestroyed) {
10304 // If this isn't a top-level load and mScriptGlobal's frame element is
10305 // null, then the element got removed from the DOM while we were trying
10306 // to load this resource. This docshell is scheduled for destruction
10307 // already, so bail out here.
10308 return NS_OK;
10309 }
10310 // If we are not being destroyed and we do not have access to the loading
10311 // node, then we are a remote subframe. Set the loading principal
10312 // to be a null principal and then set it correctly in the parent.
10313 loadingPrincipal = NullPrincipal::Create(GetOriginAttributes(), nullptr);
10314 }
10315 }
10316
10317 if (!aLoadState->TriggeringPrincipal()) {
10318 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"
, 10318); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"DoURILoad needs a valid triggeringPrincipal" ")"); do { *((
volatile int*)__null) = 10318; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
;
10319 return NS_ERROR_FAILURE;
10320 }
10321
10322 uint32_t sandboxFlags = mBrowsingContext->GetSandboxFlags();
10323 nsSecurityFlags securityFlags =
10324 nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_SEC_CONTEXT_IS_NULL;
10325
10326 if (mLoadType == LOAD_ERROR_PAGE) {
10327 securityFlags |= nsILoadInfo::SEC_LOAD_ERROR_PAGE;
10328 }
10329
10330 if (inheritPrincipal) {
10331 securityFlags |= nsILoadInfo::SEC_FORCE_INHERIT_PRINCIPAL;
10332 }
10333
10334 // Must never have a parent for TYPE_DOCUMENT loads
10335 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"
, 10336); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mBrowsingContext->GetParent()"
")"); do { *((volatile int*)__null) = 10336; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false); } } while
(false)
10336 !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"
, 10336); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mBrowsingContext->GetParent()"
")"); do { *((volatile int*)__null) = 10336; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false); } } while
(false)
;
10337 // Subdocuments must have a parent
10338 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"
, 10339); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mBrowsingContext->GetParent()"
")"); do { *((volatile int*)__null) = 10339; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false); } } while
(false)
10339 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"
, 10339); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mBrowsingContext->GetParent()"
")"); do { *((volatile int*)__null) = 10339; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false); } } while
(false)
;
10340 mBrowsingContext->SetTriggeringAndInheritPrincipals(
10341 aLoadState->TriggeringPrincipal(), aLoadState->PrincipalToInherit(),
10342 aLoadState->GetLoadIdentifier());
10343 RefPtr<LoadInfo> loadInfo =
10344 (contentPolicyType == nsIContentPolicy::TYPE_DOCUMENT)
10345 ? new LoadInfo(loadingWindow, aLoadState->URI(),
10346 aLoadState->TriggeringPrincipal(),
10347 topLevelLoadingContext, securityFlags, sandboxFlags)
10348 : new LoadInfo(loadingPrincipal, aLoadState->TriggeringPrincipal(),
10349 loadingNode, securityFlags, contentPolicyType,
10350 Maybe<mozilla::dom::ClientInfo>(),
10351 Maybe<mozilla::dom::ServiceWorkerDescriptor>(),
10352 sandboxFlags);
10353 RefPtr<WindowContext> context = mBrowsingContext->GetCurrentWindowContext();
10354
10355 if (isAboutBlankLoadOntoInitialAboutBlank) {
10356 // Match the DocumentChannel case where the default for third-partiness
10357 // differs from the default in LoadInfo construction here.
10358 // toolkit/components/antitracking/test/browser/browser_aboutblank.js
10359 // fails without this.
10360 BrowsingContext* top = mBrowsingContext->Top();
10361 if (top == mBrowsingContext) {
10362 // If we're at the top, this must be a window.open()ed
10363 // window, and we can't be third-party relative to ourselves.
10364 loadInfo->SetIsThirdPartyContextToTopWindow(false);
10365 } else {
10366 if (Document* topDoc = top->GetDocument()) {
10367 bool thirdParty = false;
10368 mozilla::Unused << topDoc->GetPrincipal()->IsThirdPartyPrincipal(
10369 aLoadState->PrincipalToInherit(), &thirdParty);
10370 loadInfo->SetIsThirdPartyContextToTopWindow(thirdParty);
10371 } else {
10372 // If top is in a different process, we have to be third-party relative
10373 // to it.
10374 loadInfo->SetIsThirdPartyContextToTopWindow(true);
10375 }
10376 }
10377 }
10378
10379 if (mLoadType != LOAD_ERROR_PAGE && context && context->IsInProcess()) {
10380 if (context->HasValidTransientUserGestureActivation()) {
10381 aLoadState->SetHasValidUserGestureActivation(true);
10382 aLoadState->SetTextDirectiveUserActivation(true);
10383 }
10384 if (!aLoadState->TriggeringWindowId()) {
10385 aLoadState->SetTriggeringWindowId(context->Id());
10386 }
10387 if (!aLoadState->TriggeringStorageAccess()) {
10388 Document* contextDoc = context->GetExtantDoc();
10389 if (contextDoc) {
10390 aLoadState->SetTriggeringStorageAccess(
10391 contextDoc->UsingStorageAccess());
10392 }
10393 }
10394 }
10395
10396 // in case this docshell load was triggered by a valid transient user gesture,
10397 // or also the load originates from external, then we pass that information on
10398 // to the loadinfo, which allows e.g. setting Sec-Fetch-User request headers.
10399 if (aLoadState->HasValidUserGestureActivation() ||
10400 aLoadState->HasLoadFlags(LOAD_FLAGS_FROM_EXTERNAL)) {
10401 loadInfo->SetHasValidUserGestureActivation(true);
10402 aLoadState->SetTextDirectiveUserActivation(true);
10403 }
10404
10405 loadInfo->SetTextDirectiveUserActivation(
10406 aLoadState->GetTextDirectiveUserActivation());
10407
10408 loadInfo->SetTriggeringWindowId(aLoadState->TriggeringWindowId());
10409 loadInfo->SetTriggeringStorageAccess(aLoadState->TriggeringStorageAccess());
10410 loadInfo->SetTriggeringSandboxFlags(aLoadState->TriggeringSandboxFlags());
10411 loadInfo->SetIsMetaRefresh(aLoadState->IsMetaRefresh());
10412
10413 uint32_t cacheKey = 0;
10414 if (aCacheKey) {
10415 cacheKey = *aCacheKey;
10416 } else if (mozilla::SessionHistoryInParent()) {
10417 if (mLoadingEntry) {
10418 cacheKey = mLoadingEntry->mInfo.GetCacheKey();
10419 } else if (mActiveEntry) { // for reload cases
10420 cacheKey = mActiveEntry->GetCacheKey();
10421 }
10422 } else {
10423 if (mLSHE) {
10424 cacheKey = mLSHE->GetCacheKey();
10425 } else if (mOSHE) { // for reload cases
10426 cacheKey = mOSHE->GetCacheKey();
10427 }
10428 }
10429
10430 bool uriModified;
10431 if (mLSHE || mLoadingEntry) {
10432 if (mLoadingEntry) {
10433 uriModified = mLoadingEntry->mInfo.GetURIWasModified();
10434 } else {
10435 uriModified = mLSHE->GetURIWasModified();
10436 }
10437 } else {
10438 uriModified = false;
10439 }
10440
10441 bool isEmbeddingBlockedError = false;
10442 if (mFailedChannel) {
10443 nsresult status;
10444 mFailedChannel->GetStatus(&status);
10445 isEmbeddingBlockedError = status == NS_ERROR_XFO_VIOLATION ||
10446 status == NS_ERROR_CSP_FRAME_ANCESTOR_VIOLATION;
10447 }
10448
10449 nsLoadFlags loadFlags = aLoadState->CalculateChannelLoadFlags(
10450 mBrowsingContext, uriModified, Some(isEmbeddingBlockedError));
10451
10452 nsCOMPtr<nsIChannel> channel;
10453 if (DocumentChannel::CanUseDocumentChannel(aLoadState->URI()) &&
10454 !isAboutBlankLoadOntoInitialAboutBlank) {
10455 channel = DocumentChannel::CreateForDocument(
10456 aLoadState, loadInfo, loadFlags, this, cacheKey, uriModified,
10457 isEmbeddingBlockedError);
10458 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"
, 10458); AnnotateMozCrashReason("MOZ_ASSERT" "(" "channel" ")"
); do { *((volatile int*)__null) = 10458; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
10459
10460 // Disable keyword fixup when using DocumentChannel, since
10461 // DocumentLoadListener will handle this for us (in the parent process).
10462 mAllowKeywordFixup = false;
10463 } else if (!CreateAndConfigureRealChannelForLoadState(
10464 mBrowsingContext, aLoadState, loadInfo, this, this,
10465 GetOriginAttributes(), loadFlags, cacheKey, rv,
10466 getter_AddRefs(channel))) {
10467 return rv;
10468 }
10469
10470 // Make sure to give the caller a channel if we managed to create one
10471 // This is important for correct error page/session history interaction
10472 if (aRequest) {
10473 NS_ADDREF(*aRequest = channel)(*aRequest = channel)->AddRef();
10474 }
10475
10476 const nsACString& typeHint = aLoadState->TypeHint();
10477 if (!typeHint.IsVoid()) {
10478 mContentTypeHint = typeHint;
10479 } else {
10480 mContentTypeHint.Truncate();
10481 }
10482
10483 // Load attributes depend on load type...
10484 if (mLoadType == LOAD_RELOAD_CHARSET_CHANGE) {
10485 // Use SetAllowStaleCacheContent (not LOAD_FROM_CACHE flag) since we
10486 // only want to force cache load for this channel, not the whole
10487 // loadGroup.
10488 nsCOMPtr<nsICacheInfoChannel> cachingChannel = do_QueryInterface(channel);
10489 if (cachingChannel) {
10490 cachingChannel->SetAllowStaleCacheContent(true);
10491 }
10492 }
10493
10494 uint32_t openFlags =
10495 nsDocShell::ComputeURILoaderFlags(mBrowsingContext, mLoadType);
10496 return OpenInitializedChannel(channel, uriLoader, openFlags);
10497}
10498
10499static nsresult AppendSegmentToString(nsIInputStream* aIn, void* aClosure,
10500 const char* aFromRawSegment,
10501 uint32_t aToOffset, uint32_t aCount,
10502 uint32_t* aWriteCount) {
10503 // aFromSegment now contains aCount bytes of data.
10504
10505 nsAutoCString* buf = static_cast<nsAutoCString*>(aClosure);
10506 buf->Append(aFromRawSegment, aCount);
10507
10508 // Indicate that we have consumed all of aFromSegment
10509 *aWriteCount = aCount;
10510 return NS_OK;
10511}
10512
10513/* static */ nsresult nsDocShell::AddHeadersToChannel(
10514 nsIInputStream* aHeadersData, nsIChannel* aGenericChannel) {
10515 nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(aGenericChannel);
10516 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"
, 10516); return NS_ERROR_UNEXPECTED; } } while (false)
;
10517
10518 uint32_t numRead;
10519 nsAutoCString headersString;
10520 nsresult rv = aHeadersData->ReadSegments(
10521 AppendSegmentToString, &headersString, UINT32_MAX(4294967295U), &numRead);
10522 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"
, 10522); return rv; } } while (false)
;
10523
10524 // used during the manipulation of the String from the InputStream
10525 nsAutoCString headerName;
10526 nsAutoCString headerValue;
10527 int32_t crlf;
10528 int32_t colon;
10529
10530 //
10531 // Iterate over the headersString: for each "\r\n" delimited chunk,
10532 // add the value as a header to the nsIHttpChannel
10533 //
10534
10535 static const char kWhitespace[] = "\b\t\r\n ";
10536 while (true) {
10537 crlf = headersString.Find("\r\n");
10538 if (crlf == kNotFound) {
10539 return NS_OK;
10540 }
10541
10542 const nsACString& oneHeader = StringHead(headersString, crlf);
10543
10544 colon = oneHeader.FindChar(':');
10545 if (colon == kNotFound) {
10546 return NS_ERROR_UNEXPECTED;
10547 }
10548
10549 headerName = StringHead(oneHeader, colon);
10550 headerValue = Substring(oneHeader, colon + 1);
10551
10552 headerName.Trim(kWhitespace);
10553 headerValue.Trim(kWhitespace);
10554
10555 headersString.Cut(0, crlf + 2);
10556
10557 //
10558 // FINALLY: we can set the header!
10559 //
10560
10561 rv = httpChannel->SetRequestHeader(headerName, headerValue, true);
10562 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"
, 10562); return rv; } } while (false)
;
10563 }
10564
10565 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"
, 10565); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "oops" ")"); do { *((volatile int
*)__null) = 10565; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
10566 return NS_ERROR_UNEXPECTED;
10567}
10568
10569/* static */ uint32_t nsDocShell::ComputeURILoaderFlags(
10570 BrowsingContext* aBrowsingContext, uint32_t aLoadType,
10571 bool aIsDocumentLoad) {
10572 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"
, 10572); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aBrowsingContext"
")"); do { *((volatile int*)__null) = 10572; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10573
10574 uint32_t openFlags = 0;
10575 if (aLoadType == LOAD_LINK) {
10576 openFlags |= nsIURILoader::IS_CONTENT_PREFERRED;
10577 }
10578 if (!aBrowsingContext->GetAllowContentRetargeting()) {
10579 openFlags |= nsIURILoader::DONT_RETARGET;
10580 }
10581
10582 // Unless the pref is set, object/embed loads always specify DONT_RETARGET.
10583 // See bug 1868001 for details.
10584 if (!aIsDocumentLoad &&
10585 !StaticPrefs::dom_navigation_object_embed_allow_retargeting()) {
10586 openFlags |= nsIURILoader::DONT_RETARGET;
10587 }
10588
10589 return openFlags;
10590}
10591
10592nsresult nsDocShell::OpenInitializedChannel(nsIChannel* aChannel,
10593 nsIURILoader* aURILoader,
10594 uint32_t aOpenFlags) {
10595 nsresult rv = NS_OK;
10596
10597 // If anything fails here, make sure to clear our initial ClientSource.
10598 auto cleanupInitialClient =
10599 MakeScopeExit([&] { mInitialClientSource.reset(); });
10600
10601 nsCOMPtr<nsPIDOMWindowOuter> win = GetWindow();
10602 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"
, 10602); return NS_ERROR_FAILURE; } } while (false)
;
10603
10604 MaybeCreateInitialClientSource();
10605
10606 // Let the client channel helper know if we are using DocumentChannel,
10607 // since redirects get handled in the parent process in that case.
10608 RefPtr<net::DocumentChannel> docChannel = do_QueryObject(aChannel);
10609 if (docChannel && XRE_IsContentProcess()) {
10610 // Tell the content process nsDocumentOpenInfo to not try to do
10611 // any sort of targeting.
10612 aOpenFlags |= nsIURILoader::DONT_RETARGET;
10613 }
10614
10615 // Since we are loading a document we need to make sure the proper reserved
10616 // and initial client data is stored on the nsILoadInfo. The
10617 // ClientChannelHelper does this and ensures that it is propagated properly
10618 // on redirects. We pass no reserved client here so that the helper will
10619 // create the reserved ClientSource if necessary.
10620 Maybe<ClientInfo> noReservedClient;
10621 if (docChannel) {
10622 // When using DocumentChannel, all redirect handling is done in the parent,
10623 // so we just need the child variant to watch for the internal redirect
10624 // to the final channel.
10625 rv = AddClientChannelHelperInChild(aChannel,
10626 GetMainThreadSerialEventTarget());
10627 docChannel->SetInitialClientInfo(GetInitialClientInfo());
10628 } else {
10629 rv = AddClientChannelHelper(aChannel, std::move(noReservedClient),
10630 GetInitialClientInfo(),
10631 GetMainThreadSerialEventTarget());
10632 }
10633 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"
, 10633); return rv; } } while (false)
;
10634
10635 rv = aURILoader->OpenURI(aChannel, aOpenFlags, this);
10636 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"
, 10636); return rv; } } while (false)
;
10637
10638 // We're about to load a new page and it may take time before necko
10639 // gives back any data, so main thread might have a chance to process a
10640 // collector slice
10641 nsJSContext::MaybeRunNextCollectorSlice(this, JS::GCReason::DOCSHELL);
10642
10643 // Success. Keep the initial ClientSource if it exists.
10644 cleanupInitialClient.release();
10645
10646 return NS_OK;
10647}
10648
10649nsresult nsDocShell::OpenRedirectedChannel(nsDocShellLoadState* aLoadState) {
10650 nsCOMPtr<nsIChannel> channel = aLoadState->GetPendingRedirectedChannel();
10651 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"
, 10651); AnnotateMozCrashReason("MOZ_ASSERT" "(" "channel" ")"
); do { *((volatile int*)__null) = 10651; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
10652
10653 // If anything fails here, make sure to clear our initial ClientSource.
10654 auto cleanupInitialClient =
10655 MakeScopeExit([&] { mInitialClientSource.reset(); });
10656
10657 nsCOMPtr<nsPIDOMWindowOuter> win = GetWindow();
10658 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"
, 10658); return NS_ERROR_FAILURE; } } while (false)
;
10659
10660 MaybeCreateInitialClientSource();
10661
10662 nsCOMPtr<nsILoadInfo> loadInfo = channel->LoadInfo();
10663
10664 LoadInfo* li = static_cast<LoadInfo*>(loadInfo.get());
10665 if (loadInfo->GetExternalContentPolicyType() ==
10666 ExtContentPolicy::TYPE_DOCUMENT) {
10667 li->UpdateBrowsingContextID(mBrowsingContext->Id());
10668 } else if (loadInfo->GetExternalContentPolicyType() ==
10669 ExtContentPolicy::TYPE_SUBDOCUMENT) {
10670 li->UpdateFrameBrowsingContextID(mBrowsingContext->Id());
10671 }
10672
10673 // If we did a process switch, then we should have an existing allocated
10674 // ClientInfo, so we just need to allocate a corresponding ClientSource.
10675 CreateReservedSourceIfNeeded(channel, GetMainThreadSerialEventTarget());
10676
10677 RefPtr<nsDocumentOpenInfo> loader =
10678 new nsDocumentOpenInfo(this, nsIURILoader::DONT_RETARGET, nullptr);
10679 channel->SetLoadGroup(mLoadGroup);
10680
10681 MOZ_ALWAYS_SUCCEEDS(loader->Prepare())do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(loader->Prepare())), 1)))), 1))) { } else { do { do { } while
(false); MOZ_ReportCrash("" "NS_SUCCEEDED(loader->Prepare())"
, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 10681); AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED(loader->Prepare())"
")"); do { *((volatile int*)__null) = 10681; __attribute__((
nomerge)) ::abort(); } while (false); } while (false); } } while
(false)
;
10682
10683 nsresult rv = NS_OK;
10684 if (XRE_IsParentProcess()) {
10685 // If we're in the parent, the we don't have an nsIChildChannel, just
10686 // the original channel, which is already open in this process.
10687
10688 // DocumentLoadListener expects to get an nsIParentChannel, so
10689 // we create a wrapper around the channel and nsIStreamListener
10690 // that forwards functionality as needed, and then we register
10691 // it under the provided identifier.
10692 RefPtr<ParentChannelWrapper> wrapper =
10693 new ParentChannelWrapper(channel, loader);
10694 wrapper->Register(aLoadState->GetPendingRedirectChannelRegistrarId());
10695
10696 mLoadGroup->AddRequest(channel, nullptr);
10697 } else if (nsCOMPtr<nsIChildChannel> childChannel =
10698 do_QueryInterface(channel)) {
10699 // Our channel was redirected from another process, so doesn't need to
10700 // be opened again. However, it does need its listener hooked up
10701 // correctly.
10702 rv = childChannel->CompleteRedirectSetup(loader);
10703 } else {
10704 // It's possible for the redirected channel to not implement
10705 // nsIChildChannel and be entirely local (like srcdoc). In that case we
10706 // can just open the local instance and it will work.
10707 rv = channel->AsyncOpen(loader);
10708 }
10709 if (rv == NS_ERROR_NO_CONTENT) {
10710 return NS_OK;
10711 }
10712 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"
, 10712); return rv; } } while (false)
;
10713
10714 // Success. Keep the initial ClientSource if it exists.
10715 cleanupInitialClient.release();
10716 return NS_OK;
10717}
10718
10719// https://html.spec.whatwg.org/#scrolling-to-a-fragment
10720nsresult nsDocShell::ScrollToAnchor(bool aCurHasRef, bool aNewHasRef,
10721 nsACString& aNewHash, uint32_t aLoadType) {
10722 if (!mCurrentURI) {
10723 return NS_OK;
10724 }
10725
10726 RefPtr<PresShell> presShell = GetPresShell();
10727 if (!presShell) {
10728 // If we failed to get the shell, or if there is no shell,
10729 // nothing left to do here.
10730 return NS_OK;
10731 }
10732
10733 ScrollContainerFrame* rootScroll = presShell->GetRootScrollContainerFrame();
10734 if (rootScroll) {
10735 rootScroll->ClearDidHistoryRestore();
10736 }
10737
10738 // If it's a load from history, we don't have any anchor jumping to do.
10739 // Scrollbar position will be restored by the caller based on positions stored
10740 // in session history.
10741 bool scroll = aLoadType != LOAD_HISTORY && aLoadType != LOAD_RELOAD_NORMAL;
10742 // If the load contains text directives, try to apply them. This may fail if
10743 // the load is a same-document load that was initiated before the document was
10744 // fully loaded and the target is not yet included in the DOM tree.
10745 // For this case, the `uninvokedTextDirectives` are not cleared, so that
10746 // `Document::ScrollToRef()` can re-apply the text directive.
10747 // `Document::ScrollToRef()` is (presumably) the second "async" call mentioned
10748 // in sec. 7.4.2.3.3 in the HTML spec, "Fragment navigations":
10749 // https://html.spec.whatwg.org/#scroll-to-fragid:~:text=This%20algorithm%20will%20be%20called%20twice
10750
10751 const RefPtr fragmentDirective = GetDocument()->FragmentDirective();
10752 const nsTArray<RefPtr<nsRange>> textDirectiveRanges =
10753 fragmentDirective->FindTextFragmentsInDocument();
10754 fragmentDirective->HighlightTextDirectives(textDirectiveRanges);
10755 const bool scrollToTextDirective =
10756 !textDirectiveRanges.IsEmpty() &&
10757 fragmentDirective->IsTextDirectiveAllowedToBeScrolledTo();
10758 const RefPtr<nsRange> textDirectiveToScroll =
10759 scrollToTextDirective ? textDirectiveRanges[0] : nullptr;
10760
10761 // If we have no new anchor, we do not want to scroll, unless there is a
10762 // current anchor and we are doing a history load. So return if we have no
10763 // new anchor, and there is no current anchor or the load is not a history
10764 // load.
10765 if ((!aCurHasRef || aLoadType != LOAD_HISTORY) && !aNewHasRef &&
10766 !scrollToTextDirective) {
10767 return NS_OK;
10768 }
10769
10770 // Both the new and current URIs refer to the same page. We can now
10771 // browse to the hash stored in the new URI.
10772
10773 if (aNewHash.IsEmpty() && !scrollToTextDirective) {
10774 // 2. If fragment is the empty string, then return the special value top of
10775 // the document.
10776 //
10777 // Tell the shell it's at an anchor without scrolling.
10778 presShell->GoToAnchor(u""_ns, nullptr, false);
10779
10780 if (scroll) {
10781 // Scroll to the top of the page. Ignore the return value; failure to
10782 // scroll here (e.g. if there is no root scrollframe) is not grounds for
10783 // canceling the load!
10784 SetCurScrollPosEx(0, 0);
10785 }
10786
10787 return NS_OK;
10788 }
10789
10790 // 3. Let potentialIndicatedElement be the result of finding a potential
10791 // indicated element given document and fragment.
10792 NS_ConvertUTF8toUTF16 uStr(aNewHash);
10793
10794 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"
, 10794); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!uStr.IsEmpty() || scrollToTextDirective"
")"); do { *((volatile int*)__null) = 10794; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10795
10796 auto rv = presShell->GoToAnchor(uStr, textDirectiveToScroll, scroll,
10797 ScrollFlags::ScrollSmoothAuto);
10798
10799 // 4. If potentialIndicatedElement is not null, then return
10800 // potentialIndicatedElement.
10801 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
10802 return NS_OK;
10803 }
10804
10805 // 5. Let fragmentBytes be the result of percent-decoding fragment.
10806 nsAutoCString fragmentBytes;
10807 const bool unescaped = NS_UnescapeURL(aNewHash.Data(), aNewHash.Length(),
10808 /* aFlags = */ 0, fragmentBytes);
10809
10810 if (!unescaped) {
10811 // Another attempt is only necessary if characters were unescaped.
10812 return NS_OK;
10813 }
10814
10815 if (fragmentBytes.IsEmpty()) {
10816 // When aNewHash contains "%00", the unescaped string may be empty, and
10817 // GoToAnchor asserts if we ask it to scroll to an empty ref.
10818 presShell->GoToAnchor(u""_ns, nullptr, false);
10819 return NS_OK;
10820 }
10821
10822 // 6. Let decodedFragment be the result of running UTF-8 decode without BOM on
10823 // fragmentBytes.
10824 nsAutoString decodedFragment;
10825 rv = UTF_8_ENCODING->DecodeWithoutBOMHandling(fragmentBytes, decodedFragment);
10826 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"
, 10826); return rv; } } while (false)
;
10827
10828 // 7. Set potentialIndicatedElement to the result of finding a potential
10829 // indicated element given document and decodedFragment.
10830 //
10831 // Ignore the return value of GoToAnchor, since it will return an error if
10832 // there is no such anchor in the document, which is actually a success
10833 // condition for us (we want to update the session history with the new URI no
10834 // matter whether we actually scrolled somewhere).
10835 presShell->GoToAnchor(decodedFragment, nullptr, scroll,
10836 ScrollFlags::ScrollSmoothAuto);
10837
10838 return NS_OK;
10839}
10840
10841bool nsDocShell::OnNewURI(nsIURI* aURI, nsIChannel* aChannel,
10842 nsIPrincipal* aTriggeringPrincipal,
10843 nsIPrincipal* aPrincipalToInherit,
10844 nsIPrincipal* aPartitionedPrincipalToInherit,
10845 nsIContentSecurityPolicy* aCsp,
10846 bool aAddToGlobalHistory, bool aCloneSHChildren) {
10847 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"
, 10847); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aURI" ") ("
"uri is null" ")"); do { *((volatile int*)__null) = 10847; __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
;
10848 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"
, 10848); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aChannel || !aTriggeringPrincipal"
") (" "Shouldn't have both set" ")"); do { *((volatile int*)
__null) = 10848; __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
10849
10850 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"
, 10851); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aPrincipalToInherit || (aPrincipalToInherit && aTriggeringPrincipal)"
")"); do { *((volatile int*)__null) = 10851; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
10851 (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"
, 10851); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aPrincipalToInherit || (aPrincipalToInherit && aTriggeringPrincipal)"
")"); do { *((volatile int*)__null) = 10851; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10852
10853#if defined(DEBUG1)
10854 if (MOZ_LOG_TEST(gDocShellLog, LogLevel::Debug)(__builtin_expect(!!(mozilla::detail::log_test(gDocShellLog, LogLevel
::Debug)), 0))
) {
10855 nsAutoCString chanName;
10856 if (aChannel) {
10857 aChannel->GetName(chanName);
10858 } else {
10859 chanName.AssignLiteral("<no channel>");
10860 }
10861
10862 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)
10863 ("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)
10864 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)
;
10865 }
10866#endif
10867
10868 bool equalUri = false;
10869
10870 // Get the post data and the HTTP response code from the channel.
10871 uint32_t responseStatus = 0;
10872 nsCOMPtr<nsIInputStream> inputStream;
10873 if (aChannel) {
10874 nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(aChannel));
10875
10876 // Check if the HTTPChannel is hiding under a multiPartChannel
10877 if (!httpChannel) {
10878 GetHttpChannel(aChannel, getter_AddRefs(httpChannel));
10879 }
10880
10881 if (httpChannel) {
10882 nsCOMPtr<nsIUploadChannel> uploadChannel(do_QueryInterface(httpChannel));
10883 if (uploadChannel) {
10884 uploadChannel->GetUploadStream(getter_AddRefs(inputStream));
10885 }
10886
10887 // If the response status indicates an error, unlink this session
10888 // history entry from any entries sharing its document.
10889 nsresult rv = httpChannel->GetResponseStatus(&responseStatus);
10890 if (mLSHE && NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && responseStatus >= 400) {
10891 mLSHE->AbandonBFCacheEntry();
10892 // FIXME Do the same for mLoadingEntry
10893 }
10894 }
10895 }
10896
10897 // Determine if this type of load should update history.
10898 bool updateGHistory = ShouldUpdateGlobalHistory(mLoadType);
10899
10900 // We don't update session history on reload unless we're loading
10901 // an iframe in shift-reload case.
10902 bool updateSHistory = mBrowsingContext->ShouldUpdateSessionHistory(mLoadType);
10903
10904 // Create SH Entry (mLSHE) only if there is a SessionHistory object in the
10905 // root browsing context.
10906 // FIXME If session history in the parent is enabled then we only do this if
10907 // the session history object is in process, otherwise we can't really
10908 // use the mLSHE anyway. Once session history is only stored in the
10909 // parent then this code will probably be removed anyway.
10910 RefPtr<ChildSHistory> rootSH = GetRootSessionHistory();
10911 if (!rootSH) {
10912 updateSHistory = false;
10913 updateGHistory = false; // XXX Why global history too?
10914 }
10915
10916 // Check if the url to be loaded is the same as the one already loaded.
10917 if (mCurrentURI) {
10918 aURI->Equals(mCurrentURI, &equalUri);
10919 }
10920
10921#ifdef DEBUG1
10922 bool shAvailable = (rootSH != nullptr);
10923
10924 // XXX This log message is almost useless because |updateSHistory|
10925 // and |updateGHistory| are not correct at this point.
10926
10927 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)
10928 (" 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)
10929 " 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)
10930 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)
;
10931#endif
10932
10933 /* If the url to be loaded is the same as the one already there,
10934 * and the original loadType is LOAD_NORMAL, LOAD_LINK, or
10935 * LOAD_STOP_CONTENT, set loadType to LOAD_NORMAL_REPLACE so that
10936 * AddToSessionHistory() won't mess with the current SHEntry and
10937 * if this page has any frame children, it also will be handled
10938 * properly. see bug 83684
10939 *
10940 * NB: If mOSHE is null but we have a current URI, then it probably
10941 * means that we must be at the transient about:blank content viewer;
10942 * we should let the normal load continue, since there's nothing to
10943 * replace. Sometimes this happens after a session restore (eg process
10944 * switch) and mCurrentURI is not about:blank; we assume we can let the load
10945 * continue (Bug 1301399).
10946 *
10947 * XXX Hopefully changing the loadType at this time will not hurt
10948 * anywhere. The other way to take care of sequentially repeating
10949 * frameset pages is to add new methods to nsIDocShellTreeItem.
10950 * Hopefully I don't have to do that.
10951 */
10952 if (equalUri &&
10953 (mozilla::SessionHistoryInParent() ? !!mActiveEntry : !!mOSHE) &&
10954 (mLoadType == LOAD_NORMAL || mLoadType == LOAD_LINK ||
10955 mLoadType == LOAD_STOP_CONTENT) &&
10956 !inputStream) {
10957 mLoadType = LOAD_NORMAL_REPLACE;
10958 }
10959
10960 // If this is a refresh to the currently loaded url, we don't
10961 // have to update session or global history.
10962 if (mLoadType == LOAD_REFRESH && !inputStream && equalUri) {
10963 SetHistoryEntryAndUpdateBC(Some<nsISHEntry*>(mOSHE), Nothing());
10964 }
10965
10966 /* If the user pressed shift-reload, cache will create a new cache key
10967 * for the page. Save the new cacheKey in Session History.
10968 * see bug 90098
10969 */
10970 if (aChannel && IsForceReloadType(mLoadType)) {
10971 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"
, 10973); 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) = 10973; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
10972 "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"
, 10973); 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) = 10973; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
10973 " 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"
, 10973); 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) = 10973; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10974
10975 nsCOMPtr<nsICacheInfoChannel> cacheChannel(do_QueryInterface(aChannel));
10976 uint32_t cacheKey = 0;
10977 // Get the Cache Key and store it in SH.
10978 if (cacheChannel) {
10979 cacheChannel->GetCacheKey(&cacheKey);
10980 }
10981 // If we already have a loading history entry, store the new cache key
10982 // in it. Otherwise, since we're doing a reload and won't be updating
10983 // our history entry, store the cache key in our current history entry.
10984 SetCacheKeyOnHistoryEntry(mLSHE ? mLSHE : mOSHE, cacheKey);
10985
10986 if (!mozilla::SessionHistoryInParent()) {
10987 // Since we're force-reloading, clear all the sub frame history.
10988 ClearFrameHistory(mLSHE);
10989 ClearFrameHistory(mOSHE);
10990 }
10991 }
10992
10993 if (!mozilla::SessionHistoryInParent()) {
10994 // Clear subframe history on refresh.
10995 // XXX: history.go(0) won't go this path as mLoadType is LOAD_HISTORY in
10996 // this case. One should re-validate after bug 1331865 fixed.
10997 if (mLoadType == LOAD_REFRESH) {
10998 ClearFrameHistory(mLSHE);
10999 ClearFrameHistory(mOSHE);
11000 }
11001
11002 if (updateSHistory) {
11003 // Update session history if necessary...
11004 if (!mLSHE && (mItemType == typeContent) && mURIResultedInDocument) {
11005 /* This is a fresh page getting loaded for the first time
11006 *.Create a Entry for it and add it to SH, if this is the
11007 * rootDocShell
11008 */
11009 (void)AddToSessionHistory(aURI, aChannel, aTriggeringPrincipal,
11010 aPrincipalToInherit,
11011 aPartitionedPrincipalToInherit, aCsp,
11012 aCloneSHChildren, getter_AddRefs(mLSHE));
11013 }
11014 } else if (GetSessionHistory() && mLSHE && mURIResultedInDocument) {
11015 // Even if we don't add anything to SHistory, ensure the current index
11016 // points to the same SHEntry as our mLSHE.
11017
11018 GetSessionHistory()->LegacySHistory()->EnsureCorrectEntryAtCurrIndex(
11019 mLSHE);
11020 }
11021 }
11022
11023 // If this is a POST request, we do not want to include this in global
11024 // history.
11025 if (ShouldAddURIVisit(aChannel) && updateGHistory && aAddToGlobalHistory &&
11026 !net::ChannelIsPost(aChannel)) {
11027 nsCOMPtr<nsIURI> previousURI;
11028 uint32_t previousFlags = 0;
11029
11030 if (mLoadType & LOAD_CMD_RELOAD) {
11031 // On a reload request, we don't set redirecting flags.
11032 previousURI = aURI;
11033 } else {
11034 ExtractLastVisit(aChannel, getter_AddRefs(previousURI), &previousFlags);
11035 }
11036
11037 AddURIVisit(aURI, previousURI, previousFlags, responseStatus);
11038 }
11039
11040 // If this was a history load or a refresh, or it was a history load but
11041 // later changed to LOAD_NORMAL_REPLACE due to redirection, update the index
11042 // in session history.
11043 if (!mozilla::SessionHistoryInParent() && rootSH &&
11044 ((mLoadType & (LOAD_CMD_HISTORY | LOAD_CMD_RELOAD)) ||
11045 mLoadType == LOAD_NORMAL_REPLACE || mLoadType == LOAD_REFRESH_REPLACE)) {
11046 mPreviousEntryIndex = rootSH->Index();
11047 if (!mozilla::SessionHistoryInParent()) {
11048 rootSH->LegacySHistory()->UpdateIndex();
11049 }
11050 mLoadedEntryIndex = rootSH->Index();
11051 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)
11052 ("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)
11053 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)
;
11054 }
11055
11056 // aCloneSHChildren exactly means "we are not loading a new document".
11057 uint32_t locationFlags =
11058 aCloneSHChildren ? uint32_t(LOCATION_CHANGE_SAME_DOCUMENT) : 0;
11059
11060 bool onLocationChangeNeeded =
11061 SetCurrentURI(aURI, aChannel, false,
11062 /* aIsInitialAboutBlank */ false, locationFlags);
11063 // Make sure to store the referrer from the channel, if any
11064 nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(aChannel));
11065 if (httpChannel) {
11066 mReferrerInfo = httpChannel->GetReferrerInfo();
11067 }
11068 return onLocationChangeNeeded;
11069}
11070
11071Maybe<Wireframe> nsDocShell::GetWireframe() {
11072 const bool collectWireFrame =
11073 mozilla::SessionHistoryInParent() &&
11074 StaticPrefs::browser_history_collectWireframes() &&
11075 mBrowsingContext->IsTopContent() && mActiveEntry;
11076
11077 if (!collectWireFrame) {
11078 return Nothing();
11079 }
11080
11081 RefPtr<Document> doc = mDocumentViewer->GetDocument();
11082 Nullable<Wireframe> wireframe;
11083 doc->GetWireframeWithoutFlushing(false, wireframe);
11084 if (wireframe.IsNull()) {
11085 return Nothing();
11086 }
11087 return Some(wireframe.Value());
11088}
11089
11090bool nsDocShell::CollectWireframe() {
11091 Maybe<Wireframe> wireframe = GetWireframe();
11092 if (wireframe.isNothing()) {
11093 return false;
11094 }
11095
11096 if (XRE_IsParentProcess()) {
11097 SessionHistoryEntry* entry =
11098 mBrowsingContext->Canonical()->GetActiveSessionHistoryEntry();
11099 if (entry) {
11100 entry->SetWireframe(wireframe);
11101 }
11102 } else {
11103 mozilla::Unused
11104 << ContentChild::GetSingleton()->SendSessionHistoryEntryWireframe(
11105 mBrowsingContext, wireframe.ref());
11106 }
11107
11108 return true;
11109}
11110
11111//*****************************************************************************
11112// nsDocShell: Session History
11113//*****************************************************************************
11114
11115NS_IMETHODIMPnsresult
11116nsDocShell::AddState(JS::Handle<JS::Value> aData, const nsAString& aTitle,
11117 const nsAString& aURL, bool aReplace, JSContext* aCx) {
11118 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)
11119 ("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)
11120 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)
11121 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)
;
11122 // Implements History.pushState and History.replaceState
11123
11124 // Here's what we do, roughly in the order specified by HTML5. The specific
11125 // steps we are executing are at
11126 // <https://html.spec.whatwg.org/multipage/history.html#dom-history-pushstate>
11127 // and
11128 // <https://html.spec.whatwg.org/multipage/history.html#url-and-history-update-steps>.
11129 // This function basically implements #dom-history-pushstate and
11130 // UpdateURLAndHistory implements #url-and-history-update-steps.
11131 //
11132 // A. Serialize aData using structured clone. This is #dom-history-pushstate
11133 // step 5.
11134 // B. If the third argument is present, #dom-history-pushstate step 7.
11135 // 7.1. Resolve the url, relative to our document.
11136 // 7.2. If (a) fails, raise a SECURITY_ERR
11137 // 7.4. Compare the resulting absolute URL to the document's address. If
11138 // any part of the URLs difer other than the <path>, <query>, and
11139 // <fragment> components, raise a SECURITY_ERR and abort.
11140 // C. If !aReplace, #url-and-history-update-steps steps 2.1-2.3:
11141 // Remove from the session history all entries after the current entry,
11142 // as we would after a regular navigation, and save the current
11143 // entry's scroll position (bug 590573).
11144 // D. #url-and-history-update-steps step 2.4 or step 3. As apropriate,
11145 // either add a state object entry to the session history after the
11146 // current entry with the following properties, or modify the current
11147 // session history entry to set
11148 // a. cloned data as the state object,
11149 // b. if the third argument was present, the absolute URL found in
11150 // step 2
11151 // Also clear the new history entry's POST data (see bug 580069).
11152 // E. If aReplace is false (i.e. we're doing a pushState instead of a
11153 // replaceState), notify bfcache that we've navigated to a new page.
11154 // F. If the third argument is present, set the document's current address
11155 // to the absolute URL found in step B. This is
11156 // #url-and-history-update-steps step 4.
11157 //
11158 // It's important that this function not run arbitrary scripts after step A
11159 // and before completing step E. For example, if a script called
11160 // history.back() before we completed step E, bfcache might destroy an
11161 // active content viewer. Since EvictOutOfRangeDocumentViewers at the end of
11162 // step E might run script, we can't just put a script blocker around the
11163 // critical section.
11164 //
11165 // Note that we completely ignore the aTitle parameter.
11166
11167 nsresult rv;
11168
11169 // Don't clobber the load type of an existing network load.
11170 AutoRestore<uint32_t> loadTypeResetter(mLoadType);
11171
11172 // pushState effectively becomes replaceState when we've started a network
11173 // load but haven't adopted its document yet. This mirrors what we do with
11174 // changes to the hash at this stage of the game.
11175 if (JustStartedNetworkLoad()) {
11176 aReplace = true;
11177 }
11178
11179 RefPtr<Document> document = GetDocument();
11180 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"
, 11180); return NS_ERROR_FAILURE; } } while (false)
;
11181
11182 // Step A: Serialize aData using structured clone.
11183 // https://html.spec.whatwg.org/multipage/history.html#dom-history-pushstate
11184 // step 5.
11185 nsCOMPtr<nsIStructuredCloneContainer> scContainer;
11186
11187 // scContainer->Init might cause arbitrary JS to run, and this code might
11188 // navigate the page we're on, potentially to a different origin! (bug
11189 // 634834) To protect against this, we abort if our principal changes due
11190 // to the InitFromJSVal() call.
11191 {
11192 RefPtr<Document> origDocument = GetDocument();
11193 if (!origDocument) {
11194 return NS_ERROR_DOM_SECURITY_ERR;
11195 }
11196 nsCOMPtr<nsIPrincipal> origPrincipal = origDocument->NodePrincipal();
11197
11198 scContainer = new nsStructuredCloneContainer();
11199 rv = scContainer->InitFromJSVal(aData, aCx);
11200 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"
, 11200); return rv; } } while (false)
;
11201
11202 RefPtr<Document> newDocument = GetDocument();
11203 if (!newDocument) {
11204 return NS_ERROR_DOM_SECURITY_ERR;
11205 }
11206 nsCOMPtr<nsIPrincipal> newPrincipal = newDocument->NodePrincipal();
11207
11208 bool principalsEqual = false;
11209 origPrincipal->Equals(newPrincipal, &principalsEqual);
11210 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"
, 11210); return NS_ERROR_DOM_SECURITY_ERR; } } while (false)
;
11211 }
11212
11213 // Check that the state object isn't too long.
11214 int32_t maxStateObjSize = StaticPrefs::browser_history_maxStateObjectSize();
11215 if (maxStateObjSize < 0) {
11216 maxStateObjSize = 0;
11217 }
11218
11219 uint64_t scSize;
11220 rv = scContainer->GetSerializedNBytes(&scSize);
11221 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"
, 11221); return rv; } } while (false)
;
11222
11223 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"
, 11223); return NS_ERROR_ILLEGAL_VALUE; } } while (false)
;
11224
11225 // Step B: Resolve aURL.
11226 // https://html.spec.whatwg.org/multipage/history.html#dom-history-pushstate
11227 // step 7.
11228 bool equalURIs = true;
11229 nsCOMPtr<nsIURI> currentURI;
11230 if (mCurrentURI) {
11231 currentURI = nsIOService::CreateExposableURI(mCurrentURI);
11232 } else {
11233 currentURI = mCurrentURI;
11234 }
11235 nsCOMPtr<nsIURI> newURI;
11236 if (aURL.Length() == 0) {
11237 newURI = currentURI;
11238 } else {
11239 // 7.1: Resolve aURL relative to mURI
11240
11241 nsIURI* docBaseURI = document->GetDocBaseURI();
11242 if (!docBaseURI) {
11243 return NS_ERROR_FAILURE;
11244 }
11245
11246 nsAutoCString spec;
11247 docBaseURI->GetSpec(spec);
11248
11249 rv = NS_NewURI(getter_AddRefs(newURI), aURL,
11250 document->GetDocumentCharacterSet(), docBaseURI);
11251
11252 // 7.2: If 2a fails, raise a SECURITY_ERR
11253 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
11254 return NS_ERROR_DOM_SECURITY_ERR;
11255 }
11256
11257 // 7.4 and 7.5: Same-origin check.
11258 if (!nsContentUtils::URIIsLocalFile(newURI)) {
11259 // In addition to checking that the security manager says that
11260 // the new URI has the same origin as our current URI, we also
11261 // check that the two URIs have the same userpass. (The
11262 // security manager says that |http://foo.com| and
11263 // |http://me@foo.com| have the same origin.) currentURI
11264 // won't contain the password part of the userpass, so this
11265 // means that it's never valid to specify a password in a
11266 // pushState or replaceState URI.
11267
11268 nsCOMPtr<nsIScriptSecurityManager> secMan =
11269 do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID"@mozilla.org/scriptsecuritymanager;1");
11270 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"
, 11270); return NS_ERROR_FAILURE; } } while (false)
;
11271
11272 // It's very important that we check that newURI is of the same
11273 // origin as currentURI, not docBaseURI, because a page can
11274 // set docBaseURI arbitrarily to any domain.
11275 nsAutoCString currentUserPass, newUserPass;
11276 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"
, 11277); return NS_ERROR_FAILURE; } } while (false)
11277 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"
, 11277); return NS_ERROR_FAILURE; } } while (false)
;
11278 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"
, 11278); return NS_ERROR_FAILURE; } } while (false)
;
11279 bool isPrivateWin =
11280 document->NodePrincipal()->OriginAttributesRef().IsPrivateBrowsing();
11281 if (NS_FAILED(secMan->CheckSameOriginURI(currentURI, newURI, true,((bool)(__builtin_expect(!!(NS_FAILED_impl(secMan->CheckSameOriginURI
(currentURI, newURI, true, isPrivateWin))), 0)))
11282 isPrivateWin))((bool)(__builtin_expect(!!(NS_FAILED_impl(secMan->CheckSameOriginURI
(currentURI, newURI, true, isPrivateWin))), 0)))
||
11283 !currentUserPass.Equals(newUserPass)) {
11284 return NS_ERROR_DOM_SECURITY_ERR;
11285 }
11286 } else {
11287 // It's a file:// URI
11288 nsCOMPtr<nsIPrincipal> principal = document->GetPrincipal();
11289
11290 if (!principal || NS_FAILED(principal->CheckMayLoadWithReporting(((bool)(__builtin_expect(!!(NS_FAILED_impl(principal->CheckMayLoadWithReporting
( newURI, false, document->InnerWindowID()))), 0)))
11291 newURI, false, document->InnerWindowID()))((bool)(__builtin_expect(!!(NS_FAILED_impl(principal->CheckMayLoadWithReporting
( newURI, false, document->InnerWindowID()))), 0)))
) {
11292 return NS_ERROR_DOM_SECURITY_ERR;
11293 }
11294 }
11295
11296 if (currentURI) {
11297 currentURI->Equals(newURI, &equalURIs);
11298 } else {
11299 equalURIs = false;
11300 }
11301
11302 } // end of same-origin check
11303
11304 // Step 8: call "URL and history update steps"
11305 rv = UpdateURLAndHistory(document, newURI, scContainer, aTitle, aReplace,
11306 currentURI, equalURIs);
11307 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"
, 11307); return rv; } } while (false)
;
11308
11309 return NS_OK;
11310}
11311
11312nsresult nsDocShell::UpdateURLAndHistory(Document* aDocument, nsIURI* aNewURI,
11313 nsIStructuredCloneContainer* aData,
11314 const nsAString& aTitle, bool aReplace,
11315 nsIURI* aCurrentURI, bool aEqualURIs) {
11316 // Implements
11317 // https://html.spec.whatwg.org/multipage/history.html#url-and-history-update-steps
11318
11319 // If we have a pending title change, handle it before creating a new entry.
11320 aDocument->DoNotifyPossibleTitleChange();
11321
11322 // Step 2, if aReplace is false: Create a new entry in the session
11323 // history. This will erase all SHEntries after the new entry and make this
11324 // entry the current one. This operation may modify mOSHE, which we need
11325 // later, so we keep a reference here.
11326 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"
, 11326); return NS_ERROR_FAILURE; } } while (false)
;
11327 nsCOMPtr<nsISHEntry> oldOSHE = mOSHE;
11328
11329 // If this push/replaceState changed the document's current URI and the new
11330 // URI differs from the old URI in more than the hash, or if the old
11331 // SHEntry's URI was modified in this way by a push/replaceState call
11332 // set URIWasModified to true for the current SHEntry (bug 669671).
11333 bool sameExceptHashes = true;
11334 aNewURI->EqualsExceptRef(aCurrentURI, &sameExceptHashes);
11335 bool uriWasModified;
11336 if (sameExceptHashes) {
11337 if (mozilla::SessionHistoryInParent()) {
11338 uriWasModified = mActiveEntry && mActiveEntry->GetURIWasModified();
11339 } else {
11340 uriWasModified = oldOSHE && oldOSHE->GetURIWasModified();
11341 }
11342 } else {
11343 uriWasModified = true;
11344 }
11345
11346 mLoadType = LOAD_PUSHSTATE;
11347
11348 nsCOMPtr<nsISHEntry> newSHEntry;
11349 if (!aReplace) {
11350 // Step 2.
11351
11352 // Step 2.2, "Remove any tasks queued by the history traversal task
11353 // source that are associated with any Document objects in the
11354 // top-level browsing context's document family." This is very hard in
11355 // SessionHistoryInParent since we can't synchronously access the
11356 // pending navigations that are already sent to the parent. We can
11357 // abort any AsyncGo navigations that are waiting to be sent. If we
11358 // send a message to the parent, it would be processed after any
11359 // navigations previously sent. So long as we consider the "history
11360 // traversal task source" to be the list in this process we match the
11361 // spec. If we move the entire list to the parent, we can handle the
11362 // aborting of loads there, but we don't have a way to synchronously
11363 // remove entries as we do here for non-SHIP.
11364 RefPtr<ChildSHistory> shistory = GetRootSessionHistory();
11365 if (shistory) {
11366 shistory->RemovePendingHistoryNavigations();
11367 }
11368
11369 nsPoint scrollPos = GetCurScrollPos();
11370
11371 bool scrollRestorationIsManual;
11372 if (mozilla::SessionHistoryInParent()) {
11373 // FIXME Need to save the current scroll position on mActiveEntry.
11374 scrollRestorationIsManual = mActiveEntry->GetScrollRestorationIsManual();
11375 } else {
11376 // Save the current scroll position (bug 590573). Step 2.3.
11377 mOSHE->SetScrollPosition(scrollPos.x, scrollPos.y);
11378
11379 scrollRestorationIsManual = mOSHE->GetScrollRestorationIsManual();
11380 }
11381
11382 nsCOMPtr<nsIContentSecurityPolicy> csp = aDocument->GetCsp();
11383
11384 if (mozilla::SessionHistoryInParent()) {
11385 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)
11386 ("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)
;
11387
11388 nsString title(mActiveEntry->GetTitle());
11389 nsCOMPtr<nsIReferrerInfo> referrerInfo = mActiveEntry->GetReferrerInfo();
11390
11391 UpdateActiveEntry(false,
11392 /* aPreviousScrollPos = */ Some(scrollPos), aNewURI,
11393 /* aOriginalURI = */ nullptr,
11394 /* aReferrerInfo = */ referrerInfo,
11395 /* aTriggeringPrincipal = */ aDocument->NodePrincipal(),
11396 csp, title, scrollRestorationIsManual, aData,
11397 uriWasModified);
11398 } else {
11399 // Since we're not changing which page we have loaded, pass
11400 // true for aCloneChildren.
11401 nsresult rv = AddToSessionHistory(
11402 aNewURI, nullptr,
11403 aDocument->NodePrincipal(), // triggeringPrincipal
11404 nullptr, nullptr, csp, true, getter_AddRefs(newSHEntry));
11405 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"
, 11405); return rv; } } while (false)
;
11406
11407 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"
, 11407); return NS_ERROR_FAILURE; } } while (false)
;
11408
11409 // Session history entries created by pushState inherit scroll restoration
11410 // mode from the current entry.
11411 newSHEntry->SetScrollRestorationIsManual(scrollRestorationIsManual);
11412
11413 // Set the new SHEntry's title (bug 655273).
11414 nsString title;
11415 mOSHE->GetTitle(title);
11416 newSHEntry->SetTitle(title);
11417
11418 nsCOMPtr<nsIReferrerInfo> referrerInfo = mOSHE->GetReferrerInfo();
11419 newSHEntry->SetReferrerInfo(referrerInfo);
11420
11421 // Link the new SHEntry to the old SHEntry's BFCache entry, since the
11422 // two entries correspond to the same document.
11423 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"
, 11424); return NS_ERROR_FAILURE; } } while (false)
11424 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"
, 11424); return NS_ERROR_FAILURE; } } while (false)
;
11425
11426 // AddToSessionHistory may not modify mOSHE. In case it doesn't,
11427 // we'll just set mOSHE here.
11428 mOSHE = newSHEntry;
11429 }
11430 } else if (mozilla::SessionHistoryInParent()) {
11431 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)
11432 ("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)
11433 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)
;
11434 // Setting the resultPrincipalURI to nullptr is fine here: it will cause
11435 // NS_GetFinalChannelURI to use the originalURI as the URI, which is aNewURI
11436 // in our case. We could also set it to aNewURI, with the same result.
11437 // We don't use aTitle here, see bug 544535.
11438 nsString title;
11439 nsCOMPtr<nsIReferrerInfo> referrerInfo;
11440 if (mActiveEntry) {
11441 title = mActiveEntry->GetTitle();
11442 referrerInfo = mActiveEntry->GetReferrerInfo();
11443 } else {
11444 referrerInfo = nullptr;
11445 }
11446 UpdateActiveEntry(
11447 true, /* aPreviousScrollPos = */ Nothing(), aNewURI, aNewURI,
11448 /* aReferrerInfo = */ referrerInfo, aDocument->NodePrincipal(),
11449 aDocument->GetCsp(), title,
11450 mActiveEntry && mActiveEntry->GetScrollRestorationIsManual(), aData,
11451 uriWasModified);
11452 } else {
11453 // Step 3.
11454 newSHEntry = mOSHE;
11455
11456 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)
;
11457 // Since we're not changing which page we have loaded, pass
11458 // true for aCloneChildren.
11459 if (!newSHEntry) {
11460 nsresult rv = AddToSessionHistory(
11461 aNewURI, nullptr,
11462 aDocument->NodePrincipal(), // triggeringPrincipal
11463 nullptr, nullptr, aDocument->GetCsp(), true,
11464 getter_AddRefs(newSHEntry));
11465 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"
, 11465); return rv; } } while (false)
;
11466 mOSHE = newSHEntry;
11467 }
11468
11469 nsCOMPtr<nsIReferrerInfo> referrerInfo = mOSHE->GetReferrerInfo();
11470
11471 newSHEntry->SetURI(aNewURI);
11472 newSHEntry->SetOriginalURI(aNewURI);
11473 // We replaced the URI of the entry, clear the unstripped URI as it
11474 // shouldn't be used for reloads anymore.
11475 newSHEntry->SetUnstrippedURI(nullptr);
11476 // Setting the resultPrincipalURI to nullptr is fine here: it will cause
11477 // NS_GetFinalChannelURI to use the originalURI as the URI, which is aNewURI
11478 // in our case. We could also set it to aNewURI, with the same result.
11479 newSHEntry->SetResultPrincipalURI(nullptr);
11480 newSHEntry->SetLoadReplace(false);
11481 newSHEntry->SetReferrerInfo(referrerInfo);
11482 }
11483
11484 if (!mozilla::SessionHistoryInParent()) {
11485 // Step 2.4 and 3: Modify new/original session history entry and clear its
11486 // POST data, if there is any.
11487 newSHEntry->SetStateData(aData);
11488 newSHEntry->SetPostData(nullptr);
11489
11490 newSHEntry->SetURIWasModified(uriWasModified);
11491
11492 // Step E as described at the top of AddState: If aReplace is false,
11493 // indicating that we're doing a pushState rather than a replaceState,
11494 // notify bfcache that we've added a page to the history so it can evict
11495 // content viewers if appropriate. Otherwise call ReplaceEntry so that we
11496 // notify nsIHistoryListeners that an entry was replaced. We may not have a
11497 // root session history if this call is coming from a document.open() in a
11498 // docshell subtree that disables session history.
11499 RefPtr<ChildSHistory> rootSH = GetRootSessionHistory();
11500 if (rootSH) {
11501 rootSH->LegacySHistory()->EvictDocumentViewersOrReplaceEntry(newSHEntry,
11502 aReplace);
11503 }
11504 }
11505
11506 // Step 4: If the document's URI changed, update document's URI and update
11507 // global history.
11508 //
11509 // We need to call FireOnLocationChange so that the browser's address bar
11510 // gets updated and the back button is enabled, but we only need to
11511 // explicitly call FireOnLocationChange if we're not calling SetCurrentURI,
11512 // since SetCurrentURI will call FireOnLocationChange for us.
11513 //
11514 // Both SetCurrentURI(...) and FireDummyOnLocationChange() pass
11515 // nullptr for aRequest param to FireOnLocationChange(...). Such an update
11516 // notification is allowed only when we know docshell is not loading a new
11517 // document and it requires LOCATION_CHANGE_SAME_DOCUMENT flag. Otherwise,
11518 // FireOnLocationChange(...) breaks security UI.
11519 //
11520 // If the docshell is shutting down, don't update the document URI, as we
11521 // can't load into a docshell that is being destroyed.
11522 if (!aEqualURIs && !mIsBeingDestroyed) {
11523 aDocument->SetDocumentURI(aNewURI);
11524 SetCurrentURI(aNewURI, nullptr, /* aFireLocationChange */ true,
11525 /* aIsInitialAboutBlank */ false,
11526 GetSameDocumentNavigationFlags(aNewURI));
11527
11528 AddURIVisit(aNewURI, aCurrentURI, 0);
11529
11530 // AddURIVisit doesn't set the title for the new URI in global history,
11531 // so do that here.
11532 UpdateGlobalHistoryTitle(aNewURI);
11533
11534 // Inform the favicon service that our old favicon applies to this new
11535 // URI.
11536 CopyFavicon(aCurrentURI, aNewURI, UsePrivateBrowsing());
11537 } else {
11538 FireDummyOnLocationChange();
11539 }
11540 aDocument->SetStateObject(aData);
11541
11542 return NS_OK;
11543}
11544
11545NS_IMETHODIMPnsresult
11546nsDocShell::GetCurrentScrollRestorationIsManual(bool* aIsManual) {
11547 if (mozilla::SessionHistoryInParent()) {
11548 *aIsManual = mActiveEntry && mActiveEntry->GetScrollRestorationIsManual();
11549 return NS_OK;
11550 }
11551
11552 *aIsManual = false;
11553 if (mOSHE) {
11554 return mOSHE->GetScrollRestorationIsManual(aIsManual);
11555 }
11556
11557 return NS_OK;
11558}
11559
11560NS_IMETHODIMPnsresult
11561nsDocShell::SetCurrentScrollRestorationIsManual(bool aIsManual) {
11562 SetScrollRestorationIsManualOnHistoryEntry(mOSHE, aIsManual);
11563
11564 return NS_OK;
11565}
11566
11567void nsDocShell::SetScrollRestorationIsManualOnHistoryEntry(
11568 nsISHEntry* aSHEntry, bool aIsManual) {
11569 if (aSHEntry) {
11570 aSHEntry->SetScrollRestorationIsManual(aIsManual);
11571 }
11572
11573 if (mActiveEntry && mBrowsingContext) {
11574 mActiveEntry->SetScrollRestorationIsManual(aIsManual);
11575 if (XRE_IsParentProcess()) {
11576 SessionHistoryEntry* entry =
11577 mBrowsingContext->Canonical()->GetActiveSessionHistoryEntry();
11578 if (entry) {
11579 entry->SetScrollRestorationIsManual(aIsManual);
11580 }
11581 } else {
11582 mozilla::Unused << ContentChild::GetSingleton()
11583 ->SendSessionHistoryEntryScrollRestorationIsManual(
11584 mBrowsingContext, aIsManual);
11585 }
11586 }
11587}
11588
11589void nsDocShell::SetCacheKeyOnHistoryEntry(nsISHEntry* aSHEntry,
11590 uint32_t aCacheKey) {
11591 if (aSHEntry) {
11592 aSHEntry->SetCacheKey(aCacheKey);
11593 }
11594
11595 if (mActiveEntry && mBrowsingContext) {
11596 mActiveEntry->SetCacheKey(aCacheKey);
11597 if (XRE_IsParentProcess()) {
11598 SessionHistoryEntry* entry =
11599 mBrowsingContext->Canonical()->GetActiveSessionHistoryEntry();
11600 if (entry) {
11601 entry->SetCacheKey(aCacheKey);
11602 }
11603 } else {
11604 mozilla::Unused
11605 << ContentChild::GetSingleton()->SendSessionHistoryEntryCacheKey(
11606 mBrowsingContext, aCacheKey);
11607 }
11608 }
11609}
11610
11611/* static */
11612bool nsDocShell::ShouldAddToSessionHistory(nsIURI* aURI, nsIChannel* aChannel) {
11613 // I believe none of the about: urls should go in the history. But then
11614 // that could just be me... If the intent is only deny about:blank then we
11615 // should just do a spec compare, rather than two gets of the scheme and
11616 // then the path. -Gagan
11617 nsresult rv;
11618 nsAutoCString buf;
11619
11620 rv = aURI->GetScheme(buf);
11621 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
11622 return false;
11623 }
11624
11625 if (buf.EqualsLiteral("about")) {
11626 rv = aURI->GetPathQueryRef(buf);
11627 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
11628 return false;
11629 }
11630
11631 if (buf.EqualsLiteral("blank")) {
11632 return false;
11633 }
11634 // We only want to add about:newtab if it's not privileged, and
11635 // if it is not configured to show the blank page.
11636 if (buf.EqualsLiteral("newtab")) {
11637 if (!StaticPrefs::browser_newtabpage_enabled()) {
11638 return false;
11639 }
11640
11641 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"
, 11641); return false; } } while (false)
;
11642 nsCOMPtr<nsIPrincipal> resultPrincipal;
11643 rv = nsContentUtils::GetSecurityManager()->GetChannelResultPrincipal(
11644 aChannel, getter_AddRefs(resultPrincipal));
11645 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"
, 11645); return false; } } while (false)
;
11646 return !resultPrincipal->IsSystemPrincipal();
11647 }
11648 }
11649
11650 return true;
11651}
11652
11653nsresult nsDocShell::AddToSessionHistory(
11654 nsIURI* aURI, nsIChannel* aChannel, nsIPrincipal* aTriggeringPrincipal,
11655 nsIPrincipal* aPrincipalToInherit,
11656 nsIPrincipal* aPartitionedPrincipalToInherit,
11657 nsIContentSecurityPolicy* aCsp, bool aCloneChildren,
11658 nsISHEntry** aNewEntry) {
11659 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"
, 11659); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aURI" ") ("
"uri is null" ")"); do { *((volatile int*)__null) = 11659; __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
;
11660 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"
, 11660); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aChannel || !aTriggeringPrincipal"
") (" "Shouldn't have both set" ")"); do { *((volatile int*)
__null) = 11660; __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
11661 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"
, 11661); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "!mozilla::SessionHistoryInParent()"
")"); do { *((volatile int*)__null) = 11661; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11662
11663#if defined(DEBUG1)
11664 if (MOZ_LOG_TEST(gDocShellLog, LogLevel::Debug)(__builtin_expect(!!(mozilla::detail::log_test(gDocShellLog, LogLevel
::Debug)), 0))
) {
11665 nsAutoCString chanName;
11666 if (aChannel) {
11667 aChannel->GetName(chanName);
11668 } else {
11669 chanName.AssignLiteral("<no channel>");
11670 }
11671
11672 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)
11673 ("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)
11674 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)
;
11675 }
11676#endif
11677
11678 nsresult rv = NS_OK;
11679 nsCOMPtr<nsISHEntry> entry;
11680
11681 /*
11682 * If this is a LOAD_FLAGS_REPLACE_HISTORY in a subframe, we use
11683 * the existing SH entry in the page and replace the url and
11684 * other vitalities.
11685 */
11686 if (LOAD_TYPE_HAS_FLAGS(mLoadType, LOAD_FLAGS_REPLACE_HISTORY)((mLoadType) & ((LOAD_FLAGS_REPLACE_HISTORY) << 16)
)
&&
11687 !mBrowsingContext->IsTop()) {
11688 // This is a subframe
11689 entry = mOSHE;
11690 if (entry) {
11691 entry->ClearEntry();
11692 }
11693 }
11694
11695 // Create a new entry if necessary.
11696 if (!entry) {
11697 entry = new nsSHEntry();
11698 }
11699
11700 // Get the post data & referrer
11701 nsCOMPtr<nsIInputStream> inputStream;
11702 nsCOMPtr<nsIURI> originalURI;
11703 nsCOMPtr<nsIURI> resultPrincipalURI;
11704 nsCOMPtr<nsIURI> unstrippedURI;
11705 bool loadReplace = false;
11706 nsCOMPtr<nsIReferrerInfo> referrerInfo;
11707 uint32_t cacheKey = 0;
11708 nsCOMPtr<nsIPrincipal> triggeringPrincipal = aTriggeringPrincipal;
11709 nsCOMPtr<nsIPrincipal> principalToInherit = aPrincipalToInherit;
11710 nsCOMPtr<nsIPrincipal> partitionedPrincipalToInherit =
11711 aPartitionedPrincipalToInherit;
11712 nsCOMPtr<nsIContentSecurityPolicy> csp = aCsp;
11713 bool expired = false; // by default the page is not expired
11714 bool discardLayoutState = false;
11715 nsCOMPtr<nsICacheInfoChannel> cacheChannel;
11716 bool userActivation = false;
11717
11718 if (aChannel) {
11719 cacheChannel = do_QueryInterface(aChannel);
11720
11721 /* If there is a caching channel, get the Cache Key and store it
11722 * in SH.
11723 */
11724 if (cacheChannel) {
11725 cacheChannel->GetCacheKey(&cacheKey);
11726 }
11727 nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(aChannel));
11728
11729 // Check if the httpChannel is hiding under a multipartChannel
11730 if (!httpChannel) {
11731 GetHttpChannel(aChannel, getter_AddRefs(httpChannel));
11732 }
11733 if (httpChannel) {
11734 nsCOMPtr<nsIUploadChannel> uploadChannel(do_QueryInterface(httpChannel));
11735 if (uploadChannel) {
11736 uploadChannel->GetUploadStream(getter_AddRefs(inputStream));
11737 }
11738 httpChannel->GetOriginalURI(getter_AddRefs(originalURI));
11739 uint32_t loadFlags;
11740 aChannel->GetLoadFlags(&loadFlags);
11741 loadReplace = loadFlags & nsIChannel::LOAD_REPLACE;
11742 rv = httpChannel->GetReferrerInfo(getter_AddRefs(referrerInfo));
11743 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"
, 11743); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { *((volatile int*)__null) = 11743; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11744
11745 discardLayoutState = ShouldDiscardLayoutState(httpChannel);
11746 }
11747
11748 nsCOMPtr<nsILoadInfo> loadInfo = aChannel->LoadInfo();
11749 if (!triggeringPrincipal) {
11750 triggeringPrincipal = loadInfo->TriggeringPrincipal();
11751 }
11752 if (!csp) {
11753 csp = loadInfo->GetCspToInherit();
11754 }
11755
11756 loadInfo->GetResultPrincipalURI(getter_AddRefs(resultPrincipalURI));
11757
11758 loadInfo->GetUnstrippedURI(getter_AddRefs(unstrippedURI));
11759
11760 userActivation = loadInfo->GetHasValidUserGestureActivation();
11761
11762 // For now keep storing just the principal in the SHEntry.
11763 if (!principalToInherit) {
11764 if (loadInfo->GetLoadingSandboxed()) {
11765 if (loadInfo->GetLoadingPrincipal()) {
11766 principalToInherit = NullPrincipal::CreateWithInheritedAttributes(
11767 loadInfo->GetLoadingPrincipal());
11768 } else {
11769 // get the OriginAttributes
11770 OriginAttributes attrs;
11771 loadInfo->GetOriginAttributes(&attrs);
11772 principalToInherit = NullPrincipal::Create(attrs);
11773 }
11774 } else {
11775 principalToInherit = loadInfo->PrincipalToInherit();
11776 }
11777 }
11778
11779 if (!partitionedPrincipalToInherit) {
11780 // XXXehsan is it correct to fall back to the principal to inherit in all
11781 // cases? For example, what about the cases where we are using the load
11782 // info's principal to inherit? Do we need to add a similar concept to
11783 // load info for partitioned principal?
11784 partitionedPrincipalToInherit = principalToInherit;
11785 }
11786 }
11787
11788 nsAutoString srcdoc;
11789 bool srcdocEntry = false;
11790 nsCOMPtr<nsIURI> baseURI;
11791
11792 nsCOMPtr<nsIInputStreamChannel> inStrmChan = do_QueryInterface(aChannel);
11793 if (inStrmChan) {
11794 bool isSrcdocChannel;
11795 inStrmChan->GetIsSrcdocChannel(&isSrcdocChannel);
11796 if (isSrcdocChannel) {
11797 inStrmChan->GetSrcdocData(srcdoc);
11798 srcdocEntry = true;
11799 inStrmChan->GetBaseURI(getter_AddRefs(baseURI));
11800 } else {
11801 srcdoc.SetIsVoid(true);
11802 }
11803 }
11804 /* If cache got a 'no-store', ask SH not to store
11805 * HistoryLayoutState. By default, SH will set this
11806 * flag to true and save HistoryLayoutState.
11807 */
11808 bool saveLayoutState = !discardLayoutState;
11809
11810 if (cacheChannel) {
11811 // Check if the page has expired from cache
11812 uint32_t expTime = 0;
11813 cacheChannel->GetCacheTokenExpirationTime(&expTime);
11814 uint32_t now = PRTimeToSeconds(PR_Now());
11815 if (expTime <= now) {
11816 expired = true;
11817 }
11818 }
11819
11820 // Title is set in nsDocShell::SetTitle()
11821 entry->Create(aURI, // uri
11822 u""_ns, // Title
11823 inputStream, // Post data stream
11824 cacheKey, // CacheKey
11825 mContentTypeHint, // Content-type
11826 triggeringPrincipal, // Channel or provided principal
11827 principalToInherit, partitionedPrincipalToInherit, csp,
11828 HistoryID(), GetCreatedDynamically(), originalURI,
11829 resultPrincipalURI, unstrippedURI, loadReplace, referrerInfo,
11830 srcdoc, srcdocEntry, baseURI, saveLayoutState, expired,
11831 userActivation);
11832
11833 if (mBrowsingContext->IsTop() && GetSessionHistory()) {
11834 bool shouldPersist = ShouldAddToSessionHistory(aURI, aChannel);
11835 Maybe<int32_t> previousEntryIndex;
11836 Maybe<int32_t> loadedEntryIndex;
11837 rv = GetSessionHistory()->LegacySHistory()->AddToRootSessionHistory(
11838 aCloneChildren, mOSHE, mBrowsingContext, entry, mLoadType,
11839 shouldPersist, &previousEntryIndex, &loadedEntryIndex);
11840
11841 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"
, 11841); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
") (" "Could not add entry to root session history" ")"); do
{ *((volatile int*)__null) = 11841; __attribute__((nomerge))
::abort(); } while (false); } } while (false)
;
11842 if (previousEntryIndex.isSome()) {
11843 mPreviousEntryIndex = previousEntryIndex.value();
11844 }
11845 if (loadedEntryIndex.isSome()) {
11846 mLoadedEntryIndex = loadedEntryIndex.value();
11847 }
11848
11849 // aCloneChildren implies that we are retaining the same document, thus we
11850 // need to signal to the top WC that the new SHEntry may receive a fresh
11851 // user interaction flag.
11852 if (aCloneChildren) {
11853 WindowContext* topWc = mBrowsingContext->GetTopWindowContext();
11854 if (topWc && !topWc->IsDiscarded()) {
11855 MOZ_ALWAYS_SUCCEEDS(topWc->SetSHEntryHasUserInteraction(false))do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(topWc->SetSHEntryHasUserInteraction(false))), 1)))), 1)))
{ } else { do { do { } while (false); MOZ_ReportCrash("" "NS_SUCCEEDED(topWc->SetSHEntryHasUserInteraction(false))"
, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 11855); AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED(topWc->SetSHEntryHasUserInteraction(false))"
")"); do { *((volatile int*)__null) = 11855; __attribute__((
nomerge)) ::abort(); } while (false); } while (false); } } while
(false)
;
11856 }
11857 }
11858 } else {
11859 // This is a subframe, make sure that this new SHEntry will be
11860 // marked with user interaction.
11861 WindowContext* topWc = mBrowsingContext->GetTopWindowContext();
11862 if (topWc && !topWc->IsDiscarded()) {
11863 MOZ_ALWAYS_SUCCEEDS(topWc->SetSHEntryHasUserInteraction(false))do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(topWc->SetSHEntryHasUserInteraction(false))), 1)))), 1)))
{ } else { do { do { } while (false); MOZ_ReportCrash("" "NS_SUCCEEDED(topWc->SetSHEntryHasUserInteraction(false))"
, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 11863); AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED(topWc->SetSHEntryHasUserInteraction(false))"
")"); do { *((volatile int*)__null) = 11863; __attribute__((
nomerge)) ::abort(); } while (false); } while (false); } } while
(false)
;
11864 }
11865 if (!mOSHE || !LOAD_TYPE_HAS_FLAGS(mLoadType, LOAD_FLAGS_REPLACE_HISTORY)((mLoadType) & ((LOAD_FLAGS_REPLACE_HISTORY) << 16)
)
) {
11866 rv = AddChildSHEntryToParent(entry, mBrowsingContext->ChildOffset(),
11867 aCloneChildren);
11868 }
11869 }
11870
11871 // Return the new SH entry...
11872 if (aNewEntry) {
11873 *aNewEntry = nullptr;
11874 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
11875 entry.forget(aNewEntry);
11876 }
11877 }
11878
11879 return rv;
11880}
11881
11882void nsDocShell::UpdateActiveEntry(
11883 bool aReplace, const Maybe<nsPoint>& aPreviousScrollPos, nsIURI* aURI,
11884 nsIURI* aOriginalURI, nsIReferrerInfo* aReferrerInfo,
11885 nsIPrincipal* aTriggeringPrincipal, nsIContentSecurityPolicy* aCsp,
11886 const nsAString& aTitle, bool aScrollRestorationIsManual,
11887 nsIStructuredCloneContainer* aData, bool aURIWasModified) {
11888 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"
, 11888); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mozilla::SessionHistoryInParent()"
")"); do { *((volatile int*)__null) = 11888; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11889 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"
, 11889); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aURI" ") ("
"uri is null" ")"); do { *((volatile int*)__null) = 11889; __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
;
11890 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"
, 11891); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mLoadType == LOAD_PUSHSTATE"
") (" "This code only deals with pushState" ")"); do { *((volatile
int*)__null) = 11891; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
11891 "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"
, 11891); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mLoadType == LOAD_PUSHSTATE"
") (" "This code only deals with pushState" ")"); do { *((volatile
int*)__null) = 11891; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
11892 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"
, 11892); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aReplace"
")"); do { *((volatile int*)__null) = 11892; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false); } } while
(false)
;
11893
11894 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)
11895 ("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)
11896 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)
;
11897
11898 // Even if we're replacing an existing entry we create new a
11899 // SessionHistoryInfo. In the parent process we'll keep the existing
11900 // SessionHistoryEntry, but just replace its SessionHistoryInfo, that way the
11901 // entry keeps identity but its data is replaced.
11902 bool replace = aReplace && mActiveEntry;
11903
11904 if (!replace) {
11905 CollectWireframe();
11906 }
11907
11908 if (mActiveEntry) {
11909 // Link this entry to the previous active entry.
11910 mActiveEntry = MakeUnique<SessionHistoryInfo>(*mActiveEntry, aURI);
11911 } else {
11912 mActiveEntry = MakeUnique<SessionHistoryInfo>(
11913 aURI, aTriggeringPrincipal, nullptr, nullptr, aCsp, mContentTypeHint);
11914 }
11915 mActiveEntry->SetOriginalURI(aOriginalURI);
11916 mActiveEntry->SetUnstrippedURI(nullptr);
11917 mActiveEntry->SetReferrerInfo(aReferrerInfo);
11918 mActiveEntry->SetTitle(aTitle);
11919 mActiveEntry->SetStateData(static_cast<nsStructuredCloneContainer*>(aData));
11920 mActiveEntry->SetURIWasModified(aURIWasModified);
11921 mActiveEntry->SetScrollRestorationIsManual(aScrollRestorationIsManual);
11922
11923 if (replace) {
11924 mBrowsingContext->ReplaceActiveSessionHistoryEntry(mActiveEntry.get());
11925 } else {
11926 mBrowsingContext->IncrementHistoryEntryCountForBrowsingContext();
11927 // FIXME We should probably just compute mChildOffset in the parent
11928 // instead of passing it over IPC here.
11929 mBrowsingContext->SetActiveSessionHistoryEntry(
11930 aPreviousScrollPos, mActiveEntry.get(), mLoadType,
11931 /* aCacheKey = */ 0);
11932 // FIXME Do we need to update mPreviousEntryIndex and mLoadedEntryIndex?
11933 }
11934}
11935
11936nsresult nsDocShell::LoadHistoryEntry(nsISHEntry* aEntry, uint32_t aLoadType,
11937 bool aUserActivation) {
11938 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"
, 11938); return NS_ERROR_FAILURE; } } while (false)
;
11939
11940 nsresult rv;
11941 RefPtr<nsDocShellLoadState> loadState;
11942 rv = aEntry->CreateLoadInfo(getter_AddRefs(loadState));
11943 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"
, 11943); return rv; } } while (false)
;
11944
11945 // Calling CreateAboutBlankDocumentViewer can set mOSHE to null, and if
11946 // that's the only thing holding a ref to aEntry that will cause aEntry to
11947 // die while we're loading it. So hold a strong ref to aEntry here, just
11948 // in case.
11949 nsCOMPtr<nsISHEntry> kungFuDeathGrip(aEntry);
11950
11951 loadState->SetHasValidUserGestureActivation(
11952 loadState->HasValidUserGestureActivation() || aUserActivation);
11953
11954 loadState->SetTextDirectiveUserActivation(
11955 loadState->GetTextDirectiveUserActivation() || aUserActivation);
11956
11957 return LoadHistoryEntry(loadState, aLoadType, aEntry == mOSHE);
11958}
11959
11960nsresult nsDocShell::LoadHistoryEntry(const LoadingSessionHistoryInfo& aEntry,
11961 uint32_t aLoadType,
11962 bool aUserActivation) {
11963 RefPtr<nsDocShellLoadState> loadState = aEntry.CreateLoadInfo();
11964 loadState->SetHasValidUserGestureActivation(
11965 loadState->HasValidUserGestureActivation() || aUserActivation);
11966
11967 loadState->SetTextDirectiveUserActivation(
11968 loadState->GetTextDirectiveUserActivation() || aUserActivation);
11969
11970 return LoadHistoryEntry(loadState, aLoadType, aEntry.mLoadingCurrentEntry);
11971}
11972
11973nsresult nsDocShell::LoadHistoryEntry(nsDocShellLoadState* aLoadState,
11974 uint32_t aLoadType,
11975 bool aLoadingCurrentEntry) {
11976 if (!IsNavigationAllowed()) {
11977 return NS_OK;
11978 }
11979
11980 // We are setting load type afterwards so we don't have to
11981 // send it in an IPC message
11982 aLoadState->SetLoadType(aLoadType);
11983
11984 nsresult rv;
11985 if (SchemeIsJavascript(aLoadState->URI())) {
11986 // We're loading a URL that will execute script from inside asyncOpen.
11987 // Replace the current document with about:blank now to prevent
11988 // anything from the current document from leaking into any JavaScript
11989 // code in the URL.
11990 // Don't cache the presentation if we're going to just reload the
11991 // current entry. Caching would lead to trying to save the different
11992 // content viewers in the same nsISHEntry object.
11993 rv = CreateAboutBlankDocumentViewer(
11994 aLoadState->PrincipalToInherit(),
11995 aLoadState->PartitionedPrincipalToInherit(), nullptr, nullptr,
11996 /* aIsInitialDocument */ false, Nothing(), !aLoadingCurrentEntry);
11997
11998 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
11999 // The creation of the intermittent about:blank content
12000 // viewer failed for some reason (potentially because the
12001 // user prevented it). Interrupt the history load.
12002 return NS_OK;
12003 }
12004
12005 if (!aLoadState->TriggeringPrincipal()) {
12006 // Ensure that we have a triggeringPrincipal. Otherwise javascript:
12007 // URIs will pick it up from the about:blank page we just loaded,
12008 // and we don't really want even that in this case.
12009 nsCOMPtr<nsIPrincipal> principal =
12010 NullPrincipal::Create(GetOriginAttributes());
12011 aLoadState->SetTriggeringPrincipal(principal);
12012 }
12013 }
12014
12015 /* If there is a valid postdata *and* the user pressed
12016 * reload or shift-reload, take user's permission before we
12017 * repost the data to the server.
12018 */
12019 if ((aLoadType & LOAD_CMD_RELOAD) && aLoadState->PostDataStream()) {
12020 bool repost;
12021 rv = ConfirmRepost(&repost);
12022 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
12023 return rv;
12024 }
12025
12026 // If the user pressed cancel in the dialog, return. We're done here.
12027 if (!repost) {
12028 return NS_BINDING_ABORTED;
12029 }
12030 }
12031
12032 // If there is no valid triggeringPrincipal, we deny the load
12033 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"
, 12034); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->TriggeringPrincipal()"
") (" "need a valid triggeringPrincipal to load from history"
")"); do { *((volatile int*)__null) = 12034; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
12034 "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"
, 12034); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->TriggeringPrincipal()"
") (" "need a valid triggeringPrincipal to load from history"
")"); do { *((volatile int*)__null) = 12034; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12035 if (!aLoadState->TriggeringPrincipal()) {
12036 return NS_ERROR_FAILURE;
12037 }
12038
12039 return InternalLoad(aLoadState); // No nsIRequest
12040}
12041
12042NS_IMETHODIMPnsresult
12043nsDocShell::PersistLayoutHistoryState() {
12044 nsresult rv = NS_OK;
12045
12046 if (mozilla::SessionHistoryInParent() ? !!mActiveEntry : !!mOSHE) {
12047 bool scrollRestorationIsManual;
12048 if (mozilla::SessionHistoryInParent()) {
12049 scrollRestorationIsManual = mActiveEntry->GetScrollRestorationIsManual();
12050 } else {
12051 scrollRestorationIsManual = mOSHE->GetScrollRestorationIsManual();
12052 }
12053 nsCOMPtr<nsILayoutHistoryState> layoutState;
12054 if (RefPtr<PresShell> presShell = GetPresShell()) {
12055 rv = presShell->CaptureHistoryState(getter_AddRefs(layoutState));
12056 } else if (scrollRestorationIsManual) {
12057 // Even if we don't have layout anymore, we may want to reset the
12058 // current scroll state in layout history.
12059 GetLayoutHistoryState(getter_AddRefs(layoutState));
12060 }
12061
12062 if (scrollRestorationIsManual && layoutState) {
12063 layoutState->ResetScrollState();
12064 }
12065 }
12066
12067 return rv;
12068}
12069
12070void nsDocShell::SwapHistoryEntries(nsISHEntry* aOldEntry,
12071 nsISHEntry* aNewEntry) {
12072 if (aOldEntry == mOSHE) {
12073 mOSHE = aNewEntry;
12074 }
12075
12076 if (aOldEntry == mLSHE) {
12077 mLSHE = aNewEntry;
12078 }
12079}
12080
12081void nsDocShell::SetHistoryEntryAndUpdateBC(const Maybe<nsISHEntry*>& aLSHE,
12082 const Maybe<nsISHEntry*>& aOSHE) {
12083 // We want to hold on to the reference in mLSHE before we update it.
12084 // Otherwise, SetHistoryEntry could release the last reference to
12085 // the entry while aOSHE is pointing to it.
12086 nsCOMPtr<nsISHEntry> deathGripOldLSHE;
12087 if (aLSHE.isSome()) {
12088 deathGripOldLSHE = SetHistoryEntry(&mLSHE, aLSHE.value());
12089 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"
, 12089); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mLSHE.get() == aLSHE.value()"
")"); do { *((volatile int*)__null) = 12089; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12090 }
12091 nsCOMPtr<nsISHEntry> deathGripOldOSHE;
12092 if (aOSHE.isSome()) {
12093 deathGripOldOSHE = SetHistoryEntry(&mOSHE, aOSHE.value());
12094 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"
, 12094); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mOSHE.get() == aOSHE.value()"
")"); do { *((volatile int*)__null) = 12094; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12095 }
12096}
12097
12098already_AddRefed<nsISHEntry> nsDocShell::SetHistoryEntry(
12099 nsCOMPtr<nsISHEntry>* aPtr, nsISHEntry* aEntry) {
12100 // We need to sync up the docshell and session history trees for
12101 // subframe navigation. If the load was in a subframe, we forward up to
12102 // the root docshell, which will then recursively sync up all docshells
12103 // to their corresponding entries in the new session history tree.
12104 // If we don't do this, then we can cache a content viewer on the wrong
12105 // cloned entry, and subsequently restore it at the wrong time.
12106 RefPtr<BrowsingContext> topBC = mBrowsingContext->Top();
12107 if (topBC->IsDiscarded()) {
12108 topBC = nullptr;
12109 }
12110 RefPtr<BrowsingContext> currBC =
12111 mBrowsingContext->IsDiscarded() ? nullptr : mBrowsingContext;
12112 if (topBC && *aPtr) {
12113 (*aPtr)->SyncTreesForSubframeNavigation(aEntry, topBC, currBC);
12114 }
12115 nsCOMPtr<nsISHEntry> entry(aEntry);
12116 entry.swap(*aPtr);
12117 return entry.forget();
12118}
12119
12120already_AddRefed<ChildSHistory> nsDocShell::GetRootSessionHistory() {
12121 RefPtr<ChildSHistory> childSHistory =
12122 mBrowsingContext->Top()->GetChildSessionHistory();
12123 return childSHistory.forget();
12124}
12125
12126nsresult nsDocShell::GetHttpChannel(nsIChannel* aChannel,
12127 nsIHttpChannel** aReturn) {
12128 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"
, 12128); return NS_ERROR_INVALID_POINTER; } } while (false)
;
12129 if (!aChannel) {
12130 return NS_ERROR_FAILURE;
12131 }
12132
12133 nsCOMPtr<nsIMultiPartChannel> multiPartChannel(do_QueryInterface(aChannel));
12134 if (multiPartChannel) {
12135 nsCOMPtr<nsIChannel> baseChannel;
12136 multiPartChannel->GetBaseChannel(getter_AddRefs(baseChannel));
12137 nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(baseChannel));
12138 *aReturn = httpChannel;
12139 NS_IF_ADDREF(*aReturn)ns_if_addref(*aReturn);
12140 }
12141 return NS_OK;
12142}
12143
12144bool nsDocShell::ShouldDiscardLayoutState(nsIHttpChannel* aChannel) {
12145 // By default layout State will be saved.
12146 if (!aChannel) {
12147 return false;
12148 }
12149
12150 // figure out if SH should be saving layout state
12151 bool noStore = false;
12152 Unused << aChannel->IsNoStoreResponse(&noStore);
12153 return noStore;
12154}
12155
12156NS_IMETHODIMPnsresult
12157nsDocShell::GetEditor(nsIEditor** aEditor) {
12158 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"
, 12158); return NS_ERROR_INVALID_POINTER; } } while (false)
;
12159 RefPtr<HTMLEditor> htmlEditor = GetHTMLEditorInternal();
12160 htmlEditor.forget(aEditor);
12161 return NS_OK;
12162}
12163
12164NS_IMETHODIMPnsresult
12165nsDocShell::SetEditor(nsIEditor* aEditor) {
12166 HTMLEditor* htmlEditor = aEditor ? aEditor->GetAsHTMLEditor() : nullptr;
12167 // If TextEditor comes, throw an error.
12168 if (aEditor && !htmlEditor) {
12169 return NS_ERROR_INVALID_ARG;
12170 }
12171 return SetHTMLEditorInternal(htmlEditor);
12172}
12173
12174HTMLEditor* nsDocShell::GetHTMLEditorInternal() {
12175 return mEditorData ? mEditorData->GetHTMLEditor() : nullptr;
12176}
12177
12178nsresult nsDocShell::SetHTMLEditorInternal(HTMLEditor* aHTMLEditor) {
12179 if (!aHTMLEditor && !mEditorData) {
12180 return NS_OK;
12181 }
12182
12183 nsresult rv = EnsureEditorData();
12184 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
12185 return rv;
12186 }
12187
12188 return mEditorData->SetHTMLEditor(aHTMLEditor);
12189}
12190
12191NS_IMETHODIMPnsresult
12192nsDocShell::GetEditable(bool* aEditable) {
12193 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"
, 12193); return NS_ERROR_INVALID_POINTER; } } while (false)
;
12194 *aEditable = mEditorData && mEditorData->GetEditable();
12195 return NS_OK;
12196}
12197
12198NS_IMETHODIMPnsresult
12199nsDocShell::GetHasEditingSession(bool* aHasEditingSession) {
12200 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"
, 12200); return NS_ERROR_INVALID_POINTER; } } while (false)
;
12201
12202 if (mEditorData) {
12203 *aHasEditingSession = !!mEditorData->GetEditingSession();
12204 } else {
12205 *aHasEditingSession = false;
12206 }
12207
12208 return NS_OK;
12209}
12210
12211NS_IMETHODIMPnsresult
12212nsDocShell::MakeEditable(bool aInWaitForUriLoad) {
12213 nsresult rv = EnsureEditorData();
12214 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
12215 return rv;
12216 }
12217
12218 return mEditorData->MakeEditable(aInWaitForUriLoad);
12219}
12220
12221/* static */ bool nsDocShell::ShouldAddURIVisit(nsIChannel* aChannel) {
12222 bool needToAddURIVisit = true;
12223 nsCOMPtr<nsIPropertyBag2> props(do_QueryInterface(aChannel));
12224 if (props) {
12225 mozilla::Unused << props->GetPropertyAsBool(
12226 u"docshell.needToAddURIVisit"_ns, &needToAddURIVisit);
12227 }
12228
12229 return needToAddURIVisit;
12230}
12231
12232/* static */ void nsDocShell::ExtractLastVisit(
12233 nsIChannel* aChannel, nsIURI** aURI, uint32_t* aChannelRedirectFlags) {
12234 nsCOMPtr<nsIPropertyBag2> props(do_QueryInterface(aChannel));
12235 if (!props) {
12236 return;
12237 }
12238
12239 nsresult rv;
12240 nsCOMPtr<nsIURI> uri(do_GetProperty(props, u"docshell.previousURI"_ns, &rv));
12241 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
12242 uri.forget(aURI);
12243
12244 rv = props->GetPropertyAsUint32(u"docshell.previousFlags"_ns,
12245 aChannelRedirectFlags);
12246
12247 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"
, 12249); } } while (false)
12248 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"
, 12249); } } while (false)
12249 "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"
, 12249); } } while (false)
;
12250
12251 } else {
12252 // There is no last visit for this channel, so this must be the first
12253 // link. Link the visit to the referrer of this request, if any.
12254 // Treat referrer as null if there is an error getting it.
12255 NS_GetReferrerFromChannel(aChannel, aURI);
12256 }
12257}
12258
12259void nsDocShell::SaveLastVisit(nsIChannel* aChannel, nsIURI* aURI,
12260 uint32_t aChannelRedirectFlags) {
12261 nsCOMPtr<nsIWritablePropertyBag2> props(do_QueryInterface(aChannel));
12262 if (!props || !aURI) {
12263 return;
12264 }
12265
12266 props->SetPropertyAsInterface(u"docshell.previousURI"_ns, aURI);
12267 props->SetPropertyAsUint32(u"docshell.previousFlags"_ns,
12268 aChannelRedirectFlags);
12269}
12270
12271/* static */ void nsDocShell::InternalAddURIVisit(
12272 nsIURI* aURI, nsIURI* aPreviousURI, uint32_t aChannelRedirectFlags,
12273 uint32_t aResponseStatus, BrowsingContext* aBrowsingContext,
12274 nsIWidget* aWidget, uint32_t aLoadType, bool aWasUpgraded) {
12275 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"
, 12275); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aURI" ") ("
"Visited URI is null!" ")"); do { *((volatile int*)__null) =
12275; __attribute__((nomerge)) ::abort(); } while (false); }
} while (false)
;
12276 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"
, 12277); 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) = 12277; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
12277 "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"
, 12277); 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) = 12277; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
12278
12279 bool usePrivateBrowsing = false;
12280 aBrowsingContext->GetUsePrivateBrowsing(&usePrivateBrowsing);
12281
12282 // Only content-type docshells save URI visits. Also don't do
12283 // anything here if we're not supposed to use global history.
12284 if (!aBrowsingContext->IsContent() ||
12285 !aBrowsingContext->GetUseGlobalHistory() || usePrivateBrowsing) {
12286 return;
12287 }
12288
12289 nsCOMPtr<IHistory> history = components::History::Service();
12290
12291 if (history) {
12292 uint32_t visitURIFlags = 0;
12293
12294 if (aBrowsingContext->IsTop()) {
12295 visitURIFlags |= IHistory::TOP_LEVEL;
12296 }
12297
12298 if (aChannelRedirectFlags & nsIChannelEventSink::REDIRECT_TEMPORARY) {
12299 visitURIFlags |= IHistory::REDIRECT_TEMPORARY;
12300 } else if (aChannelRedirectFlags &
12301 nsIChannelEventSink::REDIRECT_PERMANENT) {
12302 visitURIFlags |= IHistory::REDIRECT_PERMANENT;
12303 } else {
12304 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"
, 12306); 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) = 12306; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
12305 "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"
, 12306); 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) = 12306; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
12306 "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"
, 12306); 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) = 12306; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
;
12307 }
12308
12309 if (aResponseStatus >= 300 && aResponseStatus < 400) {
12310 visitURIFlags |= IHistory::REDIRECT_SOURCE;
12311 if (aResponseStatus == 301 || aResponseStatus == 308) {
12312 visitURIFlags |= IHistory::REDIRECT_SOURCE_PERMANENT;
12313 }
12314 }
12315 // Errors 400-501 and 505 are considered unrecoverable, in the sense a
12316 // simple retry attempt by the user is unlikely to solve them.
12317 // 408 is special cased, since may actually indicate a temporary
12318 // connection problem.
12319 else if (aResponseStatus != 408 &&
12320 ((aResponseStatus >= 400 && aResponseStatus <= 501) ||
12321 aResponseStatus == 505)) {
12322 visitURIFlags |= IHistory::UNRECOVERABLE_ERROR;
12323 }
12324
12325 if (aWasUpgraded) {
12326 visitURIFlags |=
12327 IHistory::REDIRECT_SOURCE | IHistory::REDIRECT_SOURCE_UPGRADED;
12328 }
12329
12330 mozilla::Unused << history->VisitURI(aWidget, aURI, aPreviousURI,
12331 visitURIFlags,
12332 aBrowsingContext->BrowserId());
12333 }
12334}
12335
12336void nsDocShell::AddURIVisit(nsIURI* aURI, nsIURI* aPreviousURI,
12337 uint32_t aChannelRedirectFlags,
12338 uint32_t aResponseStatus) {
12339 nsPIDOMWindowOuter* outer = GetWindow();
12340 nsCOMPtr<nsIWidget> widget = widget::WidgetUtils::DOMWindowToWidget(outer);
12341
12342 InternalAddURIVisit(aURI, aPreviousURI, aChannelRedirectFlags,
12343 aResponseStatus, mBrowsingContext, widget, mLoadType,
12344 false);
12345}
12346
12347//*****************************************************************************
12348// nsDocShell: Helper Routines
12349//*****************************************************************************
12350
12351NS_IMETHODIMPnsresult
12352nsDocShell::SetLoadType(uint32_t aLoadType) {
12353 mLoadType = aLoadType;
12354 return NS_OK;
12355}
12356
12357NS_IMETHODIMPnsresult
12358nsDocShell::GetLoadType(uint32_t* aLoadType) {
12359 *aLoadType = mLoadType;
12360 return NS_OK;
12361}
12362
12363nsresult nsDocShell::ConfirmRepost(bool* aRepost) {
12364 if (StaticPrefs::dom_confirm_repost_testing_always_accept()) {
12365 *aRepost = true;
12366 return NS_OK;
12367 }
12368
12369 nsCOMPtr<nsIPromptCollection> prompter =
12370 do_GetService("@mozilla.org/embedcomp/prompt-collection;1");
12371 if (!prompter) {
12372 return NS_ERROR_NOT_AVAILABLE;
12373 }
12374
12375 return prompter->ConfirmRepost(mBrowsingContext, aRepost);
12376}
12377
12378nsresult nsDocShell::GetPromptAndStringBundle(nsIPrompt** aPrompt,
12379 nsIStringBundle** aStringBundle) {
12380 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"
, 12381); return NS_ERROR_FAILURE; } } while (false)
12381 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"
, 12381); return NS_ERROR_FAILURE; } } while (false)
;
12382
12383 nsCOMPtr<nsIStringBundleService> stringBundleService =
12384 mozilla::components::StringBundle::Service();
12385 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"
, 12385); return NS_ERROR_FAILURE; } } while (false)
;
12386
12387 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"
, 12389); return NS_ERROR_FAILURE; } } while (false)
12388 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"
, 12389); return NS_ERROR_FAILURE; } } while (false)
12389 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"
, 12389); return NS_ERROR_FAILURE; } } while (false)
;
12390
12391 return NS_OK;
12392}
12393
12394ScrollContainerFrame* nsDocShell::GetRootScrollContainerFrame() {
12395 PresShell* presShell = GetPresShell();
12396 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"
, 12396); return nullptr; } } while (false)
;
12397
12398 return presShell->GetRootScrollContainerFrame();
12399}
12400
12401nsresult nsDocShell::EnsureScriptEnvironment() {
12402 if (mScriptGlobal) {
12403 return NS_OK;
12404 }
12405
12406 if (mIsBeingDestroyed) {
12407 return NS_ERROR_NOT_AVAILABLE;
12408 }
12409
12410#ifdef DEBUG1
12411 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"
, 12413); MOZ_PretendNoReturn(); } } while (0)
12412 "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"
, 12413); MOZ_PretendNoReturn(); } } while (0)
12413 "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"
, 12413); MOZ_PretendNoReturn(); } } while (0)
;
12414
12415 // Yeah, this isn't re-entrant safe, but that's ok since if we
12416 // re-enter this method, we'll infinitely loop...
12417 AutoRestore<bool> boolSetter(mInEnsureScriptEnv);
12418 mInEnsureScriptEnv = true;
12419#endif
12420
12421 nsCOMPtr<nsIWebBrowserChrome> browserChrome(do_GetInterface(mTreeOwner));
12422 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"
, 12422); return NS_ERROR_NOT_AVAILABLE; } } while (false)
;
12423
12424 uint32_t chromeFlags;
12425 browserChrome->GetChromeFlags(&chromeFlags);
12426
12427 // If our window is modal and we're not opened as chrome, make
12428 // this window a modal content window.
12429 mScriptGlobal = nsGlobalWindowOuter::Create(this, mItemType == typeChrome);
12430 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"
, 12430); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mScriptGlobal"
")"); do { *((volatile int*)__null) = 12430; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12431
12432 // Ensure the script object is set up to run script.
12433 return mScriptGlobal->EnsureScriptEnvironment();
12434}
12435
12436nsresult nsDocShell::EnsureEditorData() {
12437 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"
, 12437); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mIsBeingDestroyed"
")"); do { *((volatile int*)__null) = 12437; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12438
12439 bool openDocHasDetachedEditor = mOSHE && mOSHE->HasDetachedEditor();
12440 if (!mEditorData && !mIsBeingDestroyed && !openDocHasDetachedEditor) {
12441 // We shouldn't recreate the editor data if it already exists, or
12442 // we're shutting down, or we already have a detached editor data
12443 // stored in the session history. We should only have one editordata
12444 // per docshell.
12445 mEditorData = MakeUnique<nsDocShellEditorData>(this);
12446 }
12447
12448 return mEditorData ? NS_OK : NS_ERROR_NOT_AVAILABLE;
12449}
12450
12451nsresult nsDocShell::EnsureFind() {
12452 if (!mFind) {
12453 mFind = new nsWebBrowserFind();
12454 }
12455
12456 // we promise that the nsIWebBrowserFind that we return has been set
12457 // up to point to the focused, or content window, so we have to
12458 // set that up each time.
12459
12460 nsIScriptGlobalObject* scriptGO = GetScriptGlobalObject();
12461 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"
, 12461); return NS_ERROR_UNEXPECTED; } } while (false)
;
12462
12463 // default to our window
12464 nsCOMPtr<nsPIDOMWindowOuter> ourWindow = do_QueryInterface(scriptGO);
12465 nsCOMPtr<nsPIDOMWindowOuter> windowToSearch;
12466 nsFocusManager::GetFocusedDescendant(ourWindow,
12467 nsFocusManager::eIncludeAllDescendants,
12468 getter_AddRefs(windowToSearch));
12469
12470 nsCOMPtr<nsIWebBrowserFindInFrames> findInFrames = do_QueryInterface(mFind);
12471 if (!findInFrames) {
12472 return NS_ERROR_NO_INTERFACE;
12473 }
12474
12475 nsresult rv = findInFrames->SetRootSearchFrame(ourWindow);
12476 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
12477 return rv;
12478 }
12479 rv = findInFrames->SetCurrentSearchFrame(windowToSearch);
12480 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
12481 return rv;
12482 }
12483
12484 return NS_OK;
12485}
12486
12487NS_IMETHODIMPnsresult
12488nsDocShell::IsBeingDestroyed(bool* aDoomed) {
12489 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"
, 12489); return NS_ERROR_INVALID_ARG; } } while (false)
;
12490 *aDoomed = mIsBeingDestroyed;
12491 return NS_OK;
12492}
12493
12494NS_IMETHODIMPnsresult
12495nsDocShell::GetIsExecutingOnLoadHandler(bool* aResult) {
12496 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"
, 12496); return NS_ERROR_INVALID_ARG; } } while (false)
;
12497 *aResult = mIsExecutingOnLoadHandler;
12498 return NS_OK;
12499}
12500
12501NS_IMETHODIMPnsresult
12502nsDocShell::GetLayoutHistoryState(nsILayoutHistoryState** aLayoutHistoryState) {
12503 nsCOMPtr<nsILayoutHistoryState> state;
12504 if (mozilla::SessionHistoryInParent()) {
12505 if (mActiveEntry) {
12506 state = mActiveEntry->GetLayoutHistoryState();
12507 }
12508 } else {
12509 if (mOSHE) {
12510 state = mOSHE->GetLayoutHistoryState();
12511 }
12512 }
12513 state.forget(aLayoutHistoryState);
12514 return NS_OK;
12515}
12516
12517NS_IMETHODIMPnsresult
12518nsDocShell::SetLayoutHistoryState(nsILayoutHistoryState* aLayoutHistoryState) {
12519 if (mOSHE) {
12520 mOSHE->SetLayoutHistoryState(aLayoutHistoryState);
12521 }
12522 if (mActiveEntry) {
12523 mActiveEntry->SetLayoutHistoryState(aLayoutHistoryState);
12524 }
12525 return NS_OK;
12526}
12527
12528nsDocShell::InterfaceRequestorProxy::InterfaceRequestorProxy(
12529 nsIInterfaceRequestor* aRequestor) {
12530 if (aRequestor) {
12531 mWeakPtr = do_GetWeakReference(aRequestor);
12532 }
12533}
12534
12535nsDocShell::InterfaceRequestorProxy::~InterfaceRequestorProxy() {
12536 mWeakPtr = nullptr;
12537}
12538
12539NS_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"
, 12539); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { *((volatile int*)__null) =
12539; __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"
, 12539); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"nsDocShell::InterfaceRequestorProxy\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 12539; __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"
, 12539); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { *((volatile int*)__null) = 12539
; __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"
, 12539); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"nsDocShell::InterfaceRequestorProxy\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 12539; __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"
, 12539); 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(std::size(table) > 1, "need at least 1 interface"
); rv = NS_TableDrivenQI(static_cast<void*>(this), aIID
, aInstancePtr, table); return rv; }
12540
12541NS_IMETHODIMPnsresult
12542nsDocShell::InterfaceRequestorProxy::GetInterface(const nsIID& aIID,
12543 void** aSink) {
12544 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"
, 12544); return NS_ERROR_INVALID_POINTER; } } while (false)
;
12545 nsCOMPtr<nsIInterfaceRequestor> ifReq = do_QueryReferent(mWeakPtr);
12546 if (ifReq) {
12547 return ifReq->GetInterface(aIID, aSink);
12548 }
12549 *aSink = nullptr;
12550 return NS_NOINTERFACE;
12551}
12552
12553//*****************************************************************************
12554// nsDocShell::nsIAuthPromptProvider
12555//*****************************************************************************
12556
12557NS_IMETHODIMPnsresult
12558nsDocShell::GetAuthPrompt(uint32_t aPromptReason, const nsIID& aIID,
12559 void** aResult) {
12560 // a priority prompt request will override a false mAllowAuth setting
12561 bool priorityPrompt = (aPromptReason == PROMPT_PROXY);
12562
12563 if (!mAllowAuth && !priorityPrompt) {
12564 return NS_ERROR_NOT_AVAILABLE;
12565 }
12566
12567 // we're either allowing auth, or it's a proxy request
12568 nsresult rv;
12569 nsCOMPtr<nsIPromptFactory> wwatch =
12570 do_GetService(NS_WINDOWWATCHER_CONTRACTID"@mozilla.org/embedcomp/window-watcher;1", &rv);
12571 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"
, 12571); return rv; } } while (false)
;
12572
12573 rv = EnsureScriptEnvironment();
12574 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"
, 12574); return rv; } } while (false)
;
12575
12576 // Get the an auth prompter for our window so that the parenting
12577 // of the dialogs works as it should when using tabs.
12578
12579 return wwatch->GetPrompt(mScriptGlobal, aIID,
12580 reinterpret_cast<void**>(aResult));
12581}
12582
12583//*****************************************************************************
12584// nsDocShell::nsILoadContext
12585//*****************************************************************************
12586
12587NS_IMETHODIMPnsresult
12588nsDocShell::GetAssociatedWindow(mozIDOMWindowProxy** aWindow) {
12589 CallGetInterface(this, aWindow);
12590 return NS_OK;
12591}
12592
12593NS_IMETHODIMPnsresult
12594nsDocShell::GetTopWindow(mozIDOMWindowProxy** aWindow) {
12595 return mBrowsingContext->GetTopWindow(aWindow);
12596}
12597
12598NS_IMETHODIMPnsresult
12599nsDocShell::GetTopFrameElement(Element** aElement) {
12600 return mBrowsingContext->GetTopFrameElement(aElement);
12601}
12602
12603NS_IMETHODIMPnsresult
12604nsDocShell::GetUseTrackingProtection(bool* aUseTrackingProtection) {
12605 return mBrowsingContext->GetUseTrackingProtection(aUseTrackingProtection);
12606}
12607
12608NS_IMETHODIMPnsresult
12609nsDocShell::SetUseTrackingProtection(bool aUseTrackingProtection) {
12610 return mBrowsingContext->SetUseTrackingProtection(aUseTrackingProtection);
12611}
12612
12613NS_IMETHODIMPnsresult
12614nsDocShell::GetIsContent(bool* aIsContent) {
12615 *aIsContent = (mItemType == typeContent);
12616 return NS_OK;
12617}
12618
12619bool nsDocShell::IsOKToLoadURI(nsIURI* aURI) {
12620 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"
, 12620); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aURI" ") ("
"Must have a URI!" ")"); do { *((volatile int*)__null) = 12620
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
;
12621
12622 if (!mFiredUnloadEvent) {
12623 return true;
12624 }
12625
12626 if (!mLoadingURI) {
12627 return false;
12628 }
12629
12630 bool isPrivateWin = false;
12631 Document* doc = GetDocument();
12632 if (doc) {
12633 isPrivateWin =
12634 doc->NodePrincipal()->OriginAttributesRef().IsPrivateBrowsing();
12635 }
12636
12637 nsCOMPtr<nsIScriptSecurityManager> secMan =
12638 do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID"@mozilla.org/scriptsecuritymanager;1");
12639 return secMan && NS_SUCCEEDED(secMan->CheckSameOriginURI(((bool)(__builtin_expect(!!(!NS_FAILED_impl(secMan->CheckSameOriginURI
( aURI, mLoadingURI, false, isPrivateWin))), 1)))
12640 aURI, mLoadingURI, false, isPrivateWin))((bool)(__builtin_expect(!!(!NS_FAILED_impl(secMan->CheckSameOriginURI
( aURI, mLoadingURI, false, isPrivateWin))), 1)))
;
12641}
12642
12643//
12644// Routines for selection and clipboard
12645//
12646nsresult nsDocShell::GetControllerForCommand(const char* aCommand,
12647 nsIController** aResult) {
12648 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"
, 12648); return NS_ERROR_INVALID_POINTER; } } while (false)
;
12649 *aResult = nullptr;
12650
12651 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"
, 12651); return NS_ERROR_FAILURE; } } while (false)
;
12652
12653 nsCOMPtr<nsPIWindowRoot> root = mScriptGlobal->GetTopWindowRoot();
12654 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"
, 12654); return NS_ERROR_FAILURE; } } while (false)
;
12655
12656 return root->GetControllerForCommand(aCommand, false /* for any window */,
12657 aResult);
12658}
12659
12660NS_IMETHODIMPnsresult
12661nsDocShell::IsCommandEnabled(const char* aCommand, bool* aResult) {
12662 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"
, 12662); return NS_ERROR_INVALID_POINTER; } } while (false)
;
12663 *aResult = false;
12664
12665 nsresult rv = NS_ERROR_FAILURE;
12666
12667 nsCOMPtr<nsIController> controller;
12668 rv = GetControllerForCommand(aCommand, getter_AddRefs(controller));
12669 if (controller) {
12670 rv = controller->IsCommandEnabled(aCommand, aResult);
12671 }
12672
12673 return rv;
12674}
12675
12676NS_IMETHODIMPnsresult
12677nsDocShell::DoCommand(const char* aCommand) {
12678 nsresult rv = NS_ERROR_FAILURE;
12679
12680 nsCOMPtr<nsIController> controller;
12681 rv = GetControllerForCommand(aCommand, getter_AddRefs(controller));
12682 if (controller) {
12683 rv = controller->DoCommand(aCommand);
12684 }
12685
12686 return rv;
12687}
12688
12689NS_IMETHODIMPnsresult
12690nsDocShell::DoCommandWithParams(const char* aCommand,
12691 nsICommandParams* aParams) {
12692 nsCOMPtr<nsIController> controller;
12693 nsresult rv = GetControllerForCommand(aCommand, getter_AddRefs(controller));
12694 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"
, 12694)
) {
12695 return rv;
12696 }
12697
12698 nsCOMPtr<nsICommandController> commandController =
12699 do_QueryInterface(controller, &rv);
12700 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"
, 12700)
) {
12701 return rv;
12702 }
12703
12704 return commandController->DoCommandWithParams(aCommand, aParams);
12705}
12706
12707nsresult nsDocShell::EnsureCommandHandler() {
12708 if (!mCommandManager) {
12709 if (nsCOMPtr<nsPIDOMWindowOuter> domWindow = GetWindow()) {
12710 mCommandManager = new nsCommandManager(domWindow);
12711 }
12712 }
12713 return mCommandManager ? NS_OK : NS_ERROR_FAILURE;
12714}
12715
12716// link handling
12717
12718class OnLinkClickEvent : public Runnable {
12719 public:
12720 OnLinkClickEvent(nsDocShell* aHandler, nsIContent* aContent,
12721 nsDocShellLoadState* aLoadState, bool aNoOpenerImplied,
12722 nsIPrincipal* aTriggeringPrincipal);
12723
12724 NS_IMETHODvirtual nsresult Run() override {
12725 // We need to set up an AutoJSAPI here for the following reason: When we
12726 // do OnLinkClickSync we'll eventually end up in
12727 // nsGlobalWindow::OpenInternal which only does popup blocking if
12728 // !LegacyIsCallerChromeOrNativeCode(). So we need to fake things so that
12729 // we don't look like native code as far as LegacyIsCallerNativeCode() is
12730 // concerned. (Bug 1930445)
12731 AutoJSAPI jsapi;
12732 if (jsapi.Init(mContent->OwnerDoc()->GetScopeObject())) {
12733 mHandler->OnLinkClickSync(mContent, mLoadState, mNoOpenerImplied,
12734 mTriggeringPrincipal);
12735 }
12736 return NS_OK;
12737 }
12738
12739 private:
12740 RefPtr<nsDocShell> mHandler;
12741 nsCOMPtr<nsIContent> mContent;
12742 RefPtr<nsDocShellLoadState> mLoadState;
12743 nsCOMPtr<nsIPrincipal> mTriggeringPrincipal;
12744 bool mNoOpenerImplied;
12745};
12746
12747OnLinkClickEvent::OnLinkClickEvent(nsDocShell* aHandler, nsIContent* aContent,
12748 nsDocShellLoadState* aLoadState,
12749 bool aNoOpenerImplied,
12750 nsIPrincipal* aTriggeringPrincipal)
12751 : mozilla::Runnable("OnLinkClickEvent"),
12752 mHandler(aHandler),
12753 mContent(aContent),
12754 mLoadState(aLoadState),
12755 mTriggeringPrincipal(aTriggeringPrincipal),
12756 mNoOpenerImplied(aNoOpenerImplied) {}
12757
12758nsresult nsDocShell::OnLinkClick(
12759 nsIContent* aContent, nsIURI* aURI, const nsAString& aTargetSpec,
12760 const nsAString& aFileName, nsIInputStream* aPostDataStream,
12761 nsIInputStream* aHeadersDataStream, bool aIsUserTriggered,
12762 nsIPrincipal* aTriggeringPrincipal, nsIContentSecurityPolicy* aCsp) {
12763#ifndef ANDROID
12764 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"
, 12764); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aTriggeringPrincipal"
") (" "Need a valid triggeringPrincipal" ")"); do { *((volatile
int*)__null) = 12764; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
12765#endif
12766 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"
, 12766); MOZ_PretendNoReturn(); } } while (0)
;
12767
12768 if (!IsNavigationAllowed() || !IsOKToLoadURI(aURI)) {
12769 return NS_OK;
12770 }
12771
12772 // On history navigation through Back/Forward buttons, don't execute
12773 // automatic JavaScript redirection such as |anchorElement.click()| or
12774 // |formElement.submit()|.
12775 //
12776 // XXX |formElement.submit()| bypasses this checkpoint because it calls
12777 // nsDocShell::OnLinkClickSync(...) instead.
12778 if (ShouldBlockLoadingForBackButton()) {
12779 return NS_OK;
12780 }
12781
12782 if (aContent->IsEditable()) {
12783 return NS_OK;
12784 }
12785
12786 Document* ownerDoc = aContent->OwnerDoc();
12787 if (nsContentUtils::IsExternalProtocol(aURI)) {
12788 ownerDoc->EnsureNotEnteringAndExitFullscreen();
12789 }
12790
12791 bool noOpenerImplied = false;
12792 nsAutoString target(aTargetSpec);
12793 if (aFileName.IsVoid() &&
12794 ShouldOpenInBlankTarget(aTargetSpec, aURI, aContent, aIsUserTriggered)) {
12795 target = u"_blank";
12796 if (!aTargetSpec.Equals(target)) {
12797 noOpenerImplied = true;
12798 }
12799 }
12800
12801 RefPtr<nsDocShellLoadState> loadState = new nsDocShellLoadState(aURI);
12802 loadState->SetTarget(target);
12803 loadState->SetFileName(aFileName);
12804 loadState->SetPostDataStream(aPostDataStream);
12805 loadState->SetHeadersStream(aHeadersDataStream);
12806 loadState->SetFirstParty(true);
12807 loadState->SetTriggeringPrincipal(
12808 aTriggeringPrincipal ? aTriggeringPrincipal : aContent->NodePrincipal());
12809 loadState->SetPrincipalToInherit(aContent->NodePrincipal());
12810 loadState->SetCsp(aCsp ? aCsp : aContent->GetCsp());
12811 loadState->SetAllowFocusMove(UserActivation::IsHandlingUserInput());
12812
12813 const bool hasValidUserGestureActivation =
12814 ownerDoc->HasValidTransientUserGestureActivation();
12815 loadState->SetHasValidUserGestureActivation(hasValidUserGestureActivation);
12816 loadState->SetTextDirectiveUserActivation(
12817 ownerDoc->ConsumeTextDirectiveUserActivation() ||
12818 hasValidUserGestureActivation);
12819
12820 nsCOMPtr<nsIRunnable> ev = new OnLinkClickEvent(
12821 this, aContent, loadState, noOpenerImplied, aTriggeringPrincipal);
12822 return Dispatch(ev.forget());
12823}
12824
12825bool nsDocShell::ShouldOpenInBlankTarget(const nsAString& aOriginalTarget,
12826 nsIURI* aLinkURI, nsIContent* aContent,
12827 bool aIsUserTriggered) {
12828 if (net::SchemeIsJavascript(aLinkURI)) {
12829 return false;
12830 }
12831
12832 // External links from within app tabs should always open in new tabs
12833 // instead of replacing the app tab's page (Bug 575561)
12834 // nsIURI.host can throw for non-nsStandardURL nsIURIs. If we fail to
12835 // get either host, just return false to use the original target.
12836 nsAutoCString linkHost;
12837 if (NS_FAILED(aLinkURI->GetHost(linkHost))((bool)(__builtin_expect(!!(NS_FAILED_impl(aLinkURI->GetHost
(linkHost))), 0)))
) {
12838 return false;
12839 }
12840
12841 // The targetTopLevelLinkClicksToBlank property on BrowsingContext allows
12842 // privileged code to change the default targeting behaviour. In particular,
12843 // if a user-initiated link click for the (or targetting the) top-level frame
12844 // is detected, we default the target to "_blank" to give it a new
12845 // top-level BrowsingContext.
12846 if (mBrowsingContext->TargetTopLevelLinkClicksToBlank() && aIsUserTriggered &&
12847 ((aOriginalTarget.IsEmpty() && mBrowsingContext->IsTop()) ||
12848 aOriginalTarget == u"_top"_ns)) {
12849 return true;
12850 }
12851
12852 // Don't modify non-default targets.
12853 if (!aOriginalTarget.IsEmpty()) {
12854 return false;
12855 }
12856
12857 // Only check targets that are in extension panels or app tabs.
12858 // (isAppTab will be false for app tab subframes).
12859 nsString mmGroup = mBrowsingContext->Top()->GetMessageManagerGroup();
12860 if (!mmGroup.EqualsLiteral("webext-browsers") &&
12861 !mBrowsingContext->IsAppTab()) {
12862 return false;
12863 }
12864
12865 nsCOMPtr<nsIURI> docURI = aContent->OwnerDoc()->GetDocumentURIObject();
12866 if (!docURI) {
12867 return false;
12868 }
12869
12870 nsAutoCString docHost;
12871 if (NS_FAILED(docURI->GetHost(docHost))((bool)(__builtin_expect(!!(NS_FAILED_impl(docURI->GetHost
(docHost))), 0)))
) {
12872 return false;
12873 }
12874
12875 if (linkHost.Equals(docHost)) {
12876 return false;
12877 }
12878
12879 // Special case: ignore "www" prefix if it is part of host string
12880 return linkHost.Length() < docHost.Length()
12881 ? !docHost.Equals("www."_ns + linkHost)
12882 : !linkHost.Equals("www."_ns + docHost);
12883}
12884
12885static bool ElementCanHaveNoopener(nsIContent* aContent) {
12886 // Make sure we are dealing with either an <A>, <AREA>, or <FORM> element in
12887 // the HTML, XHTML, or SVG namespace.
12888 return aContent->IsAnyOfHTMLElements(nsGkAtoms::a, nsGkAtoms::area,
12889 nsGkAtoms::form) ||
12890 aContent->IsSVGElement(nsGkAtoms::a);
12891}
12892
12893nsresult nsDocShell::OnLinkClickSync(nsIContent* aContent,
12894 nsDocShellLoadState* aLoadState,
12895 bool aNoOpenerImplied,
12896 nsIPrincipal* aTriggeringPrincipal) {
12897 if (!IsNavigationAllowed() || !IsOKToLoadURI(aLoadState->URI())) {
12898 return NS_OK;
12899 }
12900
12901 // XXX When the linking node was HTMLFormElement, it is synchronous event.
12902 // That is, the caller of this method is not |OnLinkClickEvent::Run()|
12903 // but |HTMLFormElement::SubmitSubmission(...)|.
12904 if (aContent->IsHTMLElement(nsGkAtoms::form) &&
12905 ShouldBlockLoadingForBackButton()) {
12906 return NS_OK;
12907 }
12908
12909 if (aContent->IsEditable()) {
12910 return NS_OK;
12911 }
12912
12913 // if the triggeringPrincipal is not passed explicitly, then we
12914 // fall back to using doc->NodePrincipal() as the triggeringPrincipal.
12915 nsCOMPtr<nsIPrincipal> triggeringPrincipal =
12916 aTriggeringPrincipal ? aTriggeringPrincipal : aContent->NodePrincipal();
12917
12918 {
12919 // defer to an external protocol handler if necessary...
12920 nsCOMPtr<nsIExternalProtocolService> extProtService =
12921 do_GetService(NS_EXTERNALPROTOCOLSERVICE_CONTRACTID"@mozilla.org/uriloader/external-protocol-service;1");
12922 if (extProtService) {
12923 nsAutoCString scheme;
12924 aLoadState->URI()->GetScheme(scheme);
12925 if (!scheme.IsEmpty()) {
12926 // if the URL scheme does not correspond to an exposed protocol, then
12927 // we need to hand this link click over to the external protocol
12928 // handler.
12929 bool isExposed;
12930 nsresult rv =
12931 extProtService->IsExposedProtocol(scheme.get(), &isExposed);
12932 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && !isExposed) {
12933 return extProtService->LoadURI(
12934 aLoadState->URI(), triggeringPrincipal, nullptr, mBrowsingContext,
12935 /* aTriggeredExternally */
12936 false,
12937 /* aHasValidUserGestureActivation */
12938 aContent->OwnerDoc()->HasValidTransientUserGestureActivation(),
12939 /* aNewWindowTarget */ false);
12940 }
12941 }
12942 }
12943 }
12944 uint32_t triggeringSandboxFlags = 0;
12945 uint64_t triggeringWindowId = 0;
12946 bool triggeringStorageAccess = false;
12947 if (mBrowsingContext) {
12948 triggeringSandboxFlags = aContent->OwnerDoc()->GetSandboxFlags();
12949 triggeringWindowId = aContent->OwnerDoc()->InnerWindowID();
12950 triggeringStorageAccess = aContent->OwnerDoc()->UsingStorageAccess();
12951 }
12952
12953 uint32_t flags = INTERNAL_LOAD_FLAGS_NONE;
12954 bool elementCanHaveNoopener = ElementCanHaveNoopener(aContent);
12955 bool triggeringPrincipalIsSystemPrincipal =
12956 aLoadState->TriggeringPrincipal()->IsSystemPrincipal();
12957 if (elementCanHaveNoopener) {
12958 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"
, 12958); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aContent->IsHTMLElement() || aContent->IsSVGElement()"
")"); do { *((volatile int*)__null) = 12958; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12959 nsAutoString relString;
12960 aContent->AsElement()->GetAttr(nsGkAtoms::rel, relString);
12961 nsWhitespaceTokenizerTemplate<nsContentUtils::IsHTMLWhitespace> tok(
12962 relString);
12963
12964 bool targetBlank = aLoadState->Target().LowerCaseEqualsLiteral("_blank");
12965 bool explicitOpenerSet = false;
12966
12967 // The opener behaviour follows a hierarchy, such that if a higher
12968 // priority behaviour is specified, it always takes priority. That
12969 // priority is currently: norefrerer > noopener > opener > default
12970
12971 while (tok.hasMoreTokens()) {
12972 const nsAString& token = tok.nextToken();
12973 if (token.LowerCaseEqualsLiteral("noreferrer")) {
12974 flags |= INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER |
12975 INTERNAL_LOAD_FLAGS_NO_OPENER;
12976 // noreferrer cannot be overwritten by a 'rel=opener'.
12977 explicitOpenerSet = true;
12978 break;
12979 }
12980
12981 if (token.LowerCaseEqualsLiteral("noopener")) {
12982 flags |= INTERNAL_LOAD_FLAGS_NO_OPENER;
12983 explicitOpenerSet = true;
12984 }
12985
12986 if (targetBlank && StaticPrefs::dom_targetBlankNoOpener_enabled() &&
12987 token.LowerCaseEqualsLiteral("opener") && !explicitOpenerSet) {
12988 explicitOpenerSet = true;
12989 }
12990 }
12991
12992 if (targetBlank && StaticPrefs::dom_targetBlankNoOpener_enabled() &&
12993 !explicitOpenerSet && !triggeringPrincipalIsSystemPrincipal) {
12994 flags |= INTERNAL_LOAD_FLAGS_NO_OPENER;
12995 }
12996
12997 if (aNoOpenerImplied) {
12998 flags |= INTERNAL_LOAD_FLAGS_NO_OPENER;
12999 }
13000 }
13001
13002 // Get the owner document of the link that was clicked, this will be
13003 // the document that the link is in, or the last document that the
13004 // link was in. From that document, we'll get the URI to use as the
13005 // referrer, since the current URI in this docshell may be a
13006 // new document that we're in the process of loading.
13007 RefPtr<Document> referrerDoc = aContent->OwnerDoc();
13008
13009 // Now check that the referrerDoc's inner window is the current inner
13010 // window for mScriptGlobal. If it's not, then we don't want to
13011 // follow this link.
13012 nsPIDOMWindowInner* referrerInner = referrerDoc->GetInnerWindow();
13013 if (!mScriptGlobal || !referrerInner ||
13014 mScriptGlobal->GetCurrentInnerWindow() != referrerInner) {
13015 // We're no longer the current inner window
13016 return NS_OK;
13017 }
13018
13019 // referrer could be null here in some odd cases, but that's ok,
13020 // we'll just load the link w/o sending a referrer in those cases.
13021
13022 // If this is an anchor element, grab its type property to use as a hint
13023 nsAutoString typeHint;
13024 RefPtr<HTMLAnchorElement> anchor = HTMLAnchorElement::FromNode(aContent);
13025 if (anchor) {
13026 anchor->GetType(typeHint);
13027 NS_ConvertUTF16toUTF8 utf8Hint(typeHint);
13028 nsAutoCString type, dummy;
13029 NS_ParseRequestContentType(utf8Hint, type, dummy);
13030 CopyUTF8toUTF16(type, typeHint);
13031 }
13032
13033 uint32_t loadType = LOAD_LINK;
13034 if (aLoadState->IsFormSubmission()) {
13035 if (aLoadState->Target().IsEmpty()) {
13036 // We set the right load type here for form submissions with an empty
13037 // target. Form submission with a non-empty target are handled in
13038 // nsDocShell::PerformRetargeting after we've selected the correct target
13039 // BC.
13040 loadType = GetLoadTypeForFormSubmission(GetBrowsingContext(), aLoadState);
13041 }
13042 } else {
13043 // Link click can be triggered inside an onload handler, and we don't want
13044 // to add history entry in this case.
13045 bool inOnLoadHandler = false;
13046 GetIsExecutingOnLoadHandler(&inOnLoadHandler);
13047 if (inOnLoadHandler) {
13048 loadType = LOAD_NORMAL_REPLACE;
13049 }
13050 }
13051
13052 nsCOMPtr<nsIReferrerInfo> referrerInfo =
13053 elementCanHaveNoopener ? new ReferrerInfo(*aContent->AsElement())
13054 : new ReferrerInfo(*referrerDoc);
13055
13056 aLoadState->SetTriggeringSandboxFlags(triggeringSandboxFlags);
13057 aLoadState->SetTriggeringWindowId(triggeringWindowId);
13058 aLoadState->SetTriggeringStorageAccess(triggeringStorageAccess);
13059 aLoadState->SetReferrerInfo(referrerInfo);
13060 aLoadState->SetInternalLoadFlags(flags);
13061 aLoadState->SetTypeHint(NS_ConvertUTF16toUTF8(typeHint));
13062 aLoadState->SetLoadType(loadType);
13063 aLoadState->SetSourceBrowsingContext(mBrowsingContext);
13064
13065 nsresult rv = InternalLoad(aLoadState);
13066
13067 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
13068 nsPingListener::DispatchPings(this, aContent, aLoadState->URI(),
13069 referrerInfo);
13070 }
13071
13072 return rv;
13073}
13074
13075nsresult nsDocShell::OnOverLink(nsIContent* aContent, nsIURI* aURI,
13076 const nsAString& aTargetSpec) {
13077 if (aContent->IsEditable()) {
13078 return NS_OK;
13079 }
13080
13081 nsresult rv = NS_ERROR_FAILURE;
13082
13083 nsCOMPtr<nsIWebBrowserChrome> browserChrome = do_GetInterface(mTreeOwner);
13084 if (!browserChrome) {
13085 return rv;
13086 }
13087
13088 nsCOMPtr<nsIURI> exposableURI = nsIOService::CreateExposableURI(aURI);
13089 nsAutoCString spec;
13090 rv = exposableURI->GetDisplaySpec(spec);
13091 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"
, 13091); return rv; } } while (false)
;
13092
13093 NS_ConvertUTF8toUTF16 uStr(spec);
13094
13095 PredictorPredict(aURI, mCurrentURI, nsINetworkPredictor::PREDICT_LINK,
13096 aContent->NodePrincipal()->OriginAttributesRef(), nullptr);
13097
13098 rv = browserChrome->SetLinkStatus(uStr);
13099 return rv;
13100}
13101
13102nsresult nsDocShell::OnLeaveLink() {
13103 nsCOMPtr<nsIWebBrowserChrome> browserChrome(do_GetInterface(mTreeOwner));
13104 nsresult rv = NS_ERROR_FAILURE;
13105
13106 if (browserChrome) {
13107 rv = browserChrome->SetLinkStatus(u""_ns);
13108 }
13109 return rv;
13110}
13111
13112bool nsDocShell::ShouldBlockLoadingForBackButton() {
13113 if (!(mLoadType & LOAD_CMD_HISTORY) ||
13114 UserActivation::IsHandlingUserInput() ||
13115 !Preferences::GetBool("accessibility.blockjsredirection")) {
13116 return false;
13117 }
13118
13119 bool canGoForward = false;
13120 GetCanGoForward(&canGoForward);
13121 return canGoForward;
13122}
13123
13124//----------------------------------------------------------------------
13125// Web Shell Services API
13126
13127// This functions is only called when a new charset is detected in loading a
13128// document.
13129nsresult nsDocShell::CharsetChangeReloadDocument(
13130 mozilla::NotNull<const mozilla::Encoding*> aEncoding, int32_t aSource) {
13131 // XXX hack. keep the aCharset and aSource wait to pick it up
13132 nsCOMPtr<nsIDocumentViewer> viewer;
13133 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"
, 13133); return NS_ERROR_FAILURE; } } while (false)
;
13134 if (viewer) {
13135 int32_t source;
13136 Unused << viewer->GetReloadEncodingAndSource(&source);
13137 if (aSource > source) {
13138 viewer->SetReloadEncodingAndSource(aEncoding, aSource);
13139 if (eCharsetReloadRequested != mCharsetReloadState) {
13140 mCharsetReloadState = eCharsetReloadRequested;
13141 switch (mLoadType) {
13142 case LOAD_RELOAD_BYPASS_PROXY_AND_CACHE:
13143 return Reload(LOAD_FLAGS_CHARSET_CHANGE | LOAD_FLAGS_BYPASS_CACHE |
13144 LOAD_FLAGS_BYPASS_PROXY);
13145 case LOAD_RELOAD_BYPASS_CACHE:
13146 return Reload(LOAD_FLAGS_CHARSET_CHANGE | LOAD_FLAGS_BYPASS_CACHE);
13147 default:
13148 return Reload(LOAD_FLAGS_CHARSET_CHANGE);
13149 }
13150 }
13151 }
13152 }
13153 // return failure if this request is not accepted due to mCharsetReloadState
13154 return NS_ERROR_DOCSHELL_REQUEST_REJECTED;
13155}
13156
13157nsresult nsDocShell::CharsetChangeStopDocumentLoad() {
13158 if (eCharsetReloadRequested != mCharsetReloadState) {
13159 Stop(nsIWebNavigation::STOP_ALL);
13160 return NS_OK;
13161 }
13162 // return failer if this request is not accepted due to mCharsetReloadState
13163 return NS_ERROR_DOCSHELL_REQUEST_REJECTED;
13164}
13165
13166NS_IMETHODIMPnsresult nsDocShell::ExitPrintPreview() {
13167#if NS_PRINT_PREVIEW1
13168 nsCOMPtr<nsIWebBrowserPrint> viewer = do_QueryInterface(mDocumentViewer);
13169 return viewer->ExitPrintPreview();
13170#else
13171 return NS_OK;
13172#endif
13173}
13174
13175/* [infallible] */
13176NS_IMETHODIMPnsresult nsDocShell::GetIsTopLevelContentDocShell(
13177 bool* aIsTopLevelContentDocShell) {
13178 *aIsTopLevelContentDocShell = false;
13179
13180 if (mItemType == typeContent) {
13181 *aIsTopLevelContentDocShell = mBrowsingContext->IsTopContent();
13182 }
13183
13184 return NS_OK;
13185}
13186
13187// Implements nsILoadContext.originAttributes
13188NS_IMETHODIMPnsresult
13189nsDocShell::GetScriptableOriginAttributes(JSContext* aCx,
13190 JS::MutableHandle<JS::Value> aVal) {
13191 return mBrowsingContext->GetScriptableOriginAttributes(aCx, aVal);
13192}
13193
13194// Implements nsIDocShell.GetOriginAttributes()
13195NS_IMETHODIMPnsresult
13196nsDocShell::GetOriginAttributes(JSContext* aCx,
13197 JS::MutableHandle<JS::Value> aVal) {
13198 return mBrowsingContext->GetScriptableOriginAttributes(aCx, aVal);
13199}
13200
13201bool nsDocShell::ServiceWorkerAllowedToControlWindow(nsIPrincipal* aPrincipal,
13202 nsIURI* aURI) {
13203 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"
, 13203); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPrincipal"
")"); do { *((volatile int*)__null) = 13203; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
13204 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"
, 13204); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aURI" ")")
; do { *((volatile int*)__null) = 13204; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
13205
13206 if (UsePrivateBrowsing() || mBrowsingContext->GetSandboxFlags()) {
13207 return false;
13208 }
13209
13210 nsCOMPtr<nsIDocShellTreeItem> parent;
13211 GetInProcessSameTypeParent(getter_AddRefs(parent));
13212 nsPIDOMWindowOuter* parentOuter = parent ? parent->GetWindow() : nullptr;
13213 nsPIDOMWindowInner* parentInner =
13214 parentOuter ? parentOuter->GetCurrentInnerWindow() : nullptr;
13215
13216 StorageAccess storage =
13217 StorageAllowedForNewWindow(aPrincipal, aURI, parentInner);
13218
13219 // If the partitioned service worker is enabled, service worker is allowed to
13220 // control the window if partition is enabled.
13221 if (StaticPrefs::privacy_partition_serviceWorkers() && parentInner) {
13222 RefPtr<Document> doc = parentInner->GetExtantDoc();
13223
13224 if (doc && StoragePartitioningEnabled(storage, doc->CookieJarSettings())) {
13225 return true;
13226 }
13227 }
13228
13229 return storage == StorageAccess::eAllow;
13230}
13231
13232nsresult nsDocShell::SetOriginAttributes(const OriginAttributes& aAttrs) {
13233 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"
, 13233); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mIsBeingDestroyed"
")"); do { *((volatile int*)__null) = 13233; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
13234 return mBrowsingContext->SetOriginAttributes(aAttrs);
13235}
13236
13237NS_IMETHODIMPnsresult
13238nsDocShell::ResumeRedirectedLoad(uint64_t aIdentifier, int32_t aHistoryIndex) {
13239 RefPtr<nsDocShell> self = this;
13240 RefPtr<ChildProcessChannelListener> cpcl =
13241 ChildProcessChannelListener::GetSingleton();
13242
13243 // Call into InternalLoad with the pending channel when it is received.
13244 cpcl->RegisterCallback(
13245 aIdentifier, [self, aHistoryIndex](
13246 nsDocShellLoadState* aLoadState,
13247 nsTArray<Endpoint<extensions::PStreamFilterParent>>&&
13248 aStreamFilterEndpoints,
13249 nsDOMNavigationTiming* aTiming) {
13250 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"
, 13250); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->GetPendingRedirectedChannel()"
")"); do { *((volatile int*)__null) = 13250; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
13251 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"
, 13251)
) {
13252 aLoadState->GetPendingRedirectedChannel()->CancelWithReason(
13253 NS_BINDING_ABORTED, "nsDocShell::mIsBeingDestroyed"_ns);
13254 return NS_BINDING_ABORTED;
13255 }
13256
13257 self->mLoadType = aLoadState->LoadType();
13258 nsCOMPtr<nsIURI> previousURI;
13259 uint32_t previousFlags = 0;
13260 ExtractLastVisit(aLoadState->GetPendingRedirectedChannel(),
13261 getter_AddRefs(previousURI), &previousFlags);
13262 self->SaveLastVisit(aLoadState->GetPendingRedirectedChannel(),
13263 previousURI, previousFlags);
13264
13265 if (aTiming) {
13266 self->mTiming = new nsDOMNavigationTiming(self, aTiming);
13267 self->mBlankTiming = false;
13268 }
13269
13270 // If we're performing a history load, locate the correct history entry,
13271 // and set the relevant bits on our loadState.
13272 if (aHistoryIndex >= 0 && self->GetSessionHistory() &&
13273 !mozilla::SessionHistoryInParent()) {
13274 nsCOMPtr<nsISHistory> legacySHistory =
13275 self->GetSessionHistory()->LegacySHistory();
13276
13277 nsCOMPtr<nsISHEntry> entry;
13278 nsresult rv = legacySHistory->GetEntryAtIndex(aHistoryIndex,
13279 getter_AddRefs(entry));
13280 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
13281 legacySHistory->InternalSetRequestedIndex(aHistoryIndex);
13282 aLoadState->SetLoadType(LOAD_HISTORY);
13283 aLoadState->SetSHEntry(entry);
13284 }
13285 }
13286
13287 self->InternalLoad(aLoadState);
13288
13289 if (aLoadState->GetOriginalURIString().isSome()) {
13290 // Save URI string in case it's needed later when
13291 // sending to search engine service in EndPageLoad()
13292 self->mOriginalUriString = *aLoadState->GetOriginalURIString();
13293 }
13294
13295 for (auto& endpoint : aStreamFilterEndpoints) {
13296 extensions::StreamFilterParent::Attach(
13297 aLoadState->GetPendingRedirectedChannel(), std::move(endpoint));
13298 }
13299
13300 // If the channel isn't pending, then it means that InternalLoad
13301 // never connected it, and we shouldn't try to continue. This
13302 // can happen even if InternalLoad returned NS_OK.
13303 bool pending = false;
13304 aLoadState->GetPendingRedirectedChannel()->IsPending(&pending);
13305 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"
, 13305); MOZ_PretendNoReturn(); } } while (0)
;
13306 if (!pending) {
13307 return NS_BINDING_ABORTED;
13308 }
13309 return NS_OK;
13310 });
13311 return NS_OK;
13312}
13313
13314NS_IMETHODIMPnsresult
13315nsDocShell::SetOriginAttributes(JS::Handle<JS::Value> aOriginAttributes,
13316 JSContext* aCx) {
13317 OriginAttributes attrs;
13318 if (!aOriginAttributes.isObject() || !attrs.Init(aCx, aOriginAttributes)) {
13319 return NS_ERROR_INVALID_ARG;
13320 }
13321
13322 return SetOriginAttributes(attrs);
13323}
13324
13325NS_IMETHODIMPnsresult
13326nsDocShell::GetAsyncPanZoomEnabled(bool* aOut) {
13327 if (PresShell* presShell = GetPresShell()) {
13328 *aOut = presShell->AsyncPanZoomEnabled();
13329 return NS_OK;
13330 }
13331
13332 // If we don't have a presShell, fall back to the default platform value of
13333 // whether or not APZ is enabled.
13334 *aOut = gfxPlatform::AsyncPanZoomEnabled();
13335 return NS_OK;
13336}
13337
13338bool nsDocShell::HasUnloadedParent() {
13339 for (WindowContext* wc = GetBrowsingContext()->GetParentWindowContext(); wc;
13340 wc = wc->GetParentWindowContext()) {
13341 if (!wc->IsCurrent() || wc->IsDiscarded() ||
13342 wc->GetBrowsingContext()->IsDiscarded()) {
13343 // If a parent is OOP and the parent WindowContext is no
13344 // longer current, we can assume the parent was unloaded.
13345 return true;
13346 }
13347
13348 if (wc->GetBrowsingContext()->IsInProcess() &&
13349 (!wc->GetBrowsingContext()->GetDocShell() ||
13350 wc->GetBrowsingContext()->GetDocShell()->GetIsInUnload())) {
13351 return true;
13352 }
13353 }
13354 return false;
13355}
13356
13357/* static */
13358bool nsDocShell::ShouldUpdateGlobalHistory(uint32_t aLoadType) {
13359 return !(aLoadType == LOAD_BYPASS_HISTORY || aLoadType == LOAD_ERROR_PAGE ||
13360 aLoadType & LOAD_CMD_HISTORY);
13361}
13362
13363void nsDocShell::UpdateGlobalHistoryTitle(nsIURI* aURI) {
13364 if (!mBrowsingContext->GetUseGlobalHistory() || UsePrivateBrowsing()) {
13365 return;
13366 }
13367
13368 // Global history is interested into sub-frame visits only for link-coloring
13369 // purposes, thus title updates are skipped for those.
13370 //
13371 // Moreover, some iframe documents (such as the ones created via
13372 // document.open()) inherit the document uri of the caller, which would cause
13373 // us to override a previously set page title with one from the subframe.
13374 if (IsSubframe()) {
13375 return;
13376 }
13377
13378 if (nsCOMPtr<IHistory> history = components::History::Service()) {
13379 history->SetURITitle(aURI, mTitle);
13380 }
13381}
13382
13383bool nsDocShell::IsInvisible() { return mInvisible; }
13384
13385void nsDocShell::SetInvisible(bool aInvisible) { mInvisible = aInvisible; }
13386
13387/* static */
13388void nsDocShell::MaybeNotifyKeywordSearchLoading(const nsString& aProvider,
13389 const nsString& aKeyword) {
13390 if (aProvider.IsEmpty()) {
13391 return;
13392 }
13393 nsresult rv;
13394 nsCOMPtr<nsISupportsString> isupportsString =
13395 do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID"@mozilla.org/supports-string;1", &rv);
13396 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"
, 13396); return; } } while (false)
;
13397
13398 rv = isupportsString->SetData(aProvider);
13399 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"
, 13399); return; } } while (false)
;
13400
13401 nsCOMPtr<nsIObserverService> obsSvc = services::GetObserverService();
13402 if (obsSvc) {
13403 // Note that "keyword-search" refers to a search via the url
13404 // bar, not a bookmarks keyword search.
13405 obsSvc->NotifyObservers(isupportsString, "keyword-search", aKeyword.get());
13406 }
13407}
13408
13409NS_IMETHODIMPnsresult
13410nsDocShell::ShouldPrepareForIntercept(nsIURI* aURI, nsIChannel* aChannel,
13411 bool* aShouldIntercept) {
13412 return mInterceptController->ShouldPrepareForIntercept(aURI, aChannel,
13413 aShouldIntercept);
13414}
13415
13416NS_IMETHODIMPnsresult
13417nsDocShell::ChannelIntercepted(nsIInterceptedChannel* aChannel) {
13418 return mInterceptController->ChannelIntercepted(aChannel);
13419}
13420
13421bool nsDocShell::InFrameSwap() {
13422 RefPtr<nsDocShell> shell = this;
13423 do {
13424 if (shell->mInFrameSwap) {
13425 return true;
13426 }
13427 shell = shell->GetInProcessParentDocshell();
13428 } while (shell);
13429 return false;
13430}
13431
13432UniquePtr<ClientSource> nsDocShell::TakeInitialClientSource() {
13433 return std::move(mInitialClientSource);
13434}
13435
13436NS_IMETHODIMPnsresult
13437nsDocShell::GetEditingSession(nsIEditingSession** aEditSession) {
13438 if (!NS_SUCCEEDED(EnsureEditorData())((bool)(__builtin_expect(!!(!NS_FAILED_impl(EnsureEditorData(
))), 1)))
) {
13439 return NS_ERROR_FAILURE;
13440 }
13441
13442 *aEditSession = do_AddRef(mEditorData->GetEditingSession()).take();
13443 return *aEditSession ? NS_OK : NS_ERROR_FAILURE;
13444}
13445
13446NS_IMETHODIMPnsresult
13447nsDocShell::GetScriptableBrowserChild(nsIBrowserChild** aBrowserChild) {
13448 *aBrowserChild = GetBrowserChild().take();
13449 return *aBrowserChild ? NS_OK : NS_ERROR_FAILURE;
13450}
13451
13452already_AddRefed<nsIBrowserChild> nsDocShell::GetBrowserChild() {
13453 nsCOMPtr<nsIBrowserChild> tc = do_QueryReferent(mBrowserChild);
13454 return tc.forget();
13455}
13456
13457nsCommandManager* nsDocShell::GetCommandManager() {
13458 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"
, 13458); return nullptr; } } while (false)
;
13459 return mCommandManager;
13460}
13461
13462NS_IMETHODIMP_(void)void
13463nsDocShell::GetOriginAttributes(mozilla::OriginAttributes& aAttrs) {
13464 mBrowsingContext->GetOriginAttributes(aAttrs);
13465}
13466
13467HTMLEditor* nsIDocShell::GetHTMLEditor() {
13468 nsDocShell* docShell = static_cast<nsDocShell*>(this);
13469 return docShell->GetHTMLEditorInternal();
13470}
13471
13472nsresult nsIDocShell::SetHTMLEditor(HTMLEditor* aHTMLEditor) {
13473 nsDocShell* docShell = static_cast<nsDocShell*>(this);
13474 return docShell->SetHTMLEditorInternal(aHTMLEditor);
13475}
13476
13477#define MATRIX_LENGTH 20
13478
13479NS_IMETHODIMPnsresult
13480nsDocShell::SetColorMatrix(const nsTArray<float>& aMatrix) {
13481 if (aMatrix.Length() == MATRIX_LENGTH) {
13482 mColorMatrix.reset(new gfx::Matrix5x4());
13483 static_assert(
13484 MATRIX_LENGTH * sizeof(float) == sizeof(mColorMatrix->components),
13485 "Size mismatch for our memcpy");
13486 memcpy(mColorMatrix->components, aMatrix.Elements(),
13487 sizeof(mColorMatrix->components));
13488 } else if (aMatrix.Length() == 0) {
13489 mColorMatrix.reset();
13490 } else {
13491 return NS_ERROR_INVALID_ARG;
13492 }
13493
13494 PresShell* presShell = GetPresShell();
13495 if (!presShell) {
13496 return NS_ERROR_FAILURE;
13497 }
13498
13499 nsIFrame* frame = presShell->GetRootFrame();
13500 if (!frame) {
13501 return NS_ERROR_FAILURE;
13502 }
13503
13504 frame->SchedulePaint();
13505
13506 return NS_OK;
13507}
13508
13509NS_IMETHODIMPnsresult
13510nsDocShell::GetColorMatrix(nsTArray<float>& aMatrix) {
13511 if (mColorMatrix) {
13512 aMatrix.SetLength(MATRIX_LENGTH);
13513 static_assert(
13514 MATRIX_LENGTH * sizeof(float) == sizeof(mColorMatrix->components),
13515 "Size mismatch for our memcpy");
13516 memcpy(aMatrix.Elements(), mColorMatrix->components,
13517 MATRIX_LENGTH * sizeof(float));
13518 }
13519
13520 return NS_OK;
13521}
13522
13523#undef MATRIX_LENGTH
13524
13525NS_IMETHODIMPnsresult
13526nsDocShell::GetIsForceReloading(bool* aForceReload) {
13527 *aForceReload = IsForceReloading();
13528 return NS_OK;
13529}
13530
13531bool nsDocShell::IsForceReloading() { return IsForceReloadType(mLoadType); }
13532
13533NS_IMETHODIMPnsresult
13534nsDocShell::GetBrowsingContextXPCOM(BrowsingContext** aBrowsingContext) {
13535 *aBrowsingContext = do_AddRef(mBrowsingContext).take();
13536 return NS_OK;
13537}
13538
13539BrowsingContext* nsDocShell::GetBrowsingContext() { return mBrowsingContext; }
13540
13541bool nsDocShell::GetIsAttemptingToNavigate() {
13542 // XXXbz the document.open spec says to abort even if there's just a
13543 // queued navigation task, sort of. It's not clear whether browsers
13544 // actually do that, and we didn't use to do it, so for now let's
13545 // not do that.
13546 // https://github.com/whatwg/html/issues/3447 tracks the spec side of this.
13547 if (mDocumentRequest) {
13548 // There's definitely a navigation in progress.
13549 return true;
13550 }
13551
13552 // javascript: channels have slightly weird behavior: they're LOAD_BACKGROUND
13553 // until the script runs, which means they're not sending loadgroup
13554 // notifications and hence not getting set as mDocumentRequest. Look through
13555 // our loadgroup for document-level javascript: loads.
13556 if (!mLoadGroup) {
13557 return false;
13558 }
13559
13560 nsCOMPtr<nsISimpleEnumerator> requests;
13561 mLoadGroup->GetRequests(getter_AddRefs(requests));
13562 bool hasMore = false;
13563 while (NS_SUCCEEDED(requests->HasMoreElements(&hasMore))((bool)(__builtin_expect(!!(!NS_FAILED_impl(requests->HasMoreElements
(&hasMore))), 1)))
&& hasMore) {
13564 nsCOMPtr<nsISupports> elem;
13565 requests->GetNext(getter_AddRefs(elem));
13566 nsCOMPtr<nsIScriptChannel> scriptChannel(do_QueryInterface(elem));
13567 if (!scriptChannel) {
13568 continue;
13569 }
13570
13571 if (scriptChannel->GetIsDocumentLoad()) {
13572 // This is a javascript: load that might lead to a new document,
13573 // hence a navigation.
13574 return true;
13575 }
13576 }
13577
13578 return mCheckingSessionHistory;
13579}
13580
13581void nsDocShell::SetLoadingSessionHistoryInfo(
13582 const mozilla::dom::LoadingSessionHistoryInfo& aLoadingInfo,
13583 bool aNeedToReportActiveAfterLoadingBecomesActive) {
13584 // FIXME Would like to assert this, but can't yet.
13585 // MOZ_ASSERT(!mLoadingEntry);
13586 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)
13587 ("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)
13588 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)
;
13589 mLoadingEntry = MakeUnique<LoadingSessionHistoryInfo>(aLoadingInfo);
13590 mNeedToReportActiveAfterLoadingBecomesActive =
13591 aNeedToReportActiveAfterLoadingBecomesActive;
13592}
13593
13594void nsDocShell::MoveLoadingToActiveEntry(bool aPersist, bool aExpired,
13595 uint32_t aCacheKey,
13596 nsIURI* aPreviousURI) {
13597 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"
, 13597); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mozilla::SessionHistoryInParent()"
")"); do { *((volatile int*)__null) = 13597; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
13598
13599 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)
13600 ("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)
;
13601
13602 UniquePtr<SessionHistoryInfo> previousActiveEntry(mActiveEntry.release());
13603 mozilla::UniquePtr<mozilla::dom::LoadingSessionHistoryInfo> loadingEntry;
13604 mActiveEntryIsLoadingFromSessionHistory =
13605 mLoadingEntry && mLoadingEntry->mLoadIsFromSessionHistory;
13606 if (mLoadingEntry) {
13607 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)
13608 ("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)
13609 "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)
13610 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)
;
13611 mActiveEntry = MakeUnique<SessionHistoryInfo>(mLoadingEntry->mInfo);
13612 mLoadingEntry.swap(loadingEntry);
13613 if (!mActiveEntryIsLoadingFromSessionHistory) {
13614 if (mNeedToReportActiveAfterLoadingBecomesActive) {
13615 // Needed to pass various history length WPTs.
13616 mBrowsingContext->SetActiveSessionHistoryEntry(
13617 mozilla::Nothing(), mActiveEntry.get(), mLoadType,
13618 /* aUpdatedCacheKey = */ 0, false);
13619 }
13620 mBrowsingContext->IncrementHistoryEntryCountForBrowsingContext();
13621 }
13622 }
13623 mNeedToReportActiveAfterLoadingBecomesActive = false;
13624
13625 if (mActiveEntry) {
13626 if (aCacheKey != 0) {
13627 mActiveEntry->SetCacheKey(aCacheKey);
13628 }
13629 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"
, 13629); AnnotateMozCrashReason("MOZ_ASSERT" "(" "loadingEntry"
")"); do { *((volatile int*)__null) = 13629; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
13630 uint32_t loadType =
13631 mLoadType == LOAD_ERROR_PAGE ? mFailedLoadType : mLoadType;
13632
13633 if (loadingEntry->mLoadId != UINT64_MAX(18446744073709551615UL)) {
13634 // We're passing in mCurrentURI, which could be null. SessionHistoryCommit
13635 // does require a non-null uri if this is for a refresh load of the same
13636 // URI, but in that case mCurrentURI won't be null here.
13637 mBrowsingContext->SessionHistoryCommit(
13638 *loadingEntry, loadType, aPreviousURI, previousActiveEntry.get(),
13639 aPersist, false, aExpired, aCacheKey);
13640 }
13641 }
13642}
13643
13644static bool IsFaviconLoad(nsIRequest* aRequest) {
13645 nsCOMPtr<nsIChannel> channel = do_QueryInterface(aRequest);
13646 if (!channel) {
13647 return false;
13648 }
13649
13650 nsCOMPtr<nsILoadInfo> li = channel->LoadInfo();
13651 return li && li->InternalContentPolicyType() ==
13652 nsIContentPolicy::TYPE_INTERNAL_IMAGE_FAVICON;
13653}
13654
13655void nsDocShell::RecordSingleChannelId(bool aStartRequest,
13656 nsIRequest* aRequest) {
13657 // Ignore favicon loads, they don't need to block caching.
13658 if (IsFaviconLoad(aRequest)) {
13659 return;
13660 }
13661
13662 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"
, 13662); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mRequestForBlockingFromBFCacheCount > 0"
")"); do { *((volatile int*)__null) = 13662; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false); } } while
(false)
;
13663
13664 mRequestForBlockingFromBFCacheCount += aStartRequest ? 1 : -1;
13665
13666 if (mBrowsingContext->GetCurrentWindowContext()) {
13667 // We have three states: no request, one request with an id and
13668 // eiher one request without an id or multiple requests. Nothing() is no
13669 // request, Some(non-zero) is one request with an id and Some(0) is one
13670 // request without an id or multiple requests.
13671 Maybe<uint64_t> singleChannelId;
13672 if (mRequestForBlockingFromBFCacheCount > 1) {
13673 singleChannelId = Some(0);
13674 } else if (mRequestForBlockingFromBFCacheCount == 1) {
13675 nsCOMPtr<nsIIdentChannel> identChannel;
13676 if (aStartRequest) {
13677 identChannel = do_QueryInterface(aRequest);
13678 } else {
13679 // aChannel is the channel that's being removed, but we need to check if
13680 // the remaining channel in the loadgroup has an id.
13681 nsCOMPtr<nsISimpleEnumerator> requests;
13682 mLoadGroup->GetRequests(getter_AddRefs(requests));
13683 for (const auto& request : SimpleEnumerator<nsIRequest>(requests)) {
13684 if (!IsFaviconLoad(request) &&
13685 !!(identChannel = do_QueryInterface(request))) {
13686 break;
13687 }
13688 }
13689 }
13690
13691 if (identChannel) {
13692 singleChannelId = Some(identChannel->ChannelId());
13693 } else {
13694 singleChannelId = Some(0);
13695 }
13696 } else {
13697 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"
, 13697); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mRequestForBlockingFromBFCacheCount == 0"
")"); do { *((volatile int*)__null) = 13697; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
13698 singleChannelId = Nothing();
13699 }
13700
13701 if (MOZ_UNLIKELY(MOZ_LOG_TEST(gSHIPBFCacheLog, LogLevel::Verbose))(__builtin_expect(!!((__builtin_expect(!!(mozilla::detail::log_test
(gSHIPBFCacheLog, LogLevel::Verbose)), 0))), 0))
) {
13702 nsAutoCString uri("[no uri]");
13703 if (mCurrentURI) {
13704 uri = mCurrentURI->GetSpecOrDefault();
13705 }
13706 if (singleChannelId.isNothing()) {
13707 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)
13708 ("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)
13709 "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)
13710 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)
;
13711 } else if (singleChannelId.value() == 0) {
13712 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)
13713 ("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)
13714 "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)
13715 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)
;
13716 } else {
13717 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)
13718 ("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)
13719 " 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)
13720 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)
;
13721 }
13722 }
13723
13724 if (mSingleChannelId != singleChannelId) {
13725 mSingleChannelId = singleChannelId;
13726 WindowGlobalChild* wgc =
13727 mBrowsingContext->GetCurrentWindowContext()->GetWindowGlobalChild();
13728 if (wgc) {
13729 wgc->SendSetSingleChannelId(singleChannelId);
13730 }
13731 }
13732 }
13733}
13734
13735NS_IMETHODIMPnsresult
13736nsDocShell::OnStartRequest(nsIRequest* aRequest) {
13737 if (MOZ_UNLIKELY(MOZ_LOG_TEST(gSHIPBFCacheLog, LogLevel::Verbose))(__builtin_expect(!!((__builtin_expect(!!(mozilla::detail::log_test
(gSHIPBFCacheLog, LogLevel::Verbose)), 0))), 0))
) {
13738 nsAutoCString uri("[no uri]");
13739 if (mCurrentURI) {
13740 uri = mCurrentURI->GetSpecOrDefault();
13741 }
13742 nsAutoCString name;
13743 aRequest->GetName(name);
13744 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)
13745 ("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)
;
13746 }
13747 RecordSingleChannelId(true, aRequest);
13748 return nsDocLoader::OnStartRequest(aRequest);
13749}
13750
13751NS_IMETHODIMPnsresult
13752nsDocShell::OnStopRequest(nsIRequest* aRequest, nsresult aStatusCode) {
13753 if (MOZ_UNLIKELY(MOZ_LOG_TEST(gSHIPBFCacheLog, LogLevel::Verbose))(__builtin_expect(!!((__builtin_expect(!!(mozilla::detail::log_test
(gSHIPBFCacheLog, LogLevel::Verbose)), 0))), 0))
) {
13754 nsAutoCString uri("[no uri]");
13755 if (mCurrentURI) {
13756 uri = mCurrentURI->GetSpecOrDefault();
13757 }
13758 nsAutoCString name;
13759 aRequest->GetName(name);
13760 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)
13761 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)
13762 ("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)
;
13763 }
13764 RecordSingleChannelId(false, aRequest);
13765 return nsDocLoader::OnStopRequest(aRequest, aStatusCode);
13766}
13767
13768void nsDocShell::MaybeDisconnectChildListenersOnPageHide() {
13769 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"
, 13769); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "XRE_IsContentProcess()"
")"); do { *((volatile int*)__null) = 13769; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
13770
13771 if (mChannelToDisconnectOnPageHide != 0 && mLoadGroup) {
13772 nsCOMPtr<nsISimpleEnumerator> requests;
13773 mLoadGroup->GetRequests(getter_AddRefs(requests));
13774 for (const auto& request : SimpleEnumerator<nsIRequest>(requests)) {
13775 RefPtr<DocumentChannel> channel = do_QueryObject(request);
13776 if (channel && channel->ChannelId() == mChannelToDisconnectOnPageHide) {
13777 static_cast<DocumentChannelChild*>(channel.get())
13778 ->DisconnectChildListeners(NS_BINDING_ABORTED, NS_BINDING_ABORTED);
13779 }
13780 }
13781 mChannelToDisconnectOnPageHide = 0;
13782 }
13783}