Bug Summary

File:var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp
Warning:line 3426, 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-18/lib/clang/18 -include /var/lib/jenkins/workspace/firefox-scan-build/config/gcc_hidden.h -include /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/mozilla-config.h -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dist/stl_wrappers -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dist/system_wrappers -U _FORTIFY_SOURCE -D _FORTIFY_SOURCE=2 -D DEBUG=1 -D MOZ_HAS_MOZGLUE -D MOZILLA_INTERNAL_API -D IMPL_LIBXUL -D MOZ_SUPPORT_LEAKCHECKING -D STATIC_EXPORTABLE_JS_API -I /var/lib/jenkins/workspace/firefox-scan-build/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-18/lib/clang/18/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-error=tautological-type-limit-compare -Wno-invalid-offsetof -Wno-range-loop-analysis -Wno-deprecated-anon-enum-enum-conversion -Wno-deprecated-enum-enum-conversion -Wno-deprecated-this-capture -Wno-inline-new-delete -Wno-error=deprecated-declarations -Wno-error=array-bounds -Wno-error=free-nonheap-object -Wno-error=atomic-alignment -Wno-error=deprecated-builtins -Wno-psabi -Wno-error=builtin-macro-redefined -Wno-vla-cxx-extension -Wno-unknown-warning-option -fdeprecated-macro -ferror-limit 19 -stack-protector 2 -fstack-clash-protection -ftrivial-auto-var-init=pattern -fno-rtti -fgnuc-version=4.2.1 -fno-aligned-allocation -vectorize-loops -vectorize-slp -analyzer-checker optin.performance.Padding -analyzer-output=html -analyzer-config stable-report-filename=true -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/scan-build-2024-07-21-021012-413605-1 -x c++ Unified_cpp_docshell_base0.cpp
1/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2/* vim: set ts=8 sts=2 et sw=2 tw=80: */
3/* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7#include "nsDocShell.h"
8
9#include <algorithm>
10
11#ifdef XP_WIN
12# include <process.h>
13# define getpid _getpid
14#else
15# include <unistd.h> // for getpid()
16#endif
17
18#include "mozilla/ArrayUtils.h"
19#include "mozilla/Attributes.h"
20#include "mozilla/AutoRestore.h"
21#include "mozilla/BasePrincipal.h"
22#include "mozilla/Casting.h"
23#include "mozilla/CheckedInt.h"
24#include "mozilla/Components.h"
25#include "mozilla/DebugOnly.h"
26#include "mozilla/Encoding.h"
27#include "mozilla/EventStateManager.h"
28#include "mozilla/HTMLEditor.h"
29#include "mozilla/InputTaskManager.h"
30#include "mozilla/LoadInfo.h"
31#include "mozilla/Logging.h"
32#include "mozilla/MediaFeatureChange.h"
33#include "mozilla/Preferences.h"
34#include "mozilla/PresShell.h"
35#include "mozilla/ResultExtensions.h"
36#include "mozilla/SchedulerGroup.h"
37#include "mozilla/ScopeExit.h"
38#include "mozilla/ScrollContainerFrame.h"
39#include "mozilla/ScrollTypes.h"
40#include "mozilla/SimpleEnumerator.h"
41#include "mozilla/StaticPrefs_browser.h"
42#include "mozilla/StaticPrefs_docshell.h"
43#include "mozilla/StaticPrefs_dom.h"
44#include "mozilla/StaticPrefs_extensions.h"
45#include "mozilla/StaticPrefs_privacy.h"
46#include "mozilla/StaticPrefs_security.h"
47#include "mozilla/StaticPrefs_ui.h"
48#include "mozilla/StaticPrefs_fission.h"
49#include "mozilla/StartupTimeline.h"
50#include "mozilla/StorageAccess.h"
51#include "mozilla/StoragePrincipalHelper.h"
52#include "mozilla/Telemetry.h"
53
54#include "mozilla/Unused.h"
55#include "mozilla/WidgetUtils.h"
56
57#include "mozilla/dom/AutoEntryScript.h"
58#include "mozilla/dom/ChildProcessChannelListener.h"
59#include "mozilla/dom/ClientChannelHelper.h"
60#include "mozilla/dom/ClientHandle.h"
61#include "mozilla/dom/ClientInfo.h"
62#include "mozilla/dom/ClientManager.h"
63#include "mozilla/dom/ClientSource.h"
64#include "mozilla/dom/ContentChild.h"
65#include "mozilla/dom/ContentFrameMessageManager.h"
66#include "mozilla/dom/DocGroup.h"
67#include "mozilla/dom/Element.h"
68#include "mozilla/dom/FragmentDirective.h"
69#include "mozilla/dom/HTMLAnchorElement.h"
70#include "mozilla/dom/HTMLIFrameElement.h"
71#include "mozilla/dom/PerformanceNavigation.h"
72#include "mozilla/dom/PermissionMessageUtils.h"
73#include "mozilla/dom/PopupBlocker.h"
74#include "mozilla/dom/ScreenOrientation.h"
75#include "mozilla/dom/ScriptSettings.h"
76#include "mozilla/dom/ServiceWorkerInterceptController.h"
77#include "mozilla/dom/ServiceWorkerUtils.h"
78#include "mozilla/dom/SessionHistoryEntry.h"
79#include "mozilla/dom/SessionStorageManager.h"
80#include "mozilla/dom/SessionStoreChangeListener.h"
81#include "mozilla/dom/SessionStoreChild.h"
82#include "mozilla/dom/SessionStoreUtils.h"
83#include "mozilla/dom/BrowserChild.h"
84#include "mozilla/dom/ToJSValue.h"
85#include "mozilla/dom/UserActivation.h"
86#include "mozilla/dom/ChildSHistory.h"
87#include "mozilla/dom/nsCSPContext.h"
88#include "mozilla/dom/nsHTTPSOnlyUtils.h"
89#include "mozilla/dom/LoadURIOptionsBinding.h"
90#include "mozilla/dom/JSWindowActorChild.h"
91#include "mozilla/dom/DocumentBinding.h"
92#include "mozilla/ipc/ProtocolUtils.h"
93#include "mozilla/net/DocumentChannel.h"
94#include "mozilla/net/DocumentChannelChild.h"
95#include "mozilla/net/ParentChannelWrapper.h"
96#include "mozilla/net/UrlClassifierFeatureFactory.h"
97#include "ReferrerInfo.h"
98
99#include "nsIAuthPrompt.h"
100#include "nsIAuthPrompt2.h"
101#include "nsICachingChannel.h"
102#include "nsICaptivePortalService.h"
103#include "nsIChannel.h"
104#include "nsIChannelEventSink.h"
105#include "nsIClassOfService.h"
106#include "nsIConsoleReportCollector.h"
107#include "nsIContent.h"
108#include "nsIContentInlines.h"
109#include "nsIContentSecurityPolicy.h"
110#include "nsIController.h"
111#include "nsIDocShellTreeItem.h"
112#include "nsIDocShellTreeOwner.h"
113#include "nsIDocumentViewer.h"
114#include "mozilla/dom/Document.h"
115#include "nsHTMLDocument.h"
116#include "nsIDocumentLoaderFactory.h"
117#include "nsIDOMWindow.h"
118#include "nsIEditingSession.h"
119#include "nsIEffectiveTLDService.h"
120#include "nsIExternalProtocolService.h"
121#include "nsIFormPOSTActionChannel.h"
122#include "nsIFrame.h"
123#include "nsIGlobalObject.h"
124#include "nsIHttpChannel.h"
125#include "nsIHttpChannelInternal.h"
126#include "nsIIDNService.h"
127#include "nsIInputStreamChannel.h"
128#include "nsIInterfaceRequestorUtils.h"
129#include "nsILayoutHistoryState.h"
130#include "nsILoadInfo.h"
131#include "nsILoadURIDelegate.h"
132#include "nsIMultiPartChannel.h"
133#include "nsINestedURI.h"
134#include "nsINetworkPredictor.h"
135#include "nsINode.h"
136#include "nsINSSErrorsService.h"
137#include "nsIObserverService.h"
138#include "nsIOService.h"
139#include "nsIPrincipal.h"
140#include "nsIPrivacyTransitionObserver.h"
141#include "nsIPrompt.h"
142#include "nsIPromptCollection.h"
143#include "nsIPromptFactory.h"
144#include "nsIPublicKeyPinningService.h"
145#include "nsIReflowObserver.h"
146#include "nsIScriptChannel.h"
147#include "nsIScriptObjectPrincipal.h"
148#include "nsIScriptSecurityManager.h"
149#include "nsScriptSecurityManager.h"
150#include "nsIScrollObserver.h"
151#include "nsISupportsPrimitives.h"
152#include "nsISecureBrowserUI.h"
153#include "nsISeekableStream.h"
154#include "nsISelectionDisplay.h"
155#include "nsISHEntry.h"
156#include "nsISiteSecurityService.h"
157#include "nsISocketProvider.h"
158#include "nsIStringBundle.h"
159#include "nsIStructuredCloneContainer.h"
160#include "nsIBrowserChild.h"
161#include "nsITextToSubURI.h"
162#include "nsITimedChannel.h"
163#include "nsITimer.h"
164#include "nsITransportSecurityInfo.h"
165#include "nsIUploadChannel.h"
166#include "nsIURIFixup.h"
167#include "nsIURIMutator.h"
168#include "nsIURILoader.h"
169#include "nsIViewSourceChannel.h"
170#include "nsIWebBrowserChrome.h"
171#include "nsIWebBrowserFind.h"
172#include "nsIWebProgress.h"
173#include "nsIWidget.h"
174#include "nsIWindowWatcher.h"
175#include "nsIWritablePropertyBag2.h"
176#include "nsIX509Cert.h"
177#include "nsIXULRuntime.h"
178
179#include "nsCommandManager.h"
180#include "nsPIDOMWindow.h"
181#include "nsPIWindowRoot.h"
182
183#include "IHistory.h"
184#include "IUrlClassifierUITelemetry.h"
185
186#include "nsArray.h"
187#include "nsArrayUtils.h"
188#include "nsCExternalHandlerService.h"
189#include "nsContentDLF.h"
190#include "nsContentPolicyUtils.h" // NS_CheckContentLoadPolicy(...)
191#include "nsContentSecurityManager.h"
192#include "nsContentSecurityUtils.h"
193#include "nsContentUtils.h"
194#include "nsCURILoader.h"
195#include "nsDocShellCID.h"
196#include "nsDocShellEditorData.h"
197#include "nsDocShellEnumerator.h"
198#include "nsDocShellLoadState.h"
199#include "nsDocShellLoadTypes.h"
200#include "nsDOMCID.h"
201#include "nsDOMNavigationTiming.h"
202#include "nsDSURIContentListener.h"
203#include "nsEditingSession.h"
204#include "nsError.h"
205#include "nsEscape.h"
206#include "nsFocusManager.h"
207#include "nsGlobalWindowInner.h"
208#include "nsGlobalWindowOuter.h"
209#include "nsJSEnvironment.h"
210#include "nsNetCID.h"
211#include "nsNetUtil.h"
212#include "nsObjectLoadingContent.h"
213#include "nsPingListener.h"
214#include "nsPoint.h"
215#include "nsQueryObject.h"
216#include "nsQueryActor.h"
217#include "nsRect.h"
218#include "nsRefreshTimer.h"
219#include "nsSandboxFlags.h"
220#include "nsSHEntry.h"
221#include "nsSHistory.h"
222#include "nsSHEntry.h"
223#include "nsStructuredCloneContainer.h"
224#include "nsSubDocumentFrame.h"
225#include "nsURILoader.h"
226#include "nsURLHelper.h"
227#include "nsView.h"
228#include "nsViewManager.h"
229#include "nsViewSourceHandler.h"
230#include "nsWebBrowserFind.h"
231#include "nsWhitespaceTokenizer.h"
232#include "nsWidgetsCID.h"
233#include "nsXULAppAPI.h"
234
235#include "CertVerifier.h"
236#include "ThirdPartyUtil.h"
237#include "GeckoProfiler.h"
238#include "mozilla/NullPrincipal.h"
239#include "Navigator.h"
240#include "prenv.h"
241#include "mozilla/ipc/URIUtils.h"
242#include "sslerr.h"
243#include "mozpkix/pkix.h"
244#include "NSSErrorsService.h"
245
246#include "nsDocShellTelemetryUtils.h"
247
248#ifdef MOZ_PLACES1
249# include "nsIFaviconService.h"
250# include "mozIPlacesPendingOperation.h"
251#endif
252
253#if NS_PRINT_PREVIEW1
254# include "nsIDocumentViewerPrint.h"
255# include "nsIWebBrowserPrint.h"
256#endif
257
258using namespace mozilla;
259using namespace mozilla::dom;
260using namespace mozilla::net;
261
262using mozilla::ipc::Endpoint;
263
264// Threshold value in ms for META refresh based redirects
265#define REFRESH_REDIRECT_TIMER15000 15000
266
267static mozilla::LazyLogModule gCharsetMenuLog("CharsetMenu");
268
269#define LOGCHARSETMENU(args)do { const ::mozilla::LogModule* moz_real_module = gCharsetMenuLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, MOZ_LOG_EXPAND_ARGS
args); } } while (0)
\
270 MOZ_LOG(gCharsetMenuLog, mozilla::LogLevel::Debug, args)do { const ::mozilla::LogModule* moz_real_module = gCharsetMenuLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, MOZ_LOG_EXPAND_ARGS
args); } } while (0)
271
272#ifdef DEBUG1
273unsigned long nsDocShell::gNumberOfDocShells = 0;
274static uint64_t gDocshellIDCounter = 0;
275
276static mozilla::LazyLogModule gDocShellLog("nsDocShell");
277static mozilla::LazyLogModule gDocShellAndDOMWindowLeakLogging(
278 "DocShellAndDOMWindowLeak");
279#endif
280static mozilla::LazyLogModule gDocShellLeakLog("nsDocShellLeak");
281extern mozilla::LazyLogModule gPageCacheLog;
282mozilla::LazyLogModule gSHLog("SessionHistory");
283extern mozilla::LazyLogModule gSHIPBFCacheLog;
284
285const char kAppstringsBundleURL[] =
286 "chrome://global/locale/appstrings.properties";
287
288static bool IsTopLevelDoc(BrowsingContext* aBrowsingContext,
289 nsILoadInfo* aLoadInfo) {
290 MOZ_ASSERT(aBrowsingContext)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aBrowsingContext)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aBrowsingContext))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("aBrowsingContext"
, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 290); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aBrowsingContext"
")"); do { *((volatile int*)__null) = 290; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
291 MOZ_ASSERT(aLoadInfo)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aLoadInfo)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aLoadInfo))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aLoadInfo", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 291); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadInfo" ")"
); do { *((volatile int*)__null) = 291; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
292
293 if (aLoadInfo->GetExternalContentPolicyType() !=
294 ExtContentPolicy::TYPE_DOCUMENT) {
295 return false;
296 }
297
298 return aBrowsingContext->IsTopContent();
299}
300
301// True if loading for top level document loading in active tab.
302static bool IsUrgentStart(BrowsingContext* aBrowsingContext,
303 nsILoadInfo* aLoadInfo, uint32_t aLoadType) {
304 MOZ_ASSERT(aBrowsingContext)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aBrowsingContext)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aBrowsingContext))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("aBrowsingContext"
, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 304); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aBrowsingContext"
")"); do { *((volatile int*)__null) = 304; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
305 MOZ_ASSERT(aLoadInfo)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aLoadInfo)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aLoadInfo))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aLoadInfo", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 305); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadInfo" ")"
); do { *((volatile int*)__null) = 305; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
306
307 if (!IsTopLevelDoc(aBrowsingContext, aLoadInfo)) {
308 return false;
309 }
310
311 if (aLoadType &
312 (nsIDocShell::LOAD_CMD_NORMAL | nsIDocShell::LOAD_CMD_HISTORY)) {
313 return true;
314 }
315
316 return aBrowsingContext->IsActive();
317}
318
319nsDocShell::nsDocShell(BrowsingContext* aBrowsingContext,
320 uint64_t aContentWindowID)
321 : nsDocLoader(true),
322 mContentWindowID(aContentWindowID),
323 mBrowsingContext(aBrowsingContext),
324 mParentCharset(nullptr),
325 mTreeOwner(nullptr),
326 mScrollbarPref(ScrollbarPreference::Auto),
327 mCharsetReloadState(eCharsetReloadInit),
328 mParentCharsetSource(0),
329 mFrameMargins(-1, -1),
330 mItemType(aBrowsingContext->IsContent() ? typeContent : typeChrome),
331 mPreviousEntryIndex(-1),
332 mLoadedEntryIndex(-1),
333 mBusyFlags(BUSY_FLAGS_NONE),
334 mAppType(nsIDocShell::APP_TYPE_UNKNOWN),
335 mLoadType(0),
336 mFailedLoadType(0),
337 mChannelToDisconnectOnPageHide(0),
338 mCreatingDocument(false),
339#ifdef DEBUG1
340 mInEnsureScriptEnv(false),
341#endif
342 mInitialized(false),
343 mAllowSubframes(true),
344 mAllowMetaRedirects(true),
345 mAllowImages(true),
346 mAllowMedia(true),
347 mAllowDNSPrefetch(true),
348 mAllowWindowControl(true),
349 mCSSErrorReportingEnabled(false),
350 mAllowAuth(mItemType == typeContent),
351 mAllowKeywordFixup(false),
352 mDisableMetaRefreshWhenInactive(false),
353 mWindowDraggingAllowed(false),
354 mInFrameSwap(false),
355 mFiredUnloadEvent(false),
356 mEODForCurrentDocument(false),
357 mURIResultedInDocument(false),
358 mIsBeingDestroyed(false),
359 mIsExecutingOnLoadHandler(false),
360 mSavingOldViewer(false),
361 mInvisible(false),
362 mHasLoadedNonBlankURI(false),
363 mBlankTiming(false),
364 mTitleValidForCurrentURI(false),
365 mWillChangeProcess(false),
366 mIsNavigating(false),
367 mForcedAutodetection(false),
368 mCheckingSessionHistory(false),
369 mNeedToReportActiveAfterLoadingBecomesActive(false) {
370 // If no outer window ID was provided, generate a new one.
371 if (aContentWindowID == 0) {
372 mContentWindowID = nsContentUtils::GenerateWindowId();
373 }
374
375 MOZ_LOG(gDocShellLeakLog, LogLevel::Debug, ("DOCSHELL %p created\n", this))do { const ::mozilla::LogModule* moz_real_module = gDocShellLeakLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "DOCSHELL %p created\n", this); } } while (
0)
;
376
377#ifdef DEBUG1
378 mDocShellID = gDocshellIDCounter++;
379 // We're counting the number of |nsDocShells| to help find leaks
380 ++gNumberOfDocShells;
381 MOZ_LOG(gDocShellAndDOMWindowLeakLogging, LogLevel::Info,do { const ::mozilla::LogModule* moz_real_module = gDocShellAndDOMWindowLeakLogging
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Info, "++DOCSHELL %p == %ld [pid = %d] [id = %" "l"
"u" "]\n", (void*)this, gNumberOfDocShells, getpid(), mDocShellID
); } } while (0)
382 ("++DOCSHELL %p == %ld [pid = %d] [id = %" PRIu64 "]\n", (void*)this,do { const ::mozilla::LogModule* moz_real_module = gDocShellAndDOMWindowLeakLogging
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Info, "++DOCSHELL %p == %ld [pid = %d] [id = %" "l"
"u" "]\n", (void*)this, gNumberOfDocShells, getpid(), mDocShellID
); } } while (0)
383 gNumberOfDocShells, getpid(), mDocShellID))do { const ::mozilla::LogModule* moz_real_module = gDocShellAndDOMWindowLeakLogging
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Info, "++DOCSHELL %p == %ld [pid = %d] [id = %" "l"
"u" "]\n", (void*)this, gNumberOfDocShells, getpid(), mDocShellID
); } } while (0)
;
384#endif
385}
386
387nsDocShell::~nsDocShell() {
388 // Avoid notifying observers while we're in the dtor.
389 mIsBeingDestroyed = true;
390
391 Destroy();
392
393 if (mDocumentViewer) {
394 mDocumentViewer->Close(nullptr);
395 mDocumentViewer->Destroy();
396 mDocumentViewer = nullptr;
397 }
398
399 MOZ_LOG(gDocShellLeakLog, LogLevel::Debug, ("DOCSHELL %p destroyed\n", this))do { const ::mozilla::LogModule* moz_real_module = gDocShellLeakLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "DOCSHELL %p destroyed\n", this); } } while
(0)
;
400
401#ifdef DEBUG1
402 if (MOZ_LOG_TEST(gDocShellAndDOMWindowLeakLogging, LogLevel::Info)(__builtin_expect(!!(mozilla::detail::log_test(gDocShellAndDOMWindowLeakLogging
, LogLevel::Info)), 0))
) {
403 nsAutoCString url;
404 if (mLastOpenedURI) {
405 url = mLastOpenedURI->GetSpecOrDefault();
406
407 // Data URLs can be very long, so truncate to avoid flooding the log.
408 const uint32_t maxURLLength = 1000;
409 if (url.Length() > maxURLLength) {
410 url.Truncate(maxURLLength);
411 }
412 }
413
414 // We're counting the number of |nsDocShells| to help find leaks
415 --gNumberOfDocShells;
416 MOZ_LOG(do { const ::mozilla::LogModule* moz_real_module = gDocShellAndDOMWindowLeakLogging
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Info, "--DOCSHELL %p == %ld [pid = %d] [id = %" "l"
"u" "] [url = %s]\n", (void*)this, gNumberOfDocShells, getpid
(), mDocShellID, url.get()); } } while (0)
417 gDocShellAndDOMWindowLeakLogging, LogLevel::Info,do { const ::mozilla::LogModule* moz_real_module = gDocShellAndDOMWindowLeakLogging
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Info, "--DOCSHELL %p == %ld [pid = %d] [id = %" "l"
"u" "] [url = %s]\n", (void*)this, gNumberOfDocShells, getpid
(), mDocShellID, url.get()); } } while (0)
418 ("--DOCSHELL %p == %ld [pid = %d] [id = %" PRIu64 "] [url = %s]\n",do { const ::mozilla::LogModule* moz_real_module = gDocShellAndDOMWindowLeakLogging
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Info, "--DOCSHELL %p == %ld [pid = %d] [id = %" "l"
"u" "] [url = %s]\n", (void*)this, gNumberOfDocShells, getpid
(), mDocShellID, url.get()); } } while (0)
419 (void*)this, gNumberOfDocShells, getpid(), mDocShellID, url.get()))do { const ::mozilla::LogModule* moz_real_module = gDocShellAndDOMWindowLeakLogging
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Info, "--DOCSHELL %p == %ld [pid = %d] [id = %" "l"
"u" "] [url = %s]\n", (void*)this, gNumberOfDocShells, getpid
(), mDocShellID, url.get()); } } while (0)
;
420 }
421#endif
422}
423
424bool nsDocShell::Initialize() {
425 if (mInitialized) {
426 // We've already been initialized.
427 return true;
428 }
429
430 NS_ASSERTION(mItemType == typeContent || mItemType == typeChrome,do { if (!(mItemType == typeContent || mItemType == typeChrome
)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "Unexpected item type in docshell"
, "mItemType == typeContent || mItemType == typeChrome", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 431); MOZ_PretendNoReturn(); } } while (0)
431 "Unexpected item type in docshell")do { if (!(mItemType == typeContent || mItemType == typeChrome
)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "Unexpected item type in docshell"
, "mItemType == typeContent || mItemType == typeChrome", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 431); MOZ_PretendNoReturn(); } } while (0)
;
432
433 NS_ENSURE_TRUE(Preferences::GetRootBranch(), false)do { if ((__builtin_expect(!!(!(Preferences::GetRootBranch())
), 0))) { NS_DebugBreak(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "Preferences::GetRootBranch()"
") failed", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 433); return false; } } while (false)
;
434 mInitialized = true;
435
436 mDisableMetaRefreshWhenInactive =
437 Preferences::GetBool("browser.meta_refresh_when_inactive.disabled",
438 mDisableMetaRefreshWhenInactive);
439
440 if (nsCOMPtr<nsIObserverService> serv = services::GetObserverService()) {
441 const char* msg = mItemType == typeContent ? NS_WEBNAVIGATION_CREATE"webnavigation-create"
442 : NS_CHROME_WEBNAVIGATION_CREATE"chrome-webnavigation-create";
443 serv->NotifyWhenScriptSafe(GetAsSupports(this), msg, nullptr);
444 }
445
446 return true;
447}
448
449/* static */
450already_AddRefed<nsDocShell> nsDocShell::Create(
451 BrowsingContext* aBrowsingContext, uint64_t aContentWindowID) {
452 MOZ_ASSERT(aBrowsingContext, "DocShell without a BrowsingContext!")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aBrowsingContext)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aBrowsingContext))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("aBrowsingContext"
" (" "DocShell without a BrowsingContext!" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 452); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aBrowsingContext"
") (" "DocShell without a BrowsingContext!" ")"); do { *((volatile
int*)__null) = 452; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
453
454 nsresult rv;
455 RefPtr<nsDocShell> ds = new nsDocShell(aBrowsingContext, aContentWindowID);
456
457 // Initialize the underlying nsDocLoader.
458 rv = ds->nsDocLoader::InitWithBrowsingContext(aBrowsingContext);
459 if (NS_WARN_IF(NS_FAILED(rv))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(rv
)), 0))), "NS_FAILED(rv)", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 459)
) {
460 return nullptr;
461 }
462
463 // Create our ContentListener
464 ds->mContentListener = new nsDSURIContentListener(ds);
465
466 // We enable if we're in the parent process in order to support non-e10s
467 // configurations.
468 // Note: This check is duplicated in SharedWorkerInterfaceRequestor's
469 // constructor.
470 if (XRE_IsParentProcess()) {
471 ds->mInterceptController = new ServiceWorkerInterceptController();
472 }
473
474 // We want to hold a strong ref to the loadgroup, so it better hold a weak
475 // ref to us... use an InterfaceRequestorProxy to do this.
476 nsCOMPtr<nsIInterfaceRequestor> proxy = new InterfaceRequestorProxy(ds);
477 ds->mLoadGroup->SetNotificationCallbacks(proxy);
478
479 // XXX(nika): We have our BrowsingContext, so we might be able to skip this.
480 // It could be nice to directly set up our DocLoader tree?
481 rv = nsDocLoader::AddDocLoaderAsChildOfRoot(ds);
482 if (NS_WARN_IF(NS_FAILED(rv))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(rv
)), 0))), "NS_FAILED(rv)", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 482)
) {
483 return nullptr;
484 }
485
486 // Add |ds| as a progress listener to itself. A little weird, but simpler
487 // than reproducing all the listener-notification logic in overrides of the
488 // various methods via which nsDocLoader can be notified. Note that this
489 // holds an nsWeakPtr to |ds|, so it's ok.
490 rv = ds->AddProgressListener(ds, nsIWebProgress::NOTIFY_STATE_DOCUMENT |
491 nsIWebProgress::NOTIFY_STATE_NETWORK |
492 nsIWebProgress::NOTIFY_LOCATION);
493 if (NS_WARN_IF(NS_FAILED(rv))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(rv
)), 0))), "NS_FAILED(rv)", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 493)
) {
494 return nullptr;
495 }
496
497 // If our BrowsingContext has private browsing enabled, update the number of
498 // private browsing docshells.
499 if (aBrowsingContext->UsePrivateBrowsing()) {
500 ds->NotifyPrivateBrowsingChanged();
501 }
502
503 // If our parent window is present in this process, set up our parent now.
504 RefPtr<WindowContext> parentWC = aBrowsingContext->GetParentWindowContext();
505 if (parentWC && parentWC->IsInProcess()) {
506 // If we don't have a parent element anymore, we can't finish this load!
507 // How'd we get here?
508 RefPtr<Element> parentElement = aBrowsingContext->GetEmbedderElement();
509 if (!parentElement) {
510 MOZ_ASSERT_UNREACHABLE("nsDocShell::Create() - !parentElement")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "MOZ_ASSERT_UNREACHABLE: "
"nsDocShell::Create() - !parentElement" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 510); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "nsDocShell::Create() - !parentElement"
")"); do { *((volatile int*)__null) = 510; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
511 return nullptr;
512 }
513
514 // We have an in-process parent window, but don't have a parent nsDocShell?
515 // How'd we get here!
516 nsCOMPtr<nsIDocShell> parentShell =
517 parentElement->OwnerDoc()->GetDocShell();
518 if (!parentShell) {
519 MOZ_ASSERT_UNREACHABLE("nsDocShell::Create() - !parentShell")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "MOZ_ASSERT_UNREACHABLE: "
"nsDocShell::Create() - !parentShell" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 519); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "nsDocShell::Create() - !parentShell"
")"); do { *((volatile int*)__null) = 519; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
520 return nullptr;
521 }
522 parentShell->AddChild(ds);
523 }
524
525 // Make |ds| the primary DocShell for the given context.
526 aBrowsingContext->SetDocShell(ds);
527
528 // Set |ds| default load flags on load group.
529 ds->SetLoadGroupDefaultLoadFlags(aBrowsingContext->GetDefaultLoadFlags());
530
531 if (XRE_IsParentProcess()) {
532 aBrowsingContext->Canonical()->MaybeAddAsProgressListener(ds);
533 }
534
535 return ds.forget();
536}
537
538void nsDocShell::DestroyChildren() {
539 for (auto* child : mChildList.ForwardRange()) {
540 nsCOMPtr<nsIDocShellTreeItem> shell = do_QueryObject(child);
541 NS_ASSERTION(shell, "docshell has null child")do { if (!(shell)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "docshell has null child"
, "shell", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 541); MOZ_PretendNoReturn(); } } while (0)
;
542
543 if (shell) {
544 shell->SetTreeOwner(nullptr);
545 }
546 }
547
548 nsDocLoader::DestroyChildren();
549}
550
551NS_IMPL_CYCLE_COLLECTION_WEAK_PTR_INHERITED(nsDocShell, nsDocLoader,nsDocShell::cycleCollection nsDocShell::_cycleCollectorGlobal
; void nsDocShell::cycleCollection::Unlink(void* p) { nsDocShell
* tmp = DowncastCCParticipant<nsDocShell>(p); nsISupports
* s = static_cast<nsISupports*>(p); nsDocLoader::cycleCollection
::Unlink(s); ImplCycleCollectionUnlink(tmp->mScriptGlobal)
; ImplCycleCollectionUnlink(tmp->mInitialClientSource); ImplCycleCollectionUnlink
(tmp->mBrowsingContext); ImplCycleCollectionUnlink(tmp->
mChromeEventHandler); tmp->DetachWeakPtr(); (void)tmp; } nsresult
nsDocShell::cycleCollection::TraverseNative( void* p, nsCycleCollectionTraversalCallback
& cb) { nsDocShell* tmp = DowncastCCParticipant<nsDocShell
>(p); nsISupports* s = static_cast<nsISupports*>(p);
if (nsDocLoader::cycleCollection::TraverseNative(s, cb) == NS_SUCCESS_INTERRUPTED_TRAVERSE
) { return NS_SUCCESS_INTERRUPTED_TRAVERSE; } ImplCycleCollectionTraverse
(cb, tmp->mScriptGlobal, "mScriptGlobal", 0); ImplCycleCollectionTraverse
(cb, tmp->mInitialClientSource, "mInitialClientSource", 0)
; ImplCycleCollectionTraverse(cb, tmp->mBrowsingContext, "mBrowsingContext"
, 0); ImplCycleCollectionTraverse(cb, tmp->mChromeEventHandler
, "mChromeEventHandler", 0); (void)tmp; return NS_OK; }
552 mScriptGlobal, mInitialClientSource,nsDocShell::cycleCollection nsDocShell::_cycleCollectorGlobal
; void nsDocShell::cycleCollection::Unlink(void* p) { nsDocShell
* tmp = DowncastCCParticipant<nsDocShell>(p); nsISupports
* s = static_cast<nsISupports*>(p); nsDocLoader::cycleCollection
::Unlink(s); ImplCycleCollectionUnlink(tmp->mScriptGlobal)
; ImplCycleCollectionUnlink(tmp->mInitialClientSource); ImplCycleCollectionUnlink
(tmp->mBrowsingContext); ImplCycleCollectionUnlink(tmp->
mChromeEventHandler); tmp->DetachWeakPtr(); (void)tmp; } nsresult
nsDocShell::cycleCollection::TraverseNative( void* p, nsCycleCollectionTraversalCallback
& cb) { nsDocShell* tmp = DowncastCCParticipant<nsDocShell
>(p); nsISupports* s = static_cast<nsISupports*>(p);
if (nsDocLoader::cycleCollection::TraverseNative(s, cb) == NS_SUCCESS_INTERRUPTED_TRAVERSE
) { return NS_SUCCESS_INTERRUPTED_TRAVERSE; } ImplCycleCollectionTraverse
(cb, tmp->mScriptGlobal, "mScriptGlobal", 0); ImplCycleCollectionTraverse
(cb, tmp->mInitialClientSource, "mInitialClientSource", 0)
; ImplCycleCollectionTraverse(cb, tmp->mBrowsingContext, "mBrowsingContext"
, 0); ImplCycleCollectionTraverse(cb, tmp->mChromeEventHandler
, "mChromeEventHandler", 0); (void)tmp; return NS_OK; }
553 mBrowsingContext,nsDocShell::cycleCollection nsDocShell::_cycleCollectorGlobal
; void nsDocShell::cycleCollection::Unlink(void* p) { nsDocShell
* tmp = DowncastCCParticipant<nsDocShell>(p); nsISupports
* s = static_cast<nsISupports*>(p); nsDocLoader::cycleCollection
::Unlink(s); ImplCycleCollectionUnlink(tmp->mScriptGlobal)
; ImplCycleCollectionUnlink(tmp->mInitialClientSource); ImplCycleCollectionUnlink
(tmp->mBrowsingContext); ImplCycleCollectionUnlink(tmp->
mChromeEventHandler); tmp->DetachWeakPtr(); (void)tmp; } nsresult
nsDocShell::cycleCollection::TraverseNative( void* p, nsCycleCollectionTraversalCallback
& cb) { nsDocShell* tmp = DowncastCCParticipant<nsDocShell
>(p); nsISupports* s = static_cast<nsISupports*>(p);
if (nsDocLoader::cycleCollection::TraverseNative(s, cb) == NS_SUCCESS_INTERRUPTED_TRAVERSE
) { return NS_SUCCESS_INTERRUPTED_TRAVERSE; } ImplCycleCollectionTraverse
(cb, tmp->mScriptGlobal, "mScriptGlobal", 0); ImplCycleCollectionTraverse
(cb, tmp->mInitialClientSource, "mInitialClientSource", 0)
; ImplCycleCollectionTraverse(cb, tmp->mBrowsingContext, "mBrowsingContext"
, 0); ImplCycleCollectionTraverse(cb, tmp->mChromeEventHandler
, "mChromeEventHandler", 0); (void)tmp; return NS_OK; }
554 mChromeEventHandler)nsDocShell::cycleCollection nsDocShell::_cycleCollectorGlobal
; void nsDocShell::cycleCollection::Unlink(void* p) { nsDocShell
* tmp = DowncastCCParticipant<nsDocShell>(p); nsISupports
* s = static_cast<nsISupports*>(p); nsDocLoader::cycleCollection
::Unlink(s); ImplCycleCollectionUnlink(tmp->mScriptGlobal)
; ImplCycleCollectionUnlink(tmp->mInitialClientSource); ImplCycleCollectionUnlink
(tmp->mBrowsingContext); ImplCycleCollectionUnlink(tmp->
mChromeEventHandler); tmp->DetachWeakPtr(); (void)tmp; } nsresult
nsDocShell::cycleCollection::TraverseNative( void* p, nsCycleCollectionTraversalCallback
& cb) { nsDocShell* tmp = DowncastCCParticipant<nsDocShell
>(p); nsISupports* s = static_cast<nsISupports*>(p);
if (nsDocLoader::cycleCollection::TraverseNative(s, cb) == NS_SUCCESS_INTERRUPTED_TRAVERSE
) { return NS_SUCCESS_INTERRUPTED_TRAVERSE; } ImplCycleCollectionTraverse
(cb, tmp->mScriptGlobal, "mScriptGlobal", 0); ImplCycleCollectionTraverse
(cb, tmp->mInitialClientSource, "mInitialClientSource", 0)
; ImplCycleCollectionTraverse(cb, tmp->mBrowsingContext, "mBrowsingContext"
, 0); ImplCycleCollectionTraverse(cb, tmp->mChromeEventHandler
, "mChromeEventHandler", 0); (void)tmp; return NS_OK; }
555
556NS_IMPL_ADDREF_INHERITED(nsDocShell, nsDocLoader)MozExternalRefCountType nsDocShell::AddRef(void) { static_assert
(!std::is_destructible_v<nsDocShell>, "Reference-counted class "
"nsDocShell" " should not have a public destructor. " "Make this class's destructor non-public"
); nsrefcnt r = nsDocLoader::AddRef(); if constexpr (::mozilla
::detail::ShouldLogInheritedRefcnt<nsDocShell>) { NS_LogAddRef
((this), (r), ("nsDocShell"), (uint32_t)(sizeof(*this))); } return
r; }
557NS_IMPL_RELEASE_INHERITED(nsDocShell, nsDocLoader)MozExternalRefCountType nsDocShell::Release(void) { nsrefcnt r
= nsDocLoader::Release(); if constexpr (::mozilla::detail::ShouldLogInheritedRefcnt
<nsDocShell>) { NS_LogRelease((this), (r), ("nsDocShell"
)); } return r; }
558
559NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsDocShell)nsresult nsDocShell::QueryInterface(const nsIID& aIID, void
** aInstancePtr) { do { if (!(aInstancePtr)) { NS_DebugBreak(
NS_DEBUG_ASSERTION, "QueryInterface requires a non-NULL destination!"
, "aInstancePtr", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 559); MOZ_PretendNoReturn(); } } while (0); nsISupports* foundInterface
; if (TopThreeWordsEquals( aIID, (nsXPCOMCycleCollectionParticipant
::COMTypeInfo<nsXPCOMCycleCollectionParticipant, void>::
kIID), (nsCycleCollectionISupports::COMTypeInfo<nsCycleCollectionISupports
, void>::kIID)) && (LowWordEquals(aIID, (nsXPCOMCycleCollectionParticipant
::COMTypeInfo<nsXPCOMCycleCollectionParticipant, void>::
kIID)) || LowWordEquals(aIID, (nsCycleCollectionISupports::COMTypeInfo
<nsCycleCollectionISupports, void>::kIID)))) { if (LowWordEquals
(aIID, (nsXPCOMCycleCollectionParticipant::COMTypeInfo<nsXPCOMCycleCollectionParticipant
, void>::kIID))) { *aInstancePtr = nsDocShell::cycleCollection
::GetParticipant(); return NS_OK; } if (LowWordEquals(aIID, (
nsCycleCollectionISupports::COMTypeInfo<nsCycleCollectionISupports
, void>::kIID))) { *aInstancePtr = nsDocShell::cycleCollection
::Upcast(this); return NS_OK; } foundInterface = nullptr; } else
560 NS_INTERFACE_MAP_ENTRY(nsIDocShell)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIDocShell>)) foundInterface = static_cast
<nsIDocShell*>(this); else
561 NS_INTERFACE_MAP_ENTRY(nsIDocShellTreeItem)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIDocShellTreeItem>)) foundInterface
= static_cast<nsIDocShellTreeItem*>(this); else
562 NS_INTERFACE_MAP_ENTRY(nsIWebNavigation)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIWebNavigation>)) foundInterface
= static_cast<nsIWebNavigation*>(this); else
563 NS_INTERFACE_MAP_ENTRY(nsIBaseWindow)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIBaseWindow>)) foundInterface =
static_cast<nsIBaseWindow*>(this); else
564 NS_INTERFACE_MAP_ENTRY(nsIRefreshURI)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIRefreshURI>)) foundInterface =
static_cast<nsIRefreshURI*>(this); else
565 NS_INTERFACE_MAP_ENTRY(nsIWebProgressListener)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIWebProgressListener>)) foundInterface
= static_cast<nsIWebProgressListener*>(this); else
566 NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsISupportsWeakReference>)) foundInterface
= static_cast<nsISupportsWeakReference*>(this); else
567 NS_INTERFACE_MAP_ENTRY(nsIWebPageDescriptor)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIWebPageDescriptor>)) foundInterface
= static_cast<nsIWebPageDescriptor*>(this); else
568 NS_INTERFACE_MAP_ENTRY(nsIAuthPromptProvider)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIAuthPromptProvider>)) foundInterface
= static_cast<nsIAuthPromptProvider*>(this); else
569 NS_INTERFACE_MAP_ENTRY(nsILoadContext)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsILoadContext>)) foundInterface =
static_cast<nsILoadContext*>(this); else
570 NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsINetworkInterceptController,if ((mInterceptController) && aIID.Equals(mozilla::detail
::kImplementedIID<std::remove_reference_t<decltype(*this
)>, nsINetworkInterceptController>)) foundInterface = static_cast
<nsINetworkInterceptController*>(this); else
571 mInterceptController)if ((mInterceptController) && aIID.Equals(mozilla::detail
::kImplementedIID<std::remove_reference_t<decltype(*this
)>, nsINetworkInterceptController>)) foundInterface = static_cast
<nsINetworkInterceptController*>(this); else
572NS_INTERFACE_MAP_END_INHERITING(nsDocLoader)foundInterface = 0; nsresult status; if (!foundInterface) status
= nsDocLoader::QueryInterface(aIID, (void**)&foundInterface
); else { (foundInterface)->AddRef(); status = NS_OK; } *aInstancePtr
= foundInterface; return status; }
573
574NS_IMETHODIMPnsresult
575nsDocShell::GetInterface(const nsIID& aIID, void** aSink) {
576 MOZ_ASSERT(aSink, "null out param")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aSink)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(aSink))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("aSink" " (" "null out param"
")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 576); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aSink" ") ("
"null out param" ")"); do { *((volatile int*)__null) = 576; __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
;
577
578 *aSink = nullptr;
579
580 if (aIID.Equals(NS_GET_IID(nsICommandManager)(nsICommandManager::COMTypeInfo<nsICommandManager, void>
::kIID)
)) {
581 NS_ENSURE_SUCCESS(EnsureCommandHandler(), NS_ERROR_FAILURE)do { nsresult __rv = EnsureCommandHandler(); if (((bool)(__builtin_expect
(!!(NS_FAILED_impl(__rv)), 0)))) { const char* name = mozilla
::GetStaticErrorName(__rv); mozilla::SmprintfPointer msg = mozilla
::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%"
"X" "%s%s%s", "EnsureCommandHandler()", "NS_ERROR_FAILURE", static_cast
<uint32_t>(__rv), name ? " (" : "", name ? name : "", name
? ")" : ""); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 581); return NS_ERROR_FAILURE; } } while (false)
;
582 *aSink = static_cast<nsICommandManager*>(mCommandManager.get());
583 } else if (aIID.Equals(NS_GET_IID(nsIURIContentListener)(nsIURIContentListener::COMTypeInfo<nsIURIContentListener,
void>::kIID)
)) {
584 *aSink = mContentListener;
585 } else if ((aIID.Equals(NS_GET_IID(nsIScriptGlobalObject)(nsIScriptGlobalObject::COMTypeInfo<nsIScriptGlobalObject,
void>::kIID)
) ||
586 aIID.Equals(NS_GET_IID(nsIGlobalObject)(nsIGlobalObject::COMTypeInfo<nsIGlobalObject, void>::kIID
)
) ||
587 aIID.Equals(NS_GET_IID(nsPIDOMWindowOuter)(nsPIDOMWindowOuter::COMTypeInfo<nsPIDOMWindowOuter, void>
::kIID)
) ||
588 aIID.Equals(NS_GET_IID(mozIDOMWindowProxy)(mozIDOMWindowProxy::COMTypeInfo<mozIDOMWindowProxy, void>
::kIID)
) ||
589 aIID.Equals(NS_GET_IID(nsIDOMWindow)(nsIDOMWindow::COMTypeInfo<nsIDOMWindow, void>::kIID))) &&
590 NS_SUCCEEDED(EnsureScriptEnvironment())((bool)(__builtin_expect(!!(!NS_FAILED_impl(EnsureScriptEnvironment
())), 1)))
) {
591 return mScriptGlobal->QueryInterface(aIID, aSink);
592 } else if (aIID.Equals(NS_GET_IID(Document)(Document::COMTypeInfo<Document, void>::kIID)) &&
593 NS_SUCCEEDED(EnsureDocumentViewer())((bool)(__builtin_expect(!!(!NS_FAILED_impl(EnsureDocumentViewer
())), 1)))
) {
594 RefPtr<Document> doc = mDocumentViewer->GetDocument();
595 doc.forget(aSink);
596 return *aSink ? NS_OK : NS_NOINTERFACE;
597 } else if (aIID.Equals(NS_GET_IID(nsIPrompt)(nsIPrompt::COMTypeInfo<nsIPrompt, void>::kIID)) &&
598 NS_SUCCEEDED(EnsureScriptEnvironment())((bool)(__builtin_expect(!!(!NS_FAILED_impl(EnsureScriptEnvironment
())), 1)))
) {
599 nsresult rv;
600 nsCOMPtr<nsIWindowWatcher> wwatch =
601 do_GetService(NS_WINDOWWATCHER_CONTRACTID"@mozilla.org/embedcomp/window-watcher;1", &rv);
602 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 602); return rv; } } while (false)
;
603
604 // Get the an auth prompter for our window so that the parenting
605 // of the dialogs works as it should when using tabs.
606 nsIPrompt* prompt;
607 rv = wwatch->GetNewPrompter(mScriptGlobal, &prompt);
608 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 608); return rv; } } while (false)
;
609
610 *aSink = prompt;
611 return NS_OK;
612 } else if (aIID.Equals(NS_GET_IID(nsIAuthPrompt)(nsIAuthPrompt::COMTypeInfo<nsIAuthPrompt, void>::kIID)) ||
613 aIID.Equals(NS_GET_IID(nsIAuthPrompt2)(nsIAuthPrompt2::COMTypeInfo<nsIAuthPrompt2, void>::kIID
)
)) {
614 return NS_SUCCEEDED(GetAuthPrompt(PROMPT_NORMAL, aIID, aSink))((bool)(__builtin_expect(!!(!NS_FAILED_impl(GetAuthPrompt(PROMPT_NORMAL
, aIID, aSink))), 1)))
615 ? NS_OK
616 : NS_NOINTERFACE;
617 } else if (aIID.Equals(NS_GET_IID(nsISHistory)(nsISHistory::COMTypeInfo<nsISHistory, void>::kIID))) {
618 // This is deprecated, you should instead directly get
619 // ChildSHistory from the browsing context.
620 MOZ_DIAGNOSTIC_ASSERT(do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "Do not try to get a nsISHistory interface from nsIDocShell"
")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 621); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "false"
") (" "Do not try to get a nsISHistory interface from nsIDocShell"
")"); do { *((volatile int*)__null) = 621; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
621 false, "Do not try to get a nsISHistory interface from nsIDocShell")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "Do not try to get a nsISHistory interface from nsIDocShell"
")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 621); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "false"
") (" "Do not try to get a nsISHistory interface from nsIDocShell"
")"); do { *((volatile int*)__null) = 621; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
622 return NS_NOINTERFACE;
623 } else if (aIID.Equals(NS_GET_IID(nsIWebBrowserFind)(nsIWebBrowserFind::COMTypeInfo<nsIWebBrowserFind, void>
::kIID)
)) {
624 nsresult rv = EnsureFind();
625 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
626 return rv;
627 }
628
629 *aSink = mFind;
630 NS_ADDREF((nsISupports*)*aSink)((nsISupports*)*aSink)->AddRef();
631 return NS_OK;
632 } else if (aIID.Equals(NS_GET_IID(nsISelectionDisplay)(nsISelectionDisplay::COMTypeInfo<nsISelectionDisplay, void
>::kIID)
)) {
633 if (PresShell* presShell = GetPresShell()) {
634 return presShell->QueryInterface(aIID, aSink);
635 }
636 } else if (aIID.Equals(NS_GET_IID(nsIDocShellTreeOwner)(nsIDocShellTreeOwner::COMTypeInfo<nsIDocShellTreeOwner, void
>::kIID)
)) {
637 nsCOMPtr<nsIDocShellTreeOwner> treeOwner;
638 nsresult rv = GetTreeOwner(getter_AddRefs(treeOwner));
639 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && treeOwner) {
640 return treeOwner->QueryInterface(aIID, aSink);
641 }
642 } else if (aIID.Equals(NS_GET_IID(nsIBrowserChild)(nsIBrowserChild::COMTypeInfo<nsIBrowserChild, void>::kIID
)
)) {
643 *aSink = GetBrowserChild().take();
644 return *aSink ? NS_OK : NS_ERROR_FAILURE;
645 } else {
646 return nsDocLoader::GetInterface(aIID, aSink);
647 }
648
649 NS_IF_ADDREF(((nsISupports*)*aSink))ns_if_addref(((nsISupports*)*aSink));
650 return *aSink ? NS_OK : NS_NOINTERFACE;
651}
652
653NS_IMETHODIMPnsresult
654nsDocShell::SetCancelContentJSEpoch(int32_t aEpoch) {
655 // Note: this gets called fairly early (before a pageload actually starts).
656 // We could probably defer this even longer.
657 nsCOMPtr<nsIBrowserChild> browserChild = GetBrowserChild();
658 static_cast<BrowserChild*>(browserChild.get())
659 ->SetCancelContentJSEpoch(aEpoch);
660 return NS_OK;
661}
662
663nsresult nsDocShell::CheckDisallowedJavascriptLoad(
664 nsDocShellLoadState* aLoadState) {
665 if (!net::SchemeIsJavascript(aLoadState->URI())) {
666 return NS_OK;
667 }
668
669 if (nsCOMPtr<nsIPrincipal> targetPrincipal =
670 GetInheritedPrincipal(/* aConsiderCurrentDocument */ true)) {
671 if (!aLoadState->TriggeringPrincipal()->Subsumes(targetPrincipal)) {
672 return NS_ERROR_DOM_BAD_CROSS_ORIGIN_URI;
673 }
674 return NS_OK;
675 }
676 return NS_ERROR_DOM_BAD_CROSS_ORIGIN_URI;
677}
678
679NS_IMETHODIMPnsresult
680nsDocShell::LoadURI(nsDocShellLoadState* aLoadState, bool aSetNavigating) {
681 return LoadURI(aLoadState, aSetNavigating, false);
682}
683
684nsresult nsDocShell::LoadURI(nsDocShellLoadState* aLoadState,
685 bool aSetNavigating,
686 bool aContinueHandlingSubframeHistory) {
687 MOZ_ASSERT(aLoadState, "Must have a valid load state!")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aLoadState)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aLoadState))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("aLoadState" " (" "Must have a valid load state!"
")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 687); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState" ") ("
"Must have a valid load state!" ")"); do { *((volatile int*)
__null) = 687; __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
688 // NOTE: This comparison between what appears to be internal/external load
689 // flags is intentional, as it's ensuring that the caller isn't using any of
690 // the flags reserved for implementations by the `nsIWebNavigation` interface.
691 // In the future, this check may be dropped.
692 MOZ_ASSERT(do { static_assert( mozilla::detail::AssertionConditionType<
decltype((aLoadState->LoadFlags() & INTERNAL_LOAD_FLAGS_LOADURI_SETUP_FLAGS
) == 0)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!((aLoadState->LoadFlags() & INTERNAL_LOAD_FLAGS_LOADURI_SETUP_FLAGS
) == 0))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("(aLoadState->LoadFlags() & INTERNAL_LOAD_FLAGS_LOADURI_SETUP_FLAGS) == 0"
" (" "Should not have these flags set" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 694); AnnotateMozCrashReason("MOZ_ASSERT" "(" "(aLoadState->LoadFlags() & INTERNAL_LOAD_FLAGS_LOADURI_SETUP_FLAGS) == 0"
") (" "Should not have these flags set" ")"); do { *((volatile
int*)__null) = 694; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
693 (aLoadState->LoadFlags() & INTERNAL_LOAD_FLAGS_LOADURI_SETUP_FLAGS) == 0,do { static_assert( mozilla::detail::AssertionConditionType<
decltype((aLoadState->LoadFlags() & INTERNAL_LOAD_FLAGS_LOADURI_SETUP_FLAGS
) == 0)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!((aLoadState->LoadFlags() & INTERNAL_LOAD_FLAGS_LOADURI_SETUP_FLAGS
) == 0))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("(aLoadState->LoadFlags() & INTERNAL_LOAD_FLAGS_LOADURI_SETUP_FLAGS) == 0"
" (" "Should not have these flags set" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 694); AnnotateMozCrashReason("MOZ_ASSERT" "(" "(aLoadState->LoadFlags() & INTERNAL_LOAD_FLAGS_LOADURI_SETUP_FLAGS) == 0"
") (" "Should not have these flags set" ")"); do { *((volatile
int*)__null) = 694; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
694 "Should not have these flags set")do { static_assert( mozilla::detail::AssertionConditionType<
decltype((aLoadState->LoadFlags() & INTERNAL_LOAD_FLAGS_LOADURI_SETUP_FLAGS
) == 0)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!((aLoadState->LoadFlags() & INTERNAL_LOAD_FLAGS_LOADURI_SETUP_FLAGS
) == 0))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("(aLoadState->LoadFlags() & INTERNAL_LOAD_FLAGS_LOADURI_SETUP_FLAGS) == 0"
" (" "Should not have these flags set" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 694); AnnotateMozCrashReason("MOZ_ASSERT" "(" "(aLoadState->LoadFlags() & INTERNAL_LOAD_FLAGS_LOADURI_SETUP_FLAGS) == 0"
") (" "Should not have these flags set" ")"); do { *((volatile
int*)__null) = 694; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
695 MOZ_ASSERT(aLoadState->TargetBrowsingContext().IsNull(),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aLoadState->TargetBrowsingContext().IsNull())>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(aLoadState->TargetBrowsingContext().IsNull()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("aLoadState->TargetBrowsingContext().IsNull()"
" (" "Targeting doesn't occur until InternalLoad" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 696); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->TargetBrowsingContext().IsNull()"
") (" "Targeting doesn't occur until InternalLoad" ")"); do {
*((volatile int*)__null) = 696; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
696 "Targeting doesn't occur until InternalLoad")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aLoadState->TargetBrowsingContext().IsNull())>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(aLoadState->TargetBrowsingContext().IsNull()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("aLoadState->TargetBrowsingContext().IsNull()"
" (" "Targeting doesn't occur until InternalLoad" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 696); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->TargetBrowsingContext().IsNull()"
") (" "Targeting doesn't occur until InternalLoad" ")"); do {
*((volatile int*)__null) = 696; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
;
697
698 if (!aLoadState->TriggeringPrincipal()) {
699 MOZ_ASSERT(false, "LoadURI must have a triggering principal")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "LoadURI must have a triggering principal"
")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 699); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"LoadURI must have a triggering principal" ")"); do { *((volatile
int*)__null) = 699; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
700 return NS_ERROR_FAILURE;
701 }
702
703 MOZ_TRY(CheckDisallowedJavascriptLoad(aLoadState))do { auto mozTryTempResult_ = ::mozilla::ToResult(CheckDisallowedJavascriptLoad
(aLoadState)); if ((__builtin_expect(!!(mozTryTempResult_.isErr
()), 0))) { return mozTryTempResult_.propagateErr(); } } while
(0)
;
704
705 bool oldIsNavigating = mIsNavigating;
706 auto cleanupIsNavigating =
707 MakeScopeExit([&]() { mIsNavigating = oldIsNavigating; });
708 if (aSetNavigating) {
709 mIsNavigating = true;
710 }
711
712 PopupBlocker::PopupControlState popupState = PopupBlocker::openOverridden;
713 if (aLoadState->HasLoadFlags(LOAD_FLAGS_ALLOW_POPUPS)) {
714 popupState = PopupBlocker::openAllowed;
715 // If we allow popups as part of the navigation, ensure we fake a user
716 // interaction, so that popups can, in fact, be allowed to open.
717 if (WindowContext* wc = mBrowsingContext->GetCurrentWindowContext()) {
718 wc->NotifyUserGestureActivation();
719 }
720 }
721
722 AutoPopupStatePusherAutoPopupStatePusherInternal statePusher(popupState);
723
724 if (aLoadState->GetCancelContentJSEpoch().isSome()) {
725 SetCancelContentJSEpoch(*aLoadState->GetCancelContentJSEpoch());
726 }
727
728 // Note: we allow loads to get through here even if mFiredUnloadEvent is
729 // true; that case will get handled in LoadInternal or LoadHistoryEntry,
730 // so we pass false as the second parameter to IsNavigationAllowed.
731 // However, we don't allow the page to change location *in the middle of*
732 // firing beforeunload, so we do need to check if *beforeunload* is currently
733 // firing, so we call IsNavigationAllowed rather than just IsPrintingOrPP.
734 if (!IsNavigationAllowed(true, false)) {
735 return NS_OK; // JS may not handle returning of an error code
736 }
737
738 nsLoadFlags defaultLoadFlags = mBrowsingContext->GetDefaultLoadFlags();
739 if (aLoadState->HasLoadFlags(LOAD_FLAGS_FORCE_TRR)) {
740 defaultLoadFlags |= nsIRequest::LOAD_TRR_ONLY_MODE;
741 } else if (aLoadState->HasLoadFlags(LOAD_FLAGS_DISABLE_TRR)) {
742 defaultLoadFlags |= nsIRequest::LOAD_TRR_DISABLED_MODE;
743 }
744
745 MOZ_ALWAYS_SUCCEEDS(mBrowsingContext->SetDefaultLoadFlags(defaultLoadFlags))do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(mBrowsingContext->SetDefaultLoadFlags(defaultLoadFlags)))
, 1)))), 1))) { } else { do { static_assert( mozilla::detail::
AssertionConditionType<decltype(false)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("false" " (" "NS_SUCCEEDED(mBrowsingContext->SetDefaultLoadFlags(defaultLoadFlags))"
")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 745); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "false"
") (" "NS_SUCCEEDED(mBrowsingContext->SetDefaultLoadFlags(defaultLoadFlags))"
")"); do { *((volatile int*)__null) = 745; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
746
747 if (!StartupTimeline::HasRecord(StartupTimeline::FIRST_LOAD_URI) &&
748 mItemType == typeContent && !NS_IsAboutBlank(aLoadState->URI())) {
749 StartupTimeline::RecordOnce(StartupTimeline::FIRST_LOAD_URI);
750 }
751
752 // LoadType used to be set to a default value here, if no LoadInfo/LoadState
753 // object was passed in. That functionality has been removed as of bug
754 // 1492648. LoadType should now be set up by the caller at the time they
755 // create their nsDocShellLoadState object to pass into LoadURI.
756
757 MOZ_LOG(do { const ::mozilla::LogModule* moz_real_module = gDocShellLeakLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "nsDocShell[%p]: loading %s with flags 0x%08x"
, this, aLoadState->URI()->GetSpecOrDefault().get(), aLoadState
->LoadFlags()); } } while (0)
758 gDocShellLeakLog, LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = gDocShellLeakLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "nsDocShell[%p]: loading %s with flags 0x%08x"
, this, aLoadState->URI()->GetSpecOrDefault().get(), aLoadState
->LoadFlags()); } } while (0)
759 ("nsDocShell[%p]: loading %s with flags 0x%08x", this,do { const ::mozilla::LogModule* moz_real_module = gDocShellLeakLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "nsDocShell[%p]: loading %s with flags 0x%08x"
, this, aLoadState->URI()->GetSpecOrDefault().get(), aLoadState
->LoadFlags()); } } while (0)
760 aLoadState->URI()->GetSpecOrDefault().get(), aLoadState->LoadFlags()))do { const ::mozilla::LogModule* moz_real_module = gDocShellLeakLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "nsDocShell[%p]: loading %s with flags 0x%08x"
, this, aLoadState->URI()->GetSpecOrDefault().get(), aLoadState
->LoadFlags()); } } while (0)
;
761
762 if ((!aLoadState->LoadIsFromSessionHistory() &&
763 !LOAD_TYPE_HAS_FLAGS(aLoadState->LoadType(),((aLoadState->LoadType()) & ((LOAD_FLAGS_REPLACE_HISTORY
) << 16))
764 LOAD_FLAGS_REPLACE_HISTORY)((aLoadState->LoadType()) & ((LOAD_FLAGS_REPLACE_HISTORY
) << 16))
) ||
765 aContinueHandlingSubframeHistory) {
766 // This is possibly a subframe, so handle it accordingly.
767 //
768 // If history exists, it will be loaded into the aLoadState object, and the
769 // LoadType will be changed.
770 if (MaybeHandleSubframeHistory(aLoadState,
771 aContinueHandlingSubframeHistory)) {
772 // MaybeHandleSubframeHistory returns true if we need to continue loading
773 // asynchronously.
774 return NS_OK;
775 }
776 }
777
778 if (aLoadState->LoadIsFromSessionHistory()) {
779 MOZ_LOG(gSHLog, LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = gSHLog; if
((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "nsDocShell[%p]: loading from session history"
, this); } } while (0)
780 ("nsDocShell[%p]: loading from session history", this))do { const ::mozilla::LogModule* moz_real_module = gSHLog; if
((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "nsDocShell[%p]: loading from session history"
, this); } } while (0)
;
781
782 if (!mozilla::SessionHistoryInParent()) {
783 nsCOMPtr<nsISHEntry> entry = aLoadState->SHEntry();
784 return LoadHistoryEntry(entry, aLoadState->LoadType(),
785 aLoadState->HasValidUserGestureActivation());
786 }
787
788 // FIXME Null check aLoadState->GetLoadingSessionHistoryInfo()?
789 return LoadHistoryEntry(*aLoadState->GetLoadingSessionHistoryInfo(),
790 aLoadState->LoadType(),
791 aLoadState->HasValidUserGestureActivation());
792 }
793
794 // On history navigation via Back/Forward buttons, don't execute
795 // automatic JavaScript redirection such as |location.href = ...| or
796 // |window.open()|
797 //
798 // LOAD_NORMAL: window.open(...) etc.
799 // LOAD_STOP_CONTENT: location.href = ..., location.assign(...)
800 if ((aLoadState->LoadType() == LOAD_NORMAL ||
801 aLoadState->LoadType() == LOAD_STOP_CONTENT) &&
802 ShouldBlockLoadingForBackButton()) {
803 return NS_OK;
804 }
805
806 BrowsingContext::Type bcType = mBrowsingContext->GetType();
807
808 // Set up the inheriting principal in LoadState.
809 nsresult rv = aLoadState->SetupInheritingPrincipal(
810 bcType, mBrowsingContext->OriginAttributesRef());
811 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 811); return rv; } } while (false)
;
812
813 rv = aLoadState->SetupTriggeringPrincipal(
814 mBrowsingContext->OriginAttributesRef());
815 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 815); return rv; } } while (false)
;
816
817 aLoadState->CalculateLoadURIFlags();
818
819 MOZ_ASSERT(aLoadState->TypeHint().IsVoid(),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aLoadState->TypeHint().IsVoid())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aLoadState->TypeHint().IsVoid
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("aLoadState->TypeHint().IsVoid()" " (" "Typehint should be null when calling InternalLoad from LoadURI"
")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 820); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->TypeHint().IsVoid()"
") (" "Typehint should be null when calling InternalLoad from LoadURI"
")"); do { *((volatile int*)__null) = 820; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
820 "Typehint should be null when calling InternalLoad from LoadURI")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aLoadState->TypeHint().IsVoid())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aLoadState->TypeHint().IsVoid
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("aLoadState->TypeHint().IsVoid()" " (" "Typehint should be null when calling InternalLoad from LoadURI"
")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 820); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->TypeHint().IsVoid()"
") (" "Typehint should be null when calling InternalLoad from LoadURI"
")"); do { *((volatile int*)__null) = 820; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
821 MOZ_ASSERT(aLoadState->FileName().IsVoid(),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aLoadState->FileName().IsVoid())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aLoadState->FileName().IsVoid
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("aLoadState->FileName().IsVoid()" " (" "FileName should be null when calling InternalLoad from LoadURI"
")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 822); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->FileName().IsVoid()"
") (" "FileName should be null when calling InternalLoad from LoadURI"
")"); do { *((volatile int*)__null) = 822; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
822 "FileName should be null when calling InternalLoad from LoadURI")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aLoadState->FileName().IsVoid())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aLoadState->FileName().IsVoid
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("aLoadState->FileName().IsVoid()" " (" "FileName should be null when calling InternalLoad from LoadURI"
")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 822); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->FileName().IsVoid()"
") (" "FileName should be null when calling InternalLoad from LoadURI"
")"); do { *((volatile int*)__null) = 822; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
823 MOZ_ASSERT(!aLoadState->LoadIsFromSessionHistory(),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aLoadState->LoadIsFromSessionHistory())>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(!aLoadState->LoadIsFromSessionHistory()))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("!aLoadState->LoadIsFromSessionHistory()"
" (" "Shouldn't be loading from an entry when calling InternalLoad "
"from LoadURI" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 825); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aLoadState->LoadIsFromSessionHistory()"
") (" "Shouldn't be loading from an entry when calling InternalLoad "
"from LoadURI" ")"); do { *((volatile int*)__null) = 825; __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
824 "Shouldn't be loading from an entry when calling InternalLoad "do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aLoadState->LoadIsFromSessionHistory())>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(!aLoadState->LoadIsFromSessionHistory()))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("!aLoadState->LoadIsFromSessionHistory()"
" (" "Shouldn't be loading from an entry when calling InternalLoad "
"from LoadURI" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 825); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aLoadState->LoadIsFromSessionHistory()"
") (" "Shouldn't be loading from an entry when calling InternalLoad "
"from LoadURI" ")"); do { *((volatile int*)__null) = 825; __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
825 "from LoadURI")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aLoadState->LoadIsFromSessionHistory())>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(!aLoadState->LoadIsFromSessionHistory()))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("!aLoadState->LoadIsFromSessionHistory()"
" (" "Shouldn't be loading from an entry when calling InternalLoad "
"from LoadURI" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 825); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aLoadState->LoadIsFromSessionHistory()"
") (" "Shouldn't be loading from an entry when calling InternalLoad "
"from LoadURI" ")"); do { *((volatile int*)__null) = 825; __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
;
826
827 // If we have a system triggering principal, we can assume that this load was
828 // triggered by some UI in the browser chrome, such as the URL bar or
829 // bookmark bar. This should count as a user interaction for the current sh
830 // entry, so that the user may navigate back to the current entry, from the
831 // entry that is going to be added as part of this load.
832 nsCOMPtr<nsIPrincipal> triggeringPrincipal =
833 aLoadState->TriggeringPrincipal();
834 if (triggeringPrincipal && triggeringPrincipal->IsSystemPrincipal()) {
835 if (mozilla::SessionHistoryInParent()) {
836 WindowContext* topWc = mBrowsingContext->GetTopWindowContext();
837 if (topWc && !topWc->IsDiscarded()) {
838 MOZ_ALWAYS_SUCCEEDS(topWc->SetSHEntryHasUserInteraction(true))do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(topWc->SetSHEntryHasUserInteraction(true))), 1)))), 1))) {
} else { do { static_assert( mozilla::detail::AssertionConditionType
<decltype(false)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("false" " (" "NS_SUCCEEDED(topWc->SetSHEntryHasUserInteraction(true))"
")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 838); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "false"
") (" "NS_SUCCEEDED(topWc->SetSHEntryHasUserInteraction(true))"
")"); do { *((volatile int*)__null) = 838; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
839 }
840 } else {
841 bool oshe = false;
842 nsCOMPtr<nsISHEntry> currentSHEntry;
843 GetCurrentSHEntry(getter_AddRefs(currentSHEntry), &oshe);
844 if (currentSHEntry) {
845 currentSHEntry->SetHasUserInteraction(true);
846 }
847 }
848 }
849
850 rv = InternalLoad(aLoadState);
851 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 851); return rv; } } while (false)
;
852
853 if (aLoadState->GetOriginalURIString().isSome()) {
854 // Save URI string in case it's needed later when
855 // sending to search engine service in EndPageLoad()
856 mOriginalUriString = *aLoadState->GetOriginalURIString();
857 }
858
859 return NS_OK;
860}
861
862bool nsDocShell::IsLoadingFromSessionHistory() {
863 return mActiveEntryIsLoadingFromSessionHistory;
864}
865
866// StopDetector is modeled similarly to OnloadBlocker; it is a rather
867// dummy nsIRequest implementation which can be added to an nsILoadGroup to
868// detect Cancel calls.
869class StopDetector final : public nsIRequest {
870 public:
871 StopDetector() = default;
872
873 NS_DECL_ISUPPORTSpublic: virtual nsresult QueryInterface(const nsIID& aIID
, void** aInstancePtr) override; virtual MozExternalRefCountType
AddRef(void) override; virtual MozExternalRefCountType Release
(void) override; using HasThreadSafeRefCnt = std::false_type;
protected: nsAutoRefCnt mRefCnt; nsAutoOwningThread _mOwningThread
; public:
874 NS_DECL_NSIREQUESTvirtual nsresult GetName(nsACString& aName) override; virtual
nsresult IsPending(bool *_retval) override; virtual nsresult
GetStatus(nsresult *aStatus) override; virtual nsresult Cancel
(nsresult aStatus) override; virtual nsresult Suspend(void) override
; virtual nsresult Resume(void) override; virtual nsresult GetLoadGroup
(nsILoadGroup **aLoadGroup) override; virtual nsresult SetLoadGroup
(nsILoadGroup *aLoadGroup) override; virtual nsresult GetLoadFlags
(nsLoadFlags *aLoadFlags) override; virtual nsresult SetLoadFlags
(nsLoadFlags aLoadFlags) override; virtual nsresult GetTRRMode
(nsIRequest::TRRMode *_retval) override; virtual nsresult SetTRRMode
(nsIRequest::TRRMode mode) override; virtual nsresult CancelWithReason
(nsresult aStatus, const nsACString& aReason) override; virtual
nsresult GetCanceledReason(nsACString& aCanceledReason) override
; virtual nsresult SetCanceledReason(const nsACString& aCanceledReason
) override;
875
876 bool Canceled() { return mCanceled; }
877
878 private:
879 ~StopDetector() = default;
880
881 bool mCanceled = false;
882};
883
884NS_IMPL_ISUPPORTS(StopDetector, nsIRequest)MozExternalRefCountType StopDetector::AddRef(void) { static_assert
(!std::is_destructible_v<StopDetector>, "Reference-counted class "
"StopDetector" " should not have a public destructor. " "Make this class's destructor non-public"
); do { static_assert( mozilla::detail::AssertionConditionType
<decltype(int32_t(mRefCnt) >= 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) >= 0))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) >= 0"
" (" "illegal refcnt" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 884); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { *((volatile int*)__null) =
884; __attribute__((nomerge)) ::abort(); } while (false); } }
while (false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("StopDetector" != nullptr)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!("StopDetector" != nullptr)))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("\"StopDetector\" != nullptr"
" (" "Must specify a name" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 884); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"StopDetector\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 884; __attribute__((nomerge)) ::abort(); } while (false);
} } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread
.AssertOwnership("StopDetector" " not thread-safe"); nsrefcnt
count = ++mRefCnt; NS_LogAddRef((this), (count), ("StopDetector"
), (uint32_t)(sizeof(*this))); return count; } MozExternalRefCountType
StopDetector::Release(void) { do { static_assert( mozilla::detail
::AssertionConditionType<decltype(int32_t(mRefCnt) > 0)
>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(int32_t(mRefCnt) > 0))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("int32_t(mRefCnt) > 0" " (" "dup release"
")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 884); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { *((volatile int*)__null) = 884
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("StopDetector" != nullptr)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!("StopDetector" != nullptr)))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("\"StopDetector\" != nullptr"
" (" "Must specify a name" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 884); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"StopDetector\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 884; __attribute__((nomerge)) ::abort(); } while (false);
} } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread
.AssertOwnership("StopDetector" " not thread-safe"); const char
* const nametmp = "StopDetector"; nsrefcnt count = --mRefCnt;
NS_LogRelease((this), (count), (nametmp)); if (count == 0) {
mRefCnt = 1; delete (this); return 0; } return count; } nsresult
StopDetector::QueryInterface(const nsIID& aIID, void** aInstancePtr
) { do { if (!(aInstancePtr)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "QueryInterface requires a non-NULL destination!", "aInstancePtr"
, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 884); MOZ_PretendNoReturn(); } } while (0); nsresult rv = NS_ERROR_FAILURE
; static_assert(1 > 0, "Need more arguments to NS_INTERFACE_TABLE"
); static const QITableEntry table[] = { {&mozilla::detail
::kImplementedIID<StopDetector, nsIRequest>, int32_t( reinterpret_cast
<char*>(static_cast<nsIRequest*>((StopDetector*)0x1000
)) - reinterpret_cast<char*>((StopDetector*)0x1000))}, {
&mozilla::detail::kImplementedIID<StopDetector, nsISupports
>, int32_t(reinterpret_cast<char*>(static_cast<nsISupports
*>( static_cast<nsIRequest*>((StopDetector*)0x1000))
) - reinterpret_cast<char*>((StopDetector*)0x1000))}, {
nullptr, 0 } } ; static_assert((sizeof(table) / sizeof(table
[0])) > 1, "need at least 1 interface"); rv = NS_TableDrivenQI
(static_cast<void*>(this), aIID, aInstancePtr, table); return
rv; }
885
886NS_IMETHODIMPnsresult
887StopDetector::GetName(nsACString& aResult) {
888 aResult.AssignLiteral("about:stop-detector");
889 return NS_OK;
890}
891
892NS_IMETHODIMPnsresult
893StopDetector::IsPending(bool* aRetVal) {
894 *aRetVal = true;
895 return NS_OK;
896}
897
898NS_IMETHODIMPnsresult
899StopDetector::GetStatus(nsresult* aStatus) {
900 *aStatus = NS_OK;
901 return NS_OK;
902}
903
904NS_IMETHODIMPnsresult StopDetector::SetCanceledReason(const nsACString& aReason) {
905 return SetCanceledReasonImpl(aReason);
906}
907
908NS_IMETHODIMPnsresult StopDetector::GetCanceledReason(nsACString& aReason) {
909 return GetCanceledReasonImpl(aReason);
910}
911
912NS_IMETHODIMPnsresult StopDetector::CancelWithReason(nsresult aStatus,
913 const nsACString& aReason) {
914 return CancelWithReasonImpl(aStatus, aReason);
915}
916
917NS_IMETHODIMPnsresult
918StopDetector::Cancel(nsresult aStatus) {
919 mCanceled = true;
920 return NS_OK;
921}
922
923NS_IMETHODIMPnsresult
924StopDetector::Suspend(void) { return NS_OK; }
925NS_IMETHODIMPnsresult
926StopDetector::Resume(void) { return NS_OK; }
927
928NS_IMETHODIMPnsresult
929StopDetector::GetLoadGroup(nsILoadGroup** aLoadGroup) {
930 *aLoadGroup = nullptr;
931 return NS_OK;
932}
933
934NS_IMETHODIMPnsresult
935StopDetector::SetLoadGroup(nsILoadGroup* aLoadGroup) { return NS_OK; }
936
937NS_IMETHODIMPnsresult
938StopDetector::GetLoadFlags(nsLoadFlags* aLoadFlags) {
939 *aLoadFlags = nsIRequest::LOAD_NORMAL;
940 return NS_OK;
941}
942
943NS_IMETHODIMPnsresult
944StopDetector::GetTRRMode(nsIRequest::TRRMode* aTRRMode) {
945 return GetTRRModeImpl(aTRRMode);
946}
947
948NS_IMETHODIMPnsresult
949StopDetector::SetTRRMode(nsIRequest::TRRMode aTRRMode) {
950 return SetTRRModeImpl(aTRRMode);
951}
952
953NS_IMETHODIMPnsresult
954StopDetector::SetLoadFlags(nsLoadFlags aLoadFlags) { return NS_OK; }
955
956bool nsDocShell::MaybeHandleSubframeHistory(
957 nsDocShellLoadState* aLoadState, bool aContinueHandlingSubframeHistory) {
958 // First, verify if this is a subframe.
959 // Note, it is ok to rely on docshell here and not browsing context since when
960 // an iframe is created, it has first in-process docshell.
961 nsCOMPtr<nsIDocShellTreeItem> parentAsItem;
962 GetInProcessSameTypeParent(getter_AddRefs(parentAsItem));
963 nsCOMPtr<nsIDocShell> parentDS(do_QueryInterface(parentAsItem));
964
965 if (!parentDS || parentDS == static_cast<nsIDocShell*>(this)) {
966 if (mBrowsingContext && mBrowsingContext->IsTop()) {
967 // This is the root docshell. If we got here while
968 // executing an onLoad Handler,this load will not go
969 // into session history.
970 // XXX Why is this code in a method which deals with iframes!
971 if (aLoadState->IsFormSubmission()) {
972#ifdef DEBUG1
973 if (!mEODForCurrentDocument) {
974 const MaybeDiscarded<BrowsingContext>& targetBC =
975 aLoadState->TargetBrowsingContext();
976 MOZ_ASSERT_IF(GetBrowsingContext() == targetBC.get(),do { if (GetBrowsingContext() == targetBC.get()) { do { static_assert
( mozilla::detail::AssertionConditionType<decltype(aLoadState
->LoadType() == LOAD_NORMAL_REPLACE)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aLoadState->LoadType() ==
LOAD_NORMAL_REPLACE))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("aLoadState->LoadType() == LOAD_NORMAL_REPLACE", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 977); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->LoadType() == LOAD_NORMAL_REPLACE"
")"); do { *((volatile int*)__null) = 977; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
977 aLoadState->LoadType() == LOAD_NORMAL_REPLACE)do { if (GetBrowsingContext() == targetBC.get()) { do { static_assert
( mozilla::detail::AssertionConditionType<decltype(aLoadState
->LoadType() == LOAD_NORMAL_REPLACE)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aLoadState->LoadType() ==
LOAD_NORMAL_REPLACE))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("aLoadState->LoadType() == LOAD_NORMAL_REPLACE", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 977); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->LoadType() == LOAD_NORMAL_REPLACE"
")"); do { *((volatile int*)__null) = 977; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
978 }
979#endif
980 } else {
981 bool inOnLoadHandler = false;
982 GetIsExecutingOnLoadHandler(&inOnLoadHandler);
983 if (inOnLoadHandler) {
984 aLoadState->SetLoadType(LOAD_NORMAL_REPLACE);
985 }
986 }
987 }
988 return false;
989 }
990
991 /* OK. It is a subframe. Checkout the parent's loadtype. If the parent was
992 * loaded through a history mechanism, then get the SH entry for the child
993 * from the parent. This is done to restore frameset navigation while going
994 * back/forward. If the parent was loaded through any other loadType, set the
995 * child's loadType too accordingly, so that session history does not get
996 * confused.
997 */
998
999 // Get the parent's load type
1000 uint32_t parentLoadType;
1001 parentDS->GetLoadType(&parentLoadType);
1002
1003 if (!aContinueHandlingSubframeHistory) {
1004 if (mozilla::SessionHistoryInParent()) {
1005 if (nsDocShell::Cast(parentDS.get())->IsLoadingFromSessionHistory() &&
1006 !GetCreatedDynamically()) {
1007 if (XRE_IsContentProcess()) {
1008 dom::ContentChild* contentChild = dom::ContentChild::GetSingleton();
1009 nsCOMPtr<nsILoadGroup> loadGroup;
1010 GetLoadGroup(getter_AddRefs(loadGroup));
1011 if (contentChild && loadGroup && !mCheckingSessionHistory) {
1012 RefPtr<Document> parentDoc = parentDS->GetDocument();
1013 parentDoc->BlockOnload();
1014 RefPtr<BrowsingContext> browsingContext = mBrowsingContext;
1015 Maybe<uint64_t> currentLoadIdentifier =
1016 mBrowsingContext->GetCurrentLoadIdentifier();
1017 RefPtr<nsDocShellLoadState> loadState = aLoadState;
1018 bool isNavigating = mIsNavigating;
1019 RefPtr<StopDetector> stopDetector = new StopDetector();
1020 loadGroup->AddRequest(stopDetector, nullptr);
1021 // Need to set mCheckingSessionHistory so that
1022 // GetIsAttemptingToNavigate() returns true.
1023 mCheckingSessionHistory = true;
1024
1025 auto resolve =
1026 [currentLoadIdentifier, browsingContext, parentDoc, loadState,
1027 isNavigating, loadGroup, stopDetector](
1028 mozilla::Maybe<LoadingSessionHistoryInfo>&& aResult) {
1029 RefPtr<nsDocShell> docShell =
1030 static_cast<nsDocShell*>(browsingContext->GetDocShell());
1031 auto unblockParent = MakeScopeExit(
1032 [loadGroup, stopDetector, parentDoc, docShell]() {
1033 if (docShell) {
1034 docShell->mCheckingSessionHistory = false;
1035 }
1036 loadGroup->RemoveRequest(stopDetector, nullptr, NS_OK);
1037 parentDoc->UnblockOnload(false);
1038 });
1039
1040 if (!docShell || !docShell->mCheckingSessionHistory) {
1041 return;
1042 }
1043
1044 if (stopDetector->Canceled()) {
1045 return;
1046 }
1047 if (currentLoadIdentifier ==
1048 browsingContext->GetCurrentLoadIdentifier() &&
1049 aResult.isSome()) {
1050 loadState->SetLoadingSessionHistoryInfo(aResult.value());
1051 // This is an initial subframe load from the session
1052 // history, index doesn't need to be updated.
1053 loadState->SetLoadIsFromSessionHistory(0, false);
1054 }
1055
1056 // We got the results back from the parent process, call
1057 // LoadURI again with the possibly updated data.
1058 docShell->LoadURI(loadState, isNavigating, true);
1059 };
1060 auto reject = [loadGroup, stopDetector, browsingContext,
1061 parentDoc](mozilla::ipc::ResponseRejectReason) {
1062 RefPtr<nsDocShell> docShell =
1063 static_cast<nsDocShell*>(browsingContext->GetDocShell());
1064 if (docShell) {
1065 docShell->mCheckingSessionHistory = false;
1066 }
1067 // In practise reject shouldn't be called ever.
1068 loadGroup->RemoveRequest(stopDetector, nullptr, NS_OK);
1069 parentDoc->UnblockOnload(false);
1070 };
1071 contentChild->SendGetLoadingSessionHistoryInfoFromParent(
1072 mBrowsingContext, std::move(resolve), std::move(reject));
1073 return true;
1074 }
1075 } else {
1076 Maybe<LoadingSessionHistoryInfo> info;
1077 mBrowsingContext->Canonical()->GetLoadingSessionHistoryInfoFromParent(
1078 info);
1079 if (info.isSome()) {
1080 aLoadState->SetLoadingSessionHistoryInfo(info.value());
1081 // This is an initial subframe load from the session
1082 // history, index doesn't need to be updated.
1083 aLoadState->SetLoadIsFromSessionHistory(0, false);
1084 }
1085 }
1086 }
1087 } else {
1088 // Get the ShEntry for the child from the parent
1089 nsCOMPtr<nsISHEntry> currentSH;
1090 bool oshe = false;
1091 parentDS->GetCurrentSHEntry(getter_AddRefs(currentSH), &oshe);
1092 bool dynamicallyAddedChild = GetCreatedDynamically();
1093
1094 if (!dynamicallyAddedChild && !oshe && currentSH) {
1095 // Only use the old SHEntry, if we're sure enough that
1096 // it wasn't originally for some other frame.
1097 nsCOMPtr<nsISHEntry> shEntry;
1098 currentSH->GetChildSHEntryIfHasNoDynamicallyAddedChild(
1099 mBrowsingContext->ChildOffset(), getter_AddRefs(shEntry));
1100 if (shEntry) {
1101 aLoadState->SetSHEntry(shEntry);
1102 }
1103 }
1104 }
1105 }
1106
1107 // Make some decisions on the child frame's loadType based on the
1108 // parent's loadType, if the subframe hasn't loaded anything into it.
1109 //
1110 // In some cases privileged scripts may try to get the DOMWindow
1111 // reference of this docshell before the loading starts, causing the
1112 // initial about:blank content viewer being created and mCurrentURI being
1113 // set. To handle this case we check if mCurrentURI is about:blank and
1114 // currentSHEntry is null.
1115 bool oshe = false;
1116 nsCOMPtr<nsISHEntry> currentChildEntry;
1117 GetCurrentSHEntry(getter_AddRefs(currentChildEntry), &oshe);
1118
1119 if (mCurrentURI && (!NS_IsAboutBlank(mCurrentURI) || currentChildEntry ||
1120 mLoadingEntry || mActiveEntry)) {
1121 // This is a pre-existing subframe. If
1122 // 1. The load of this frame was not originally initiated by session
1123 // history directly (i.e. (!shEntry) condition succeeded, but it can
1124 // still be a history load on parent which causes this frame being
1125 // loaded), which we checked with the above assert, and
1126 // 2. mCurrentURI is not null, nor the initial about:blank,
1127 // it is possible that a parent's onLoadHandler or even self's
1128 // onLoadHandler is loading a new page in this child. Check parent's and
1129 // self's busy flag and if it is set, we don't want this onLoadHandler
1130 // load to get in to session history.
1131 BusyFlags parentBusy = parentDS->GetBusyFlags();
1132 BusyFlags selfBusy = GetBusyFlags();
1133
1134 if (parentBusy & BUSY_FLAGS_BUSY || selfBusy & BUSY_FLAGS_BUSY) {
1135 aLoadState->SetLoadType(LOAD_NORMAL_REPLACE);
1136 aLoadState->ClearLoadIsFromSessionHistory();
1137 }
1138 return false;
1139 }
1140
1141 // This is a newly created frame. Check for exception cases first.
1142 // By default the subframe will inherit the parent's loadType.
1143 if (aLoadState->LoadIsFromSessionHistory() &&
1144 (parentLoadType == LOAD_NORMAL || parentLoadType == LOAD_LINK)) {
1145 // The parent was loaded normally. In this case, this *brand new*
1146 // child really shouldn't have a SHEntry. If it does, it could be
1147 // because the parent is replacing an existing frame with a new frame,
1148 // in the onLoadHandler. We don't want this url to get into session
1149 // history. Clear off shEntry, and set load type to
1150 // LOAD_BYPASS_HISTORY.
1151 bool inOnLoadHandler = false;
1152 parentDS->GetIsExecutingOnLoadHandler(&inOnLoadHandler);
1153 if (inOnLoadHandler) {
1154 aLoadState->SetLoadType(LOAD_NORMAL_REPLACE);
1155 aLoadState->ClearLoadIsFromSessionHistory();
1156 }
1157 } else if (parentLoadType == LOAD_REFRESH) {
1158 // Clear shEntry. For refresh loads, we have to load
1159 // what comes through the pipe, not what's in history.
1160 aLoadState->ClearLoadIsFromSessionHistory();
1161 } else if ((parentLoadType == LOAD_BYPASS_HISTORY) ||
1162 (aLoadState->LoadIsFromSessionHistory() &&
1163 ((parentLoadType & LOAD_CMD_HISTORY) ||
1164 (parentLoadType == LOAD_RELOAD_NORMAL) ||
1165 (parentLoadType == LOAD_RELOAD_CHARSET_CHANGE) ||
1166 (parentLoadType == LOAD_RELOAD_CHARSET_CHANGE_BYPASS_CACHE) ||
1167 (parentLoadType ==
1168 LOAD_RELOAD_CHARSET_CHANGE_BYPASS_PROXY_AND_CACHE)))) {
1169 // If the parent url, bypassed history or was loaded from
1170 // history, pass on the parent's loadType to the new child
1171 // frame too, so that the child frame will also
1172 // avoid getting into history.
1173 aLoadState->SetLoadType(parentLoadType);
1174 } else if (parentLoadType == LOAD_ERROR_PAGE) {
1175 // If the parent document is an error page, we don't
1176 // want to update global/session history. However,
1177 // this child frame is not an error page.
1178 aLoadState->SetLoadType(LOAD_BYPASS_HISTORY);
1179 } else if ((parentLoadType == LOAD_RELOAD_BYPASS_CACHE) ||
1180 (parentLoadType == LOAD_RELOAD_BYPASS_PROXY) ||
1181 (parentLoadType == LOAD_RELOAD_BYPASS_PROXY_AND_CACHE)) {
1182 // the new frame should inherit the parent's load type so that it also
1183 // bypasses the cache and/or proxy
1184 aLoadState->SetLoadType(parentLoadType);
1185 }
1186
1187 return false;
1188}
1189
1190/*
1191 * Reset state to a new content model within the current document and the
1192 * document viewer. Called by the document before initiating an out of band
1193 * document.write().
1194 */
1195NS_IMETHODIMPnsresult
1196nsDocShell::PrepareForNewContentModel() {
1197 // Clear out our form control state, because the state of controls
1198 // in the pre-open() document should not affect the state of
1199 // controls that are now going to be written.
1200 SetLayoutHistoryState(nullptr);
1201 mEODForCurrentDocument = false;
1202 return NS_OK;
1203}
1204
1205NS_IMETHODIMPnsresult
1206nsDocShell::FirePageHideNotification(bool aIsUnload) {
1207 FirePageHideNotificationInternal(aIsUnload, false);
1208 return NS_OK;
1209}
1210
1211void nsDocShell::FirePageHideNotificationInternal(
1212 bool aIsUnload, bool aSkipCheckingDynEntries) {
1213 if (mDocumentViewer && !mFiredUnloadEvent) {
1214 // Keep an explicit reference since calling PageHide could release
1215 // mDocumentViewer
1216 nsCOMPtr<nsIDocumentViewer> viewer(mDocumentViewer);
1217 mFiredUnloadEvent = true;
1218
1219 if (mTiming) {
1220 mTiming->NotifyUnloadEventStart();
1221 }
1222
1223 viewer->PageHide(aIsUnload);
1224
1225 if (mTiming) {
1226 mTiming->NotifyUnloadEventEnd();
1227 }
1228
1229 AutoTArray<nsCOMPtr<nsIDocShell>, 8> kids;
1230 uint32_t n = mChildList.Length();
1231 kids.SetCapacity(n);
1232 for (uint32_t i = 0; i < n; i++) {
1233 kids.AppendElement(do_QueryInterface(ChildAt(i)));
1234 }
1235
1236 n = kids.Length();
1237 for (uint32_t i = 0; i < n; ++i) {
1238 RefPtr<nsDocShell> child = static_cast<nsDocShell*>(kids[i].get());
1239 if (child) {
1240 // Skip checking dynamic subframe entries in our children.
1241 child->FirePageHideNotificationInternal(aIsUnload, true);
1242 }
1243 }
1244
1245 // If the document is unloading, remove all dynamic subframe entries.
1246 if (aIsUnload && !aSkipCheckingDynEntries) {
1247 RefPtr<ChildSHistory> rootSH = GetRootSessionHistory();
1248 if (rootSH) {
1249 MOZ_LOG(do { const ::mozilla::LogModule* moz_real_module = gSHLog; if
((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "nsDocShell %p unloading, remove dynamic subframe entries"
, this); } } while (0)
1250 gSHLog, LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = gSHLog; if
((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "nsDocShell %p unloading, remove dynamic subframe entries"
, this); } } while (0)
1251 ("nsDocShell %p unloading, remove dynamic subframe entries", this))do { const ::mozilla::LogModule* moz_real_module = gSHLog; if
((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "nsDocShell %p unloading, remove dynamic subframe entries"
, this); } } while (0)
;
1252 if (mozilla::SessionHistoryInParent()) {
1253 if (mActiveEntry) {
1254 mBrowsingContext->RemoveDynEntriesFromActiveSessionHistoryEntry();
1255 }
1256 MOZ_LOG(gSHLog, LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = gSHLog; if
((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "nsDocShell %p unloading, no active entries"
, this); } } while (0)
1257 ("nsDocShell %p unloading, no active entries", this))do { const ::mozilla::LogModule* moz_real_module = gSHLog; if
((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "nsDocShell %p unloading, no active entries"
, this); } } while (0)
;
1258 } else if (mOSHE) {
1259 int32_t index = rootSH->Index();
1260 rootSH->LegacySHistory()->RemoveDynEntries(index, mOSHE);
1261 }
1262 }
1263 }
1264
1265 // Now make sure our editor, if any, is detached before we go
1266 // any farther.
1267 DetachEditorFromWindow();
1268 }
1269}
1270
1271void nsDocShell::ThawFreezeNonRecursive(bool aThaw) {
1272 MOZ_ASSERT(mozilla::BFCacheInParent())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mozilla::BFCacheInParent())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mozilla::BFCacheInParent()))
), 0))) { do { } while (false); MOZ_ReportAssertionFailure("mozilla::BFCacheInParent()"
, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 1272); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mozilla::BFCacheInParent()"
")"); do { *((volatile int*)__null) = 1272; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1273
1274 if (!mScriptGlobal) {
1275 return;
1276 }
1277
1278 if (RefPtr<nsGlobalWindowInner> inner =
1279 nsGlobalWindowInner::Cast(mScriptGlobal->GetCurrentInnerWindow())) {
1280 if (aThaw) {
1281 inner->Thaw(false);
1282 } else {
1283 inner->Freeze(false);
1284 }
1285 }
1286}
1287
1288void nsDocShell::FirePageHideShowNonRecursive(bool aShow) {
1289 MOZ_ASSERT(mozilla::BFCacheInParent())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mozilla::BFCacheInParent())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mozilla::BFCacheInParent()))
), 0))) { do { } while (false); MOZ_ReportAssertionFailure("mozilla::BFCacheInParent()"
, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 1289); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mozilla::BFCacheInParent()"
")"); do { *((volatile int*)__null) = 1289; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1290
1291 if (!mDocumentViewer) {
1292 return;
1293 }
1294
1295 // Emulate what non-SHIP BFCache does too. In pageshow case
1296 // add and remove a request and before that call SetCurrentURI to get
1297 // the location change notification.
1298 // For pagehide, set mFiredUnloadEvent to true, so that unload doesn't fire.
1299 nsCOMPtr<nsIDocumentViewer> viewer(mDocumentViewer);
1300 if (aShow) {
1301 viewer->SetIsHidden(false);
1302 mRefreshURIList = std::move(mBFCachedRefreshURIList);
1303 RefreshURIFromQueue();
1304 mFiredUnloadEvent = false;
1305 RefPtr<Document> doc = viewer->GetDocument();
1306 if (doc) {
1307 doc->NotifyActivityChanged();
1308 nsCOMPtr<nsPIDOMWindowInner> inner =
1309 mScriptGlobal ? mScriptGlobal->GetCurrentInnerWindow() : nullptr;
1310 if (mBrowsingContext->IsTop()) {
1311 doc->NotifyPossibleTitleChange(false);
1312 doc->SetLoadingOrRestoredFromBFCacheTimeStampToNow();
1313 if (inner) {
1314 // Now that we have found the inner window of the page restored
1315 // from the history, we have to make sure that
1316 // performance.navigation.type is 2.
1317 // Traditionally this type change has been done to the top level page
1318 // only.
1319 Performance* performance = inner->GetPerformance();
1320 if (performance) {
1321 performance->GetDOMTiming()->NotifyRestoreStart();
1322 }
1323 }
1324 }
1325
1326 nsCOMPtr<nsIChannel> channel = doc->GetChannel();
1327 if (channel) {
1328 SetLoadType(LOAD_HISTORY);
1329 mEODForCurrentDocument = false;
1330 mIsRestoringDocument = true;
1331 mLoadGroup->AddRequest(channel, nullptr);
1332 SetCurrentURI(doc->GetDocumentURI(), channel,
1333 /* aFireOnLocationChange */ true,
1334 /* aIsInitialAboutBlank */ false,
1335 /* aLocationFlags */ 0);
1336 mLoadGroup->RemoveRequest(channel, nullptr, NS_OK);
1337 mIsRestoringDocument = false;
1338 }
1339 RefPtr<PresShell> presShell = GetPresShell();
1340 if (presShell) {
1341 presShell->Thaw(false);
1342 }
1343
1344 if (inner) {
1345 inner->FireDelayedDOMEvents(false);
1346 }
1347 }
1348 } else if (!mFiredUnloadEvent) {
1349 // XXXBFCache check again that the page can enter bfcache.
1350 // XXXBFCache should mTiming->NotifyUnloadEventStart()/End() be called here?
1351
1352 if (mRefreshURIList) {
1353 RefreshURIToQueue();
1354 mBFCachedRefreshURIList = std::move(mRefreshURIList);
1355 } else {
1356 // If Stop was called, the list was moved to mSavedRefreshURIList after
1357 // calling SuspendRefreshURIs, which calls RefreshURIToQueue.
1358 mBFCachedRefreshURIList = std::move(mSavedRefreshURIList);
1359 }
1360
1361 mFiredUnloadEvent = true;
1362 viewer->PageHide(false);
1363
1364 RefPtr<PresShell> presShell = GetPresShell();
1365 if (presShell) {
1366 presShell->Freeze(false);
1367 }
1368 }
1369}
1370
1371nsresult nsDocShell::Dispatch(already_AddRefed<nsIRunnable>&& aRunnable) {
1372 nsCOMPtr<nsIRunnable> runnable(aRunnable);
1373 if (NS_WARN_IF(!GetWindow())NS_warn_if_impl(!GetWindow(), "!GetWindow()", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 1373)
) {
1374 // Window should only be unavailable after destroyed.
1375 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"
, 1375); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mIsBeingDestroyed"
")"); do { *((volatile int*)__null) = 1375; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1376 return NS_ERROR_FAILURE;
1377 }
1378 return SchedulerGroup::Dispatch(runnable.forget());
1379}
1380
1381NS_IMETHODIMPnsresult
1382nsDocShell::DispatchLocationChangeEvent() {
1383 return Dispatch(NewRunnableMethod("nsDocShell::FireDummyOnLocationChange",
1384 this,
1385 &nsDocShell::FireDummyOnLocationChange));
1386}
1387
1388NS_IMETHODIMPnsresult
1389nsDocShell::StartDelayedAutoplayMediaComponents() {
1390 RefPtr<nsPIDOMWindowOuter> outerWindow = GetWindow();
1391 if (outerWindow) {
1392 outerWindow->ActivateMediaComponents();
1393 }
1394 return NS_OK;
1395}
1396
1397bool nsDocShell::MaybeInitTiming() {
1398 if (mTiming && !mBlankTiming) {
1399 return false;
1400 }
1401
1402 bool canBeReset = false;
1403
1404 if (mScriptGlobal && mBlankTiming) {
1405 nsPIDOMWindowInner* innerWin = mScriptGlobal->GetCurrentInnerWindow();
1406 if (innerWin && innerWin->GetPerformance()) {
1407 mTiming = innerWin->GetPerformance()->GetDOMTiming();
1408 mBlankTiming = false;
1409 }
1410 }
1411
1412 if (!mTiming) {
1413 mTiming = new nsDOMNavigationTiming(this);
1414 canBeReset = true;
1415 }
1416
1417 mTiming->NotifyNavigationStart(
1418 mBrowsingContext->IsActive()
1419 ? nsDOMNavigationTiming::DocShellState::eActive
1420 : nsDOMNavigationTiming::DocShellState::eInactive);
1421
1422 return canBeReset;
1423}
1424
1425void nsDocShell::MaybeResetInitTiming(bool aReset) {
1426 if (aReset) {
1427 mTiming = nullptr;
1428 }
1429}
1430
1431nsDOMNavigationTiming* nsDocShell::GetNavigationTiming() const {
1432 return mTiming;
1433}
1434
1435nsPresContext* nsDocShell::GetEldestPresContext() {
1436 nsIDocumentViewer* viewer = mDocumentViewer;
1437 while (viewer) {
1438 nsIDocumentViewer* prevViewer = viewer->GetPreviousViewer();
1439 if (!prevViewer) {
1440 return viewer->GetPresContext();
1441 }
1442 viewer = prevViewer;
1443 }
1444
1445 return nullptr;
1446}
1447
1448nsPresContext* nsDocShell::GetPresContext() {
1449 if (!mDocumentViewer) {
1450 return nullptr;
1451 }
1452
1453 return mDocumentViewer->GetPresContext();
1454}
1455
1456PresShell* nsDocShell::GetPresShell() {
1457 nsPresContext* presContext = GetPresContext();
1458 return presContext ? presContext->GetPresShell() : nullptr;
1459}
1460
1461PresShell* nsDocShell::GetEldestPresShell() {
1462 nsPresContext* presContext = GetEldestPresContext();
1463
1464 if (presContext) {
1465 return presContext->GetPresShell();
1466 }
1467
1468 return nullptr;
1469}
1470
1471NS_IMETHODIMPnsresult
1472nsDocShell::GetDocViewer(nsIDocumentViewer** aDocumentViewer) {
1473 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"
, 1473); return NS_ERROR_INVALID_POINTER; } } while (false)
;
1474
1475 *aDocumentViewer = mDocumentViewer;
1476 NS_IF_ADDREF(*aDocumentViewer)ns_if_addref(*aDocumentViewer);
1477 return NS_OK;
1478}
1479
1480NS_IMETHODIMPnsresult
1481nsDocShell::GetOuterWindowID(uint64_t* aWindowID) {
1482 *aWindowID = mContentWindowID;
1483 return NS_OK;
1484}
1485
1486NS_IMETHODIMPnsresult
1487nsDocShell::SetChromeEventHandler(EventTarget* aChromeEventHandler) {
1488 mChromeEventHandler = aChromeEventHandler;
1489
1490 if (mScriptGlobal) {
1491 mScriptGlobal->SetChromeEventHandler(mChromeEventHandler);
1492 }
1493
1494 return NS_OK;
1495}
1496
1497NS_IMETHODIMPnsresult
1498nsDocShell::GetChromeEventHandler(EventTarget** aChromeEventHandler) {
1499 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"
, 1499); return NS_ERROR_INVALID_POINTER; } } while (false)
;
1500 RefPtr<EventTarget> handler = mChromeEventHandler;
1501 handler.forget(aChromeEventHandler);
1502 return NS_OK;
1503}
1504
1505NS_IMETHODIMPnsresult
1506nsDocShell::SetCurrentURIForSessionStore(nsIURI* aURI) {
1507 // Note that securityUI will set STATE_IS_INSECURE, even if
1508 // the scheme of |aURI| is "https".
1509 SetCurrentURI(aURI, nullptr,
1510 /* aFireOnLocationChange */
1511 true,
1512 /* aIsInitialAboutBlank */
1513 false,
1514 /* aLocationFlags */
1515 nsIWebProgressListener::LOCATION_CHANGE_SESSION_STORE);
1516 return NS_OK;
1517}
1518
1519bool nsDocShell::SetCurrentURI(nsIURI* aURI, nsIRequest* aRequest,
1520 bool aFireOnLocationChange,
1521 bool aIsInitialAboutBlank,
1522 uint32_t aLocationFlags) {
1523 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"
, 1523); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mIsBeingDestroyed"
")"); do { *((volatile int*)__null) = 1523; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1524
1525 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)
1526 ("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)
1527 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)
;
1528
1529 // We don't want to send a location change when we're displaying an error
1530 // page, and we don't want to change our idea of "current URI" either
1531 if (mLoadType == LOAD_ERROR_PAGE) {
1532 return false;
1533 }
1534
1535 bool uriIsEqual = false;
1536 if (!mCurrentURI || !aURI ||
1537 NS_FAILED(mCurrentURI->Equals(aURI, &uriIsEqual))((bool)(__builtin_expect(!!(NS_FAILED_impl(mCurrentURI->Equals
(aURI, &uriIsEqual))), 0)))
|| !uriIsEqual) {
1538 mTitleValidForCurrentURI = false;
1539 }
1540
1541 SetCurrentURIInternal(aURI);
1542
1543#ifdef DEBUG1
1544 mLastOpenedURI = aURI;
1545#endif
1546
1547 if (!NS_IsAboutBlank(mCurrentURI)) {
1548 mHasLoadedNonBlankURI = true;
1549 }
1550
1551 // Don't fire onLocationChange when creating a subframe's initial about:blank
1552 // document, as this can happen when it's not safe for us to run script.
1553 if (aIsInitialAboutBlank && !mHasLoadedNonBlankURI &&
1554 !mBrowsingContext->IsTop()) {
1555 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"
, 1555); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aRequest && aLocationFlags == 0"
")"); do { *((volatile int*)__null) = 1555; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1556 return false;
1557 }
1558
1559 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"
, 1559); AnnotateMozCrashReason("MOZ_ASSERT" "(" "nsContentUtils::IsSafeToRunScript()"
")"); do { *((volatile int*)__null) = 1559; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1560
1561 if (aFireOnLocationChange) {
1562 FireOnLocationChange(this, aRequest, aURI, aLocationFlags);
1563 }
1564 return !aFireOnLocationChange;
1565}
1566
1567void nsDocShell::SetCurrentURIInternal(nsIURI* aURI) {
1568 mCurrentURI = aURI;
1569 if (mBrowsingContext) {
1570 mBrowsingContext->ClearCachedValuesOfLocations();
1571 }
1572}
1573
1574NS_IMETHODIMPnsresult
1575nsDocShell::GetCharset(nsACString& aCharset) {
1576 aCharset.Truncate();
1577
1578 PresShell* presShell = GetPresShell();
1579 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"
, 1579); return NS_ERROR_FAILURE; } } while (false)
;
1580 Document* doc = presShell->GetDocument();
1581 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"
, 1581); return NS_ERROR_FAILURE; } } while (false)
;
1582 doc->GetDocumentCharacterSet()->Name(aCharset);
1583 return NS_OK;
1584}
1585
1586NS_IMETHODIMPnsresult
1587nsDocShell::ForceEncodingDetection() {
1588 nsCOMPtr<nsIDocumentViewer> viewer;
1589 GetDocViewer(getter_AddRefs(viewer));
1590 if (!viewer) {
1591 return NS_OK;
1592 }
1593
1594 Document* doc = viewer->GetDocument();
1595 if (!doc || doc->WillIgnoreCharsetOverride()) {
1596 return NS_OK;
1597 }
1598
1599 mForcedAutodetection = true;
1600
1601 nsIURI* url = doc->GetOriginalURI();
1602 bool isFileURL = url && SchemeIsFile(url);
1603
1604 int32_t charsetSource = doc->GetDocumentCharacterSetSource();
1605 auto encoding = doc->GetDocumentCharacterSet();
1606 // AsHTMLDocument is valid, because we called
1607 // WillIgnoreCharsetOverride() above.
1608 if (doc->AsHTMLDocument()->IsPlainText()) {
1609 switch (charsetSource) {
1610 case kCharsetFromInitialAutoDetectionASCII:
1611 // Deliberately no final version
1612 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)
;
1613 Telemetry::AccumulateCategorical(
1614 Telemetry::LABELS_ENCODING_OVERRIDE_SITUATION_TEXT::UnlabeledAscii);
1615 break;
1616 case kCharsetFromInitialAutoDetectionWouldNotHaveBeenUTF8Generic:
1617 case kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8Generic:
1618 case kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8GenericInitialWasASCII:
1619 case kCharsetFromInitialAutoDetectionWouldNotHaveBeenUTF8Content:
1620 case kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8Content:
1621 case kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8ContentInitialWasASCII:
1622 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)
;
1623 Telemetry::AccumulateCategorical(
1624 Telemetry::LABELS_ENCODING_OVERRIDE_SITUATION_TEXT::
1625 UnlabeledNonUtf8);
1626 break;
1627 case kCharsetFromInitialAutoDetectionWouldNotHaveBeenUTF8DependedOnTLD:
1628 case kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8DependedOnTLD:
1629 case kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8DependedOnTLDInitialWasASCII:
1630 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)
;
1631 Telemetry::AccumulateCategorical(
1632 Telemetry::LABELS_ENCODING_OVERRIDE_SITUATION_TEXT::
1633 UnlabeledNonUtf8TLD);
1634 break;
1635 case kCharsetFromInitialAutoDetectionWouldHaveBeenUTF8:
1636 case kCharsetFromFinalAutoDetectionWouldHaveBeenUTF8InitialWasASCII:
1637 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)
;
1638 Telemetry::AccumulateCategorical(
1639 Telemetry::LABELS_ENCODING_OVERRIDE_SITUATION_TEXT::UnlabeledUtf8);
1640 break;
1641 case kCharsetFromChannel:
1642 if (encoding == UTF_8_ENCODING) {
1643 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)
;
1644 Telemetry::AccumulateCategorical(
1645 Telemetry::LABELS_ENCODING_OVERRIDE_SITUATION_TEXT::ChannelUtf8);
1646 } else {
1647 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)
;
1648 Telemetry::AccumulateCategorical(
1649 Telemetry::LABELS_ENCODING_OVERRIDE_SITUATION_TEXT::
1650 ChannelNonUtf8);
1651 }
1652 break;
1653 default:
1654 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)
;
1655 Telemetry::AccumulateCategorical(
1656 Telemetry::LABELS_ENCODING_OVERRIDE_SITUATION_TEXT::Bug);
1657 break;
1658 }
1659 } else {
1660 switch (charsetSource) {
1661 case kCharsetFromInitialAutoDetectionASCII:
1662 // Deliberately no final version
1663 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)
;
1664 Telemetry::AccumulateCategorical(
1665 Telemetry::LABELS_ENCODING_OVERRIDE_SITUATION_HTML::UnlabeledAscii);
1666 break;
1667 case kCharsetFromInitialAutoDetectionWouldNotHaveBeenUTF8Generic:
1668 case kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8Generic:
1669 case kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8GenericInitialWasASCII:
1670 case kCharsetFromInitialAutoDetectionWouldNotHaveBeenUTF8Content:
1671 case kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8Content:
1672 case kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8ContentInitialWasASCII:
1673 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)
;
1674 Telemetry::AccumulateCategorical(
1675 Telemetry::LABELS_ENCODING_OVERRIDE_SITUATION_HTML::
1676 UnlabeledNonUtf8);
1677 break;
1678 case kCharsetFromInitialAutoDetectionWouldNotHaveBeenUTF8DependedOnTLD:
1679 case kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8DependedOnTLD:
1680 case kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8DependedOnTLDInitialWasASCII:
1681 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)
;
1682 Telemetry::AccumulateCategorical(
1683 Telemetry::LABELS_ENCODING_OVERRIDE_SITUATION_HTML::
1684 UnlabeledNonUtf8TLD);
1685 break;
1686 case kCharsetFromInitialAutoDetectionWouldHaveBeenUTF8:
1687 case kCharsetFromFinalAutoDetectionWouldHaveBeenUTF8InitialWasASCII:
1688 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)
;
1689 Telemetry::AccumulateCategorical(
1690 Telemetry::LABELS_ENCODING_OVERRIDE_SITUATION_HTML::UnlabeledUtf8);
1691 break;
1692 case kCharsetFromChannel:
1693 if (encoding == UTF_8_ENCODING) {
1694 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)
;
1695 Telemetry::AccumulateCategorical(
1696 Telemetry::LABELS_ENCODING_OVERRIDE_SITUATION_HTML::ChannelUtf8);
1697 } else {
1698 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)
;
1699 Telemetry::AccumulateCategorical(
1700 Telemetry::LABELS_ENCODING_OVERRIDE_SITUATION_HTML::
1701 ChannelNonUtf8);
1702 }
1703 break;
1704 case kCharsetFromXmlDeclaration:
1705 case kCharsetFromMetaTag:
1706 if (isFileURL) {
1707 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)
;
1708 Telemetry::AccumulateCategorical(
1709 Telemetry::LABELS_ENCODING_OVERRIDE_SITUATION_HTML::LocalLabeled);
1710 } else if (encoding == UTF_8_ENCODING) {
1711 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)
;
1712 Telemetry::AccumulateCategorical(
1713 Telemetry::LABELS_ENCODING_OVERRIDE_SITUATION_HTML::InternalUtf8);
1714 } else {
1715 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)
;
1716 Telemetry::AccumulateCategorical(
1717 Telemetry::LABELS_ENCODING_OVERRIDE_SITUATION_HTML::
1718 InternalNonUtf8);
1719 }
1720 break;
1721 default:
1722 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)
;
1723 Telemetry::AccumulateCategorical(
1724 Telemetry::LABELS_ENCODING_OVERRIDE_SITUATION_HTML::Bug);
1725 break;
1726 }
1727 }
1728 return NS_OK;
1729}
1730
1731void nsDocShell::SetParentCharset(const Encoding*& aCharset,
1732 int32_t aCharsetSource,
1733 nsIPrincipal* aPrincipal) {
1734 mParentCharset = aCharset;
1735 mParentCharsetSource = aCharsetSource;
1736 mParentCharsetPrincipal = aPrincipal;
1737}
1738
1739void nsDocShell::GetParentCharset(const Encoding*& aCharset,
1740 int32_t* aCharsetSource,
1741 nsIPrincipal** aPrincipal) {
1742 aCharset = mParentCharset;
1743 *aCharsetSource = mParentCharsetSource;
1744 NS_IF_ADDREF(*aPrincipal = mParentCharsetPrincipal)ns_if_addref(*aPrincipal = mParentCharsetPrincipal);
1745}
1746
1747NS_IMETHODIMPnsresult
1748nsDocShell::GetHasTrackingContentBlocked(Promise** aPromise) {
1749 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"
, 1749); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPromise" ")"
); do { *((volatile int*)__null) = 1749; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1750
1751 ErrorResult rv;
1752 RefPtr<Document> doc(GetDocument());
1753 RefPtr<Promise> retPromise = Promise::Create(doc->GetOwnerGlobal(), rv);
1754 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"
, 1754)
) {
1755 return rv.StealNSResult();
1756 }
1757
1758 // Retrieve the document's content blocking events from the parent process.
1759 RefPtr<Document::GetContentBlockingEventsPromise> promise =
1760 doc->GetContentBlockingEvents();
1761 if (promise) {
1762 promise->Then(
1763 GetCurrentSerialEventTarget(), __func__,
1764 [retPromise](const Document::GetContentBlockingEventsPromise::
1765 ResolveOrRejectValue& aValue) {
1766 if (aValue.IsResolve()) {
1767 bool has = aValue.ResolveValue() &
1768 nsIWebProgressListener::STATE_BLOCKED_TRACKING_CONTENT;
1769 retPromise->MaybeResolve(has);
1770 } else {
1771 retPromise->MaybeResolve(false);
1772 }
1773 });
1774 } else {
1775 retPromise->MaybeResolve(false);
1776 }
1777
1778 retPromise.forget(aPromise);
1779 return NS_OK;
1780}
1781
1782NS_IMETHODIMPnsresult
1783nsDocShell::GetCssErrorReportingEnabled(bool* aEnabled) {
1784 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"
, 1784); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aEnabled" ")"
); do { *((volatile int*)__null) = 1784; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1785 *aEnabled = mCSSErrorReportingEnabled;
1786 return NS_OK;
1787}
1788
1789NS_IMETHODIMPnsresult
1790nsDocShell::SetCssErrorReportingEnabled(bool aEnabled) {
1791 mCSSErrorReportingEnabled = aEnabled;
1792 return NS_OK;
1793}
1794
1795NS_IMETHODIMPnsresult
1796nsDocShell::GetUsePrivateBrowsing(bool* aUsePrivateBrowsing) {
1797 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"
, 1797); return NS_ERROR_INVALID_POINTER; } } while (false)
;
1798 return mBrowsingContext->GetUsePrivateBrowsing(aUsePrivateBrowsing);
1799}
1800
1801void nsDocShell::NotifyPrivateBrowsingChanged() {
1802 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"
, 1802); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mIsBeingDestroyed"
")"); do { *((volatile int*)__null) = 1802; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1803
1804 nsTObserverArray<nsWeakPtr>::ForwardIterator iter(mPrivacyObservers);
1805 while (iter.HasMore()) {
1806 nsWeakPtr ref = iter.GetNext();
1807 nsCOMPtr<nsIPrivacyTransitionObserver> obs = do_QueryReferent(ref);
1808 if (!obs) {
1809 iter.Remove();
1810 } else {
1811 obs->PrivateModeChanged(UsePrivateBrowsing());
1812 }
1813 }
1814}
1815
1816NS_IMETHODIMPnsresult
1817nsDocShell::SetUsePrivateBrowsing(bool aUsePrivateBrowsing) {
1818 return mBrowsingContext->SetUsePrivateBrowsing(aUsePrivateBrowsing);
1819}
1820
1821NS_IMETHODIMPnsresult
1822nsDocShell::SetPrivateBrowsing(bool aUsePrivateBrowsing) {
1823 return mBrowsingContext->SetPrivateBrowsing(aUsePrivateBrowsing);
1824}
1825
1826NS_IMETHODIMPnsresult
1827nsDocShell::GetHasLoadedNonBlankURI(bool* aResult) {
1828 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"
, 1828); return NS_ERROR_INVALID_POINTER; } } while (false)
;
1829
1830 *aResult = mHasLoadedNonBlankURI;
1831 return NS_OK;
1832}
1833
1834NS_IMETHODIMPnsresult
1835nsDocShell::GetUseRemoteTabs(bool* aUseRemoteTabs) {
1836 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"
, 1836); return NS_ERROR_INVALID_POINTER; } } while (false)
;
1837 return mBrowsingContext->GetUseRemoteTabs(aUseRemoteTabs);
1838}
1839
1840NS_IMETHODIMPnsresult
1841nsDocShell::SetRemoteTabs(bool aUseRemoteTabs) {
1842 return mBrowsingContext->SetRemoteTabs(aUseRemoteTabs);
1843}
1844
1845NS_IMETHODIMPnsresult
1846nsDocShell::GetUseRemoteSubframes(bool* aUseRemoteSubframes) {
1847 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"
, 1847); return NS_ERROR_INVALID_POINTER; } } while (false)
;
1848 return mBrowsingContext->GetUseRemoteSubframes(aUseRemoteSubframes);
1849}
1850
1851NS_IMETHODIMPnsresult
1852nsDocShell::SetRemoteSubframes(bool aUseRemoteSubframes) {
1853 return mBrowsingContext->SetRemoteSubframes(aUseRemoteSubframes);
1854}
1855
1856NS_IMETHODIMPnsresult
1857nsDocShell::AddWeakPrivacyTransitionObserver(
1858 nsIPrivacyTransitionObserver* aObserver) {
1859 nsWeakPtr weakObs = do_GetWeakReference(aObserver);
1860 if (!weakObs) {
1861 return NS_ERROR_NOT_AVAILABLE;
1862 }
1863 mPrivacyObservers.AppendElement(weakObs);
1864 return NS_OK;
1865}
1866
1867NS_IMETHODIMPnsresult
1868nsDocShell::AddWeakReflowObserver(nsIReflowObserver* aObserver) {
1869 nsWeakPtr weakObs = do_GetWeakReference(aObserver);
1870 if (!weakObs) {
1871 return NS_ERROR_FAILURE;
1872 }
1873 mReflowObservers.AppendElement(weakObs);
1874 return NS_OK;
1875}
1876
1877NS_IMETHODIMPnsresult
1878nsDocShell::RemoveWeakReflowObserver(nsIReflowObserver* aObserver) {
1879 nsWeakPtr obs = do_GetWeakReference(aObserver);
1880 return mReflowObservers.RemoveElement(obs) ? NS_OK : NS_ERROR_FAILURE;
1881}
1882
1883NS_IMETHODIMPnsresult
1884nsDocShell::NotifyReflowObservers(bool aInterruptible,
1885 DOMHighResTimeStamp aStart,
1886 DOMHighResTimeStamp aEnd) {
1887 nsTObserverArray<nsWeakPtr>::ForwardIterator iter(mReflowObservers);
1888 while (iter.HasMore()) {
1889 nsWeakPtr ref = iter.GetNext();
1890 nsCOMPtr<nsIReflowObserver> obs = do_QueryReferent(ref);
1891 if (!obs) {
1892 iter.Remove();
1893 } else if (aInterruptible) {
1894 obs->ReflowInterruptible(aStart, aEnd);
1895 } else {
1896 obs->Reflow(aStart, aEnd);
1897 }
1898 }
1899 return NS_OK;
1900}
1901
1902NS_IMETHODIMPnsresult
1903nsDocShell::GetAllowMetaRedirects(bool* aReturn) {
1904 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"
, 1904); return NS_ERROR_INVALID_POINTER; } } while (false)
;
1905
1906 *aReturn = mAllowMetaRedirects;
1907 return NS_OK;
1908}
1909
1910NS_IMETHODIMPnsresult
1911nsDocShell::SetAllowMetaRedirects(bool aValue) {
1912 mAllowMetaRedirects = aValue;
1913 return NS_OK;
1914}
1915
1916NS_IMETHODIMPnsresult
1917nsDocShell::GetAllowSubframes(bool* aAllowSubframes) {
1918 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"
, 1918); return NS_ERROR_INVALID_POINTER; } } while (false)
;
1919
1920 *aAllowSubframes = mAllowSubframes;
1921 return NS_OK;
1922}
1923
1924NS_IMETHODIMPnsresult
1925nsDocShell::SetAllowSubframes(bool aAllowSubframes) {
1926 mAllowSubframes = aAllowSubframes;
1927 return NS_OK;
1928}
1929
1930NS_IMETHODIMPnsresult
1931nsDocShell::GetAllowImages(bool* aAllowImages) {
1932 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"
, 1932); return NS_ERROR_INVALID_POINTER; } } while (false)
;
1933
1934 *aAllowImages = mAllowImages;
1935 return NS_OK;
1936}
1937
1938NS_IMETHODIMPnsresult
1939nsDocShell::SetAllowImages(bool aAllowImages) {
1940 mAllowImages = aAllowImages;
1941 return NS_OK;
1942}
1943
1944NS_IMETHODIMPnsresult
1945nsDocShell::GetAllowMedia(bool* aAllowMedia) {
1946 *aAllowMedia = mAllowMedia;
1947 return NS_OK;
1948}
1949
1950NS_IMETHODIMPnsresult
1951nsDocShell::SetAllowMedia(bool aAllowMedia) {
1952 mAllowMedia = aAllowMedia;
1953
1954 // Mute or unmute audio contexts attached to the inner window.
1955 if (mScriptGlobal) {
1956 if (nsPIDOMWindowInner* innerWin = mScriptGlobal->GetCurrentInnerWindow()) {
1957 if (aAllowMedia) {
1958 innerWin->UnmuteAudioContexts();
1959 } else {
1960 innerWin->MuteAudioContexts();
1961 }
1962 }
1963 }
1964
1965 return NS_OK;
1966}
1967
1968NS_IMETHODIMPnsresult
1969nsDocShell::GetAllowDNSPrefetch(bool* aAllowDNSPrefetch) {
1970 *aAllowDNSPrefetch = mAllowDNSPrefetch;
1971 return NS_OK;
1972}
1973
1974NS_IMETHODIMPnsresult
1975nsDocShell::SetAllowDNSPrefetch(bool aAllowDNSPrefetch) {
1976 mAllowDNSPrefetch = aAllowDNSPrefetch;
1977 return NS_OK;
1978}
1979
1980NS_IMETHODIMPnsresult
1981nsDocShell::GetAllowWindowControl(bool* aAllowWindowControl) {
1982 *aAllowWindowControl = mAllowWindowControl;
1983 return NS_OK;
1984}
1985
1986NS_IMETHODIMPnsresult
1987nsDocShell::SetAllowWindowControl(bool aAllowWindowControl) {
1988 mAllowWindowControl = aAllowWindowControl;
1989 return NS_OK;
1990}
1991
1992NS_IMETHODIMPnsresult
1993nsDocShell::GetAllowContentRetargeting(bool* aAllowContentRetargeting) {
1994 *aAllowContentRetargeting = mBrowsingContext->GetAllowContentRetargeting();
1995 return NS_OK;
1996}
1997
1998NS_IMETHODIMPnsresult
1999nsDocShell::SetAllowContentRetargeting(bool aAllowContentRetargeting) {
2000 BrowsingContext::Transaction txn;
2001 txn.SetAllowContentRetargeting(aAllowContentRetargeting);
2002 txn.SetAllowContentRetargetingOnChildren(aAllowContentRetargeting);
2003 return txn.Commit(mBrowsingContext);
2004}
2005
2006NS_IMETHODIMPnsresult
2007nsDocShell::GetAllowContentRetargetingOnChildren(
2008 bool* aAllowContentRetargetingOnChildren) {
2009 *aAllowContentRetargetingOnChildren =
2010 mBrowsingContext->GetAllowContentRetargetingOnChildren();
2011 return NS_OK;
2012}
2013
2014NS_IMETHODIMPnsresult
2015nsDocShell::SetAllowContentRetargetingOnChildren(
2016 bool aAllowContentRetargetingOnChildren) {
2017 return mBrowsingContext->SetAllowContentRetargetingOnChildren(
2018 aAllowContentRetargetingOnChildren);
2019}
2020
2021NS_IMETHODIMPnsresult
2022nsDocShell::GetMayEnableCharacterEncodingMenu(
2023 bool* aMayEnableCharacterEncodingMenu) {
2024 *aMayEnableCharacterEncodingMenu = false;
2025 if (!mDocumentViewer) {
2026 return NS_OK;
2027 }
2028 Document* doc = mDocumentViewer->GetDocument();
2029 if (!doc) {
2030 return NS_OK;
2031 }
2032 if (doc->WillIgnoreCharsetOverride()) {
2033 return NS_OK;
2034 }
2035
2036 *aMayEnableCharacterEncodingMenu = true;
2037 return NS_OK;
2038}
2039
2040NS_IMETHODIMPnsresult
2041nsDocShell::GetAllDocShellsInSubtree(int32_t aItemType,
2042 DocShellEnumeratorDirection aDirection,
2043 nsTArray<RefPtr<nsIDocShell>>& aResult) {
2044 aResult.Clear();
2045
2046 nsDocShellEnumerator docShellEnum(
2047 (aDirection == ENUMERATE_FORWARDS)
2048 ? nsDocShellEnumerator::EnumerationDirection::Forwards
2049 : nsDocShellEnumerator::EnumerationDirection::Backwards,
2050 aItemType, *this);
2051
2052 nsresult rv = docShellEnum.BuildDocShellArray(aResult);
2053 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2054 return rv;
2055 }
2056
2057 return NS_OK;
2058}
2059
2060NS_IMETHODIMPnsresult
2061nsDocShell::GetAppType(AppType* aAppType) {
2062 *aAppType = mAppType;
2063 return NS_OK;
2064}
2065
2066NS_IMETHODIMPnsresult
2067nsDocShell::SetAppType(AppType aAppType) {
2068 mAppType = aAppType;
2069 return NS_OK;
2070}
2071
2072NS_IMETHODIMPnsresult
2073nsDocShell::GetAllowAuth(bool* aAllowAuth) {
2074 *aAllowAuth = mAllowAuth;
2075 return NS_OK;
2076}
2077
2078NS_IMETHODIMPnsresult
2079nsDocShell::SetAllowAuth(bool aAllowAuth) {
2080 mAllowAuth = aAllowAuth;
2081 return NS_OK;
2082}
2083
2084NS_IMETHODIMPnsresult
2085nsDocShell::GetZoom(float* aZoom) {
2086 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"
, 2086); return NS_ERROR_INVALID_POINTER; } } while (false)
;
2087 *aZoom = 1.0f;
2088 return NS_OK;
2089}
2090
2091NS_IMETHODIMPnsresult
2092nsDocShell::SetZoom(float aZoom) { return NS_ERROR_NOT_IMPLEMENTED; }
2093
2094NS_IMETHODIMPnsresult
2095nsDocShell::GetBusyFlags(BusyFlags* aBusyFlags) {
2096 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"
, 2096); return NS_ERROR_INVALID_POINTER; } } while (false)
;
2097
2098 *aBusyFlags = mBusyFlags;
2099 return NS_OK;
2100}
2101
2102NS_IMETHODIMPnsresult
2103nsDocShell::GetLoadURIDelegate(nsILoadURIDelegate** aLoadURIDelegate) {
2104 nsCOMPtr<nsILoadURIDelegate> delegate = GetLoadURIDelegate();
2105 delegate.forget(aLoadURIDelegate);
2106 return NS_OK;
2107}
2108
2109already_AddRefed<nsILoadURIDelegate> nsDocShell::GetLoadURIDelegate() {
2110 if (nsCOMPtr<nsILoadURIDelegate> result =
2111 do_QueryActor("LoadURIDelegate", GetDocument())) {
2112 return result.forget();
2113 }
2114
2115 return nullptr;
2116}
2117
2118NS_IMETHODIMPnsresult
2119nsDocShell::GetUseErrorPages(bool* aUseErrorPages) {
2120 *aUseErrorPages = mBrowsingContext->GetUseErrorPages();
2121 return NS_OK;
2122}
2123
2124NS_IMETHODIMPnsresult
2125nsDocShell::SetUseErrorPages(bool aUseErrorPages) {
2126 return mBrowsingContext->SetUseErrorPages(aUseErrorPages);
2127}
2128
2129NS_IMETHODIMPnsresult
2130nsDocShell::GetPreviousEntryIndex(int32_t* aPreviousEntryIndex) {
2131 *aPreviousEntryIndex = mPreviousEntryIndex;
2132 return NS_OK;
2133}
2134
2135NS_IMETHODIMPnsresult
2136nsDocShell::GetLoadedEntryIndex(int32_t* aLoadedEntryIndex) {
2137 *aLoadedEntryIndex = mLoadedEntryIndex;
2138 return NS_OK;
2139}
2140
2141NS_IMETHODIMPnsresult
2142nsDocShell::HistoryPurged(int32_t aNumEntries) {
2143 // These indices are used for fastback cache eviction, to determine
2144 // which session history entries are candidates for content viewer
2145 // eviction. We need to adjust by the number of entries that we
2146 // just purged from history, so that we look at the right session history
2147 // entries during eviction.
2148 mPreviousEntryIndex = std::max(-1, mPreviousEntryIndex - aNumEntries);
2149 mLoadedEntryIndex = std::max(0, mLoadedEntryIndex - aNumEntries);
2150
2151 for (auto* child : mChildList.ForwardRange()) {
2152 nsCOMPtr<nsIDocShell> shell = do_QueryObject(child);
2153 if (shell) {
2154 shell->HistoryPurged(aNumEntries);
2155 }
2156 }
2157
2158 return NS_OK;
2159}
2160
2161nsresult nsDocShell::HistoryEntryRemoved(int32_t aIndex) {
2162 // These indices are used for fastback cache eviction, to determine
2163 // which session history entries are candidates for content viewer
2164 // eviction. We need to adjust by the number of entries that we
2165 // just purged from history, so that we look at the right session history
2166 // entries during eviction.
2167 if (aIndex == mPreviousEntryIndex) {
2168 mPreviousEntryIndex = -1;
2169 } else if (aIndex < mPreviousEntryIndex) {
2170 --mPreviousEntryIndex;
2171 }
2172 if (mLoadedEntryIndex == aIndex) {
2173 mLoadedEntryIndex = 0;
2174 } else if (aIndex < mLoadedEntryIndex) {
2175 --mLoadedEntryIndex;
2176 }
2177
2178 for (auto* child : mChildList.ForwardRange()) {
2179 nsCOMPtr<nsIDocShell> shell = do_QueryObject(child);
2180 if (shell) {
2181 static_cast<nsDocShell*>(shell.get())->HistoryEntryRemoved(aIndex);
2182 }
2183 }
2184
2185 return NS_OK;
2186}
2187
2188nsresult nsDocShell::Now(DOMHighResTimeStamp* aWhen) {
2189 *aWhen = (TimeStamp::Now() - TimeStamp::ProcessCreation()).ToMilliseconds();
2190 return NS_OK;
2191}
2192
2193NS_IMETHODIMPnsresult
2194nsDocShell::SetWindowDraggingAllowed(bool aValue) {
2195 RefPtr<nsDocShell> parent = GetInProcessParentDocshell();
2196 if (!aValue && mItemType == typeChrome && !parent) {
2197 // Window dragging is always allowed for top level
2198 // chrome docshells.
2199 return NS_ERROR_FAILURE;
2200 }
2201 mWindowDraggingAllowed = aValue;
2202 return NS_OK;
2203}
2204
2205NS_IMETHODIMPnsresult
2206nsDocShell::GetWindowDraggingAllowed(bool* aValue) {
2207 // window dragging regions in CSS (-moz-window-drag:drag)
2208 // can be slow. Default behavior is to only allow it for
2209 // chrome top level windows.
2210 RefPtr<nsDocShell> parent = GetInProcessParentDocshell();
2211 if (mItemType == typeChrome && !parent) {
2212 // Top level chrome window
2213 *aValue = true;
2214 } else {
2215 *aValue = mWindowDraggingAllowed;
2216 }
2217 return NS_OK;
2218}
2219
2220NS_IMETHODIMPnsresult
2221nsDocShell::GetCurrentDocumentChannel(nsIChannel** aResult) {
2222 NS_IF_ADDREF(*aResult = GetCurrentDocChannel())ns_if_addref(*aResult = GetCurrentDocChannel());
2223 return NS_OK;
2224}
2225
2226nsIChannel* nsDocShell::GetCurrentDocChannel() {
2227 if (mDocumentViewer) {
2228 Document* doc = mDocumentViewer->GetDocument();
2229 if (doc) {
2230 return doc->GetChannel();
2231 }
2232 }
2233 return nullptr;
2234}
2235
2236NS_IMETHODIMPnsresult
2237nsDocShell::AddWeakScrollObserver(nsIScrollObserver* aObserver) {
2238 nsWeakPtr weakObs = do_GetWeakReference(aObserver);
2239 if (!weakObs) {
2240 return NS_ERROR_FAILURE;
2241 }
2242 mScrollObservers.AppendElement(weakObs);
2243 return NS_OK;
2244}
2245
2246NS_IMETHODIMPnsresult
2247nsDocShell::RemoveWeakScrollObserver(nsIScrollObserver* aObserver) {
2248 nsWeakPtr obs = do_GetWeakReference(aObserver);
2249 return mScrollObservers.RemoveElement(obs) ? NS_OK : NS_ERROR_FAILURE;
2250}
2251
2252void nsDocShell::NotifyAsyncPanZoomStarted() {
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->AsyncPanZoomStarted();
2259 } else {
2260 iter.Remove();
2261 }
2262 }
2263}
2264
2265void nsDocShell::NotifyAsyncPanZoomStopped() {
2266 nsTObserverArray<nsWeakPtr>::ForwardIterator iter(mScrollObservers);
2267 while (iter.HasMore()) {
2268 nsWeakPtr ref = iter.GetNext();
2269 nsCOMPtr<nsIScrollObserver> obs = do_QueryReferent(ref);
2270 if (obs) {
2271 obs->AsyncPanZoomStopped();
2272 } else {
2273 iter.Remove();
2274 }
2275 }
2276}
2277
2278NS_IMETHODIMPnsresult
2279nsDocShell::NotifyScrollObservers() {
2280 nsTObserverArray<nsWeakPtr>::ForwardIterator iter(mScrollObservers);
2281 while (iter.HasMore()) {
2282 nsWeakPtr ref = iter.GetNext();
2283 nsCOMPtr<nsIScrollObserver> obs = do_QueryReferent(ref);
2284 if (obs) {
2285 obs->ScrollPositionChanged();
2286 } else {
2287 iter.Remove();
2288 }
2289 }
2290 return NS_OK;
2291}
2292
2293//*****************************************************************************
2294// nsDocShell::nsIDocShellTreeItem
2295//*****************************************************************************
2296
2297NS_IMETHODIMPnsresult
2298nsDocShell::GetName(nsAString& aName) {
2299 aName = mBrowsingContext->Name();
2300 return NS_OK;
2301}
2302
2303NS_IMETHODIMPnsresult
2304nsDocShell::SetName(const nsAString& aName) {
2305 return mBrowsingContext->SetName(aName);
2306}
2307
2308NS_IMETHODIMPnsresult
2309nsDocShell::NameEquals(const nsAString& aName, bool* aResult) {
2310 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"
, 2310); return NS_ERROR_INVALID_POINTER; } } while (false)
;
2311 *aResult = mBrowsingContext->NameEquals(aName);
2312 return NS_OK;
2313}
2314
2315NS_IMETHODIMPnsresult
2316nsDocShell::GetCustomUserAgent(nsAString& aCustomUserAgent) {
2317 mBrowsingContext->GetCustomUserAgent(aCustomUserAgent);
2318 return NS_OK;
2319}
2320
2321NS_IMETHODIMPnsresult
2322nsDocShell::SetCustomUserAgent(const nsAString& aCustomUserAgent) {
2323 if (mWillChangeProcess) {
2324 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"
, 2324)
;
2325 return NS_ERROR_FAILURE;
2326 }
2327
2328 return mBrowsingContext->SetCustomUserAgent(aCustomUserAgent);
2329}
2330
2331NS_IMETHODIMPnsresult
2332nsDocShell::ClearCachedPlatform() {
2333 nsCOMPtr<nsPIDOMWindowInner> win =
2334 mScriptGlobal ? mScriptGlobal->GetCurrentInnerWindow() : nullptr;
2335 if (win) {
2336 Navigator* navigator = win->Navigator();
2337 if (navigator) {
2338 navigator->ClearPlatformCache();
2339 }
2340 }
2341
2342 return NS_OK;
2343}
2344
2345NS_IMETHODIMPnsresult
2346nsDocShell::ClearCachedUserAgent() {
2347 nsCOMPtr<nsPIDOMWindowInner> win =
2348 mScriptGlobal ? mScriptGlobal->GetCurrentInnerWindow() : nullptr;
2349 if (win) {
2350 Navigator* navigator = win->Navigator();
2351 if (navigator) {
2352 navigator->ClearUserAgentCache();
2353 }
2354 }
2355
2356 return NS_OK;
2357}
2358
2359/* virtual */
2360int32_t nsDocShell::ItemType() { return mItemType; }
2361
2362NS_IMETHODIMPnsresult
2363nsDocShell::GetItemType(int32_t* aItemType) {
2364 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"
, 2364); return NS_ERROR_INVALID_POINTER; } } while (false)
;
2365
2366 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"
, 2367); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "(mBrowsingContext->IsContent() ? typeContent : typeChrome) == mItemType"
")"); do { *((volatile int*)__null) = 2367; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2367 (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"
, 2367); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "(mBrowsingContext->IsContent() ? typeContent : typeChrome) == mItemType"
")"); do { *((volatile int*)__null) = 2367; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2368 *aItemType = mItemType;
2369 return NS_OK;
2370}
2371
2372NS_IMETHODIMPnsresult
2373nsDocShell::GetInProcessParent(nsIDocShellTreeItem** aParent) {
2374 if (!mParent) {
2375 *aParent = nullptr;
2376 } else {
2377 CallQueryInterface(mParent, aParent);
2378 }
2379 // Note that in the case when the parent is not an nsIDocShellTreeItem we
2380 // don't want to throw; we just want to return null.
2381 return NS_OK;
2382}
2383
2384// With Fission, related nsDocShell objects may exist in a different process. In
2385// that case, this method will return `nullptr`, despite a parent nsDocShell
2386// object existing.
2387//
2388// Prefer using `BrowsingContext::Parent()`, which will succeed even if the
2389// parent entry is not in the current process, and handle the case where the
2390// parent nsDocShell is inaccessible.
2391already_AddRefed<nsDocShell> nsDocShell::GetInProcessParentDocshell() {
2392 nsCOMPtr<nsIDocShell> docshell = do_QueryInterface(GetAsSupports(mParent));
2393 return docshell.forget().downcast<nsDocShell>();
2394}
2395
2396void nsDocShell::MaybeCreateInitialClientSource(nsIPrincipal* aPrincipal) {
2397 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"
, 2397); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mIsBeingDestroyed"
")"); do { *((volatile int*)__null) = 2397; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2398
2399 // If there is an existing document then there is no need to create
2400 // a client for a future initial about:blank document.
2401 if (mScriptGlobal && mScriptGlobal->GetCurrentInnerWindow() &&
2402 mScriptGlobal->GetCurrentInnerWindow()->GetExtantDoc()) {
2403 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"
, 2404); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "mScriptGlobal->GetCurrentInnerWindow()->GetClientInfo().isSome()"
")"); do { *((volatile int*)__null) = 2404; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2404 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"
, 2404); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "mScriptGlobal->GetCurrentInnerWindow()->GetClientInfo().isSome()"
")"); do { *((volatile int*)__null) = 2404; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2405 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"
, 2405); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "!mInitialClientSource"
")"); do { *((volatile int*)__null) = 2405; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2406 return;
2407 }
2408
2409 // Don't recreate the initial client source. We call this multiple times
2410 // when DoChannelLoad() is called before CreateAboutBlankDocumentViewer.
2411 if (mInitialClientSource) {
2412 return;
2413 }
2414
2415 // Don't pre-allocate the client when we are sandboxed. The inherited
2416 // principal does not take sandboxing into account.
2417 // TODO: Refactor sandboxing principal code out so we can use it here.
2418 if (!aPrincipal && mBrowsingContext->GetSandboxFlags()) {
2419 return;
2420 }
2421
2422 // We cannot get inherited foreign partitioned principal here. Instead, we
2423 // directly check which principal we want to inherit for the service worker.
2424 nsIPrincipal* principal =
2425 aPrincipal
2426 ? aPrincipal
2427 : GetInheritedPrincipal(
2428 false, StoragePrincipalHelper::
2429 ShouldUsePartitionPrincipalForServiceWorker(this));
2430
2431 // Sometimes there is no principal available when we are called from
2432 // CreateAboutBlankDocumentViewer. For example, sometimes the principal
2433 // is only extracted from the load context after the document is created
2434 // in Document::ResetToURI(). Ideally we would do something similar
2435 // here, but for now lets just avoid the issue by not preallocating the
2436 // client.
2437 if (!principal) {
2438 return;
2439 }
2440
2441 nsCOMPtr<nsPIDOMWindowOuter> win = GetWindow();
2442 if (!win) {
2443 return;
2444 }
2445
2446 mInitialClientSource = ClientManager::CreateSource(
2447 ClientType::Window, GetMainThreadSerialEventTarget(), principal);
2448 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"
, 2448); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "mInitialClientSource"
")"); do { *((volatile int*)__null) = 2448; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2449
2450 // Mark the initial client as execution ready, but owned by the docshell.
2451 // If the client is actually used this will cause ClientSource to force
2452 // the creation of the initial about:blank by calling
2453 // nsDocShell::GetDocument().
2454 mInitialClientSource->DocShellExecutionReady(this);
2455
2456 // Next, check to see if the parent is controlled.
2457 nsCOMPtr<nsIDocShell> parent = GetInProcessParentDocshell();
2458 nsPIDOMWindowOuter* parentOuter = parent ? parent->GetWindow() : nullptr;
2459 nsPIDOMWindowInner* parentInner =
2460 parentOuter ? parentOuter->GetCurrentInnerWindow() : nullptr;
2461 if (!parentInner) {
2462 return;
2463 }
2464
2465 nsCOMPtr<nsIURI> uri;
2466 MOZ_ALWAYS_SUCCEEDS(NS_NewURI(getter_AddRefs(uri), "about:blank"_ns))do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(NS_NewURI(getter_AddRefs(uri), "about:blank"_ns))), 1)))), 1
))) { } else { do { static_assert( mozilla::detail::AssertionConditionType
<decltype(false)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("false" " (" "NS_SUCCEEDED(NS_NewURI(getter_AddRefs(uri), \"about:blank\"_ns))"
")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 2466); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "false"
") (" "NS_SUCCEEDED(NS_NewURI(getter_AddRefs(uri), \"about:blank\"_ns))"
")"); do { *((volatile int*)__null) = 2466; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
2467
2468 // We're done if there is no parent controller or if this docshell
2469 // is not permitted to control for some reason.
2470 Maybe<ServiceWorkerDescriptor> controller(parentInner->GetController());
2471 if (controller.isNothing() ||
2472 !ServiceWorkerAllowedToControlWindow(principal, uri)) {
2473 return;
2474 }
2475
2476 mInitialClientSource->InheritController(controller.ref());
2477}
2478
2479Maybe<ClientInfo> nsDocShell::GetInitialClientInfo() const {
2480 if (mInitialClientSource) {
2481 Maybe<ClientInfo> result;
2482 result.emplace(mInitialClientSource->Info());
2483 return result;
2484 }
2485
2486 nsPIDOMWindowInner* innerWindow =
2487 mScriptGlobal ? mScriptGlobal->GetCurrentInnerWindow() : nullptr;
2488 Document* doc = innerWindow ? innerWindow->GetExtantDoc() : nullptr;
2489
2490 if (!doc || !doc->IsInitialDocument()) {
2491 return Maybe<ClientInfo>();
2492 }
2493
2494 return innerWindow->GetClientInfo();
2495}
2496
2497nsresult nsDocShell::SetDocLoaderParent(nsDocLoader* aParent) {
2498 bool wasFrame = IsSubframe();
2499
2500 nsresult rv = nsDocLoader::SetDocLoaderParent(aParent);
2501 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"
, 2501); return rv; } } while (false)
;
2502
2503 nsCOMPtr<nsISupportsPriority> priorityGroup = do_QueryInterface(mLoadGroup);
2504 if (wasFrame != IsSubframe() && priorityGroup) {
2505 priorityGroup->AdjustPriority(wasFrame ? -1 : 1);
2506 }
2507
2508 // Curse ambiguous nsISupports inheritance!
2509 nsISupports* parent = GetAsSupports(aParent);
2510
2511 // If parent is another docshell, we inherit all their flags for
2512 // allowing plugins, scripting etc.
2513 bool value;
2514 nsCOMPtr<nsIDocShell> parentAsDocShell(do_QueryInterface(parent));
2515
2516 if (parentAsDocShell) {
2517 if (mAllowMetaRedirects &&
2518 NS_SUCCEEDED(parentAsDocShell->GetAllowMetaRedirects(&value))((bool)(__builtin_expect(!!(!NS_FAILED_impl(parentAsDocShell->
GetAllowMetaRedirects(&value))), 1)))
) {
2519 SetAllowMetaRedirects(value);
2520 }
2521 if (mAllowSubframes &&
2522 NS_SUCCEEDED(parentAsDocShell->GetAllowSubframes(&value))((bool)(__builtin_expect(!!(!NS_FAILED_impl(parentAsDocShell->
GetAllowSubframes(&value))), 1)))
) {
2523 SetAllowSubframes(value);
2524 }
2525 if (mAllowImages &&
2526 NS_SUCCEEDED(parentAsDocShell->GetAllowImages(&value))((bool)(__builtin_expect(!!(!NS_FAILED_impl(parentAsDocShell->
GetAllowImages(&value))), 1)))
) {
2527 SetAllowImages(value);
2528 }
2529 SetAllowMedia(parentAsDocShell->GetAllowMedia() && mAllowMedia);
2530 if (mAllowWindowControl &&
2531 NS_SUCCEEDED(parentAsDocShell->GetAllowWindowControl(&value))((bool)(__builtin_expect(!!(!NS_FAILED_impl(parentAsDocShell->
GetAllowWindowControl(&value))), 1)))
) {
2532 SetAllowWindowControl(value);
2533 }
2534 if (NS_FAILED(parentAsDocShell->GetAllowDNSPrefetch(&value))((bool)(__builtin_expect(!!(NS_FAILED_impl(parentAsDocShell->
GetAllowDNSPrefetch(&value))), 0)))
) {
2535 value = false;
2536 }
2537 SetAllowDNSPrefetch(mAllowDNSPrefetch && value);
2538 }
2539
2540 nsCOMPtr<nsIURIContentListener> parentURIListener(do_GetInterface(parent));
2541 if (parentURIListener) {
2542 mContentListener->SetParentContentListener(parentURIListener);
2543 }
2544
2545 return NS_OK;
2546}
2547
2548void nsDocShell::MaybeRestoreWindowName() {
2549 if (!StaticPrefs::privacy_window_name_update_enabled()) {
2550 return;
2551 }
2552
2553 // We only restore window.name for the top-level content.
2554 if (!mBrowsingContext->IsTopContent()) {
2555 return;
2556 }
2557
2558 nsAutoString name;
2559
2560 // Following implements https://html.spec.whatwg.org/#history-traversal:
2561 // Step 4.4. Check if the loading entry has a name.
2562
2563 if (mLSHE) {
2564 mLSHE->GetName(name);
2565 }
2566
2567 if (mLoadingEntry) {
2568 name = mLoadingEntry->mInfo.GetName();
2569 }
2570
2571 if (name.IsEmpty()) {
2572 return;
2573 }
2574
2575 // Step 4.4.1. Set the name to the browsing context.
2576 Unused << mBrowsingContext->SetName(name);
2577
2578 // Step 4.4.2. Clear the name of all entries that are contiguous and
2579 // same-origin with the loading entry.
2580 if (mLSHE) {
2581 nsSHistory::WalkContiguousEntries(
2582 mLSHE, [](nsISHEntry* aEntry) { aEntry->SetName(EmptyString()); });
2583 }
2584
2585 if (mLoadingEntry) {
2586 // Clear the name of the session entry in the child side. For parent side,
2587 // the clearing will be done when we commit the history to the parent.
2588 mLoadingEntry->mInfo.SetName(EmptyString());
2589 }
2590}
2591
2592void nsDocShell::StoreWindowNameToSHEntries() {
2593 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"
, 2593); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mBrowsingContext->IsTopContent()"
")"); do { *((volatile int*)__null) = 2593; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2594
2595 nsAutoString name;
2596 mBrowsingContext->GetName(name);
2597
2598 if (mOSHE) {
2599 nsSHistory::WalkContiguousEntries(
2600 mOSHE, [&](nsISHEntry* aEntry) { aEntry->SetName(name); });
2601 }
2602
2603 if (mozilla::SessionHistoryInParent()) {
2604 if (XRE_IsParentProcess()) {
2605 SessionHistoryEntry* entry =
2606 mBrowsingContext->Canonical()->GetActiveSessionHistoryEntry();
2607 if (entry) {
2608 nsSHistory::WalkContiguousEntries(
2609 entry, [&](nsISHEntry* aEntry) { aEntry->SetName(name); });
2610 }
2611 } else {
2612 // Ask parent process to store the name in entries.
2613 mozilla::Unused
2614 << ContentChild::GetSingleton()
2615 ->SendSessionHistoryEntryStoreWindowNameInContiguousEntries(
2616 mBrowsingContext, name);
2617 }
2618 }
2619}
2620
2621NS_IMETHODIMPnsresult
2622nsDocShell::GetInProcessSameTypeParent(nsIDocShellTreeItem** aParent) {
2623 if (BrowsingContext* parentBC = mBrowsingContext->GetParent()) {
2624 *aParent = do_AddRef(parentBC->GetDocShell()).take();
2625 }
2626 return NS_OK;
2627}
2628
2629NS_IMETHODIMPnsresult
2630nsDocShell::GetInProcessRootTreeItem(nsIDocShellTreeItem** aRootTreeItem) {
2631 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"
, 2631); return NS_ERROR_INVALID_POINTER; } } while (false)
;
2632
2633 RefPtr<nsDocShell> root = this;
2634 RefPtr<nsDocShell> parent = root->GetInProcessParentDocshell();
2635 while (parent) {
2636 root = parent;
2637 parent = root->GetInProcessParentDocshell();
2638 }
2639
2640 root.forget(aRootTreeItem);
2641 return NS_OK;
2642}
2643
2644NS_IMETHODIMPnsresult
2645nsDocShell::GetInProcessSameTypeRootTreeItem(
2646 nsIDocShellTreeItem** aRootTreeItem) {
2647 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"
, 2647); return NS_ERROR_INVALID_POINTER; } } while (false)
;
2648 *aRootTreeItem = static_cast<nsIDocShellTreeItem*>(this);
2649
2650 nsCOMPtr<nsIDocShellTreeItem> parent;
2651 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"
, 2652); return NS_ERROR_FAILURE; } } while (false)
2652 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"
, 2652); return NS_ERROR_FAILURE; } } while (false)
;
2653 while (parent) {
2654 *aRootTreeItem = parent;
2655 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"
, 2657); return NS_ERROR_FAILURE; } } while (false)
2656 (*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"
, 2657); return NS_ERROR_FAILURE; } } while (false)
2657 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"
, 2657); return NS_ERROR_FAILURE; } } while (false)
;
2658 }
2659 NS_ADDREF(*aRootTreeItem)(*aRootTreeItem)->AddRef();
2660 return NS_OK;
2661}
2662
2663NS_IMETHODIMPnsresult
2664nsDocShell::GetTreeOwner(nsIDocShellTreeOwner** aTreeOwner) {
2665 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"
, 2665); return NS_ERROR_INVALID_POINTER; } } while (false)
;
2666
2667 *aTreeOwner = mTreeOwner;
2668 NS_IF_ADDREF(*aTreeOwner)ns_if_addref(*aTreeOwner);
2669 return NS_OK;
2670}
2671
2672NS_IMETHODIMPnsresult
2673nsDocShell::SetTreeOwner(nsIDocShellTreeOwner* aTreeOwner) {
2674 if (mIsBeingDestroyed && aTreeOwner) {
2675 return NS_ERROR_FAILURE;
2676 }
2677
2678 // Don't automatically set the progress based on the tree owner for frames
2679 if (!IsSubframe()) {
2680 nsCOMPtr<nsIWebProgress> webProgress =
2681 do_QueryInterface(GetAsSupports(this));
2682
2683 if (webProgress) {
2684 nsCOMPtr<nsIWebProgressListener> oldListener =
2685 do_QueryInterface(mTreeOwner);
2686 nsCOMPtr<nsIWebProgressListener> newListener =
2687 do_QueryInterface(aTreeOwner);
2688
2689 if (oldListener) {
2690 webProgress->RemoveProgressListener(oldListener);
2691 }
2692
2693 if (newListener) {
2694 webProgress->AddProgressListener(newListener,
2695 nsIWebProgress::NOTIFY_ALL);
2696 }
2697 }
2698 }
2699
2700 mTreeOwner = aTreeOwner; // Weak reference per API
2701
2702 for (auto* childDocLoader : mChildList.ForwardRange()) {
2703 nsCOMPtr<nsIDocShellTreeItem> child = do_QueryObject(childDocLoader);
2704 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"
, 2704); return NS_ERROR_FAILURE; } } while (false)
;
2705
2706 if (child->ItemType() == mItemType) {
2707 child->SetTreeOwner(aTreeOwner);
2708 }
2709 }
2710
2711 // If we're in the content process and have had a TreeOwner set on us, extract
2712 // our BrowserChild actor. If we've already had our BrowserChild set, assert
2713 // that it hasn't changed.
2714 if (mTreeOwner && XRE_IsContentProcess()) {
2715 nsCOMPtr<nsIBrowserChild> newBrowserChild = do_GetInterface(mTreeOwner);
2716 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"
, 2717); AnnotateMozCrashReason("MOZ_ASSERT" "(" "newBrowserChild"
") (" "No BrowserChild actor for tree owner in Content!" ")"
); do { *((volatile int*)__null) = 2717; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2717 "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"
, 2717); AnnotateMozCrashReason("MOZ_ASSERT" "(" "newBrowserChild"
") (" "No BrowserChild actor for tree owner in Content!" ")"
); do { *((volatile int*)__null) = 2717; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2718
2719 if (mBrowserChild) {
2720 nsCOMPtr<nsIBrowserChild> oldBrowserChild =
2721 do_QueryReferent(mBrowserChild);
2722 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"
, 2724); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "oldBrowserChild == newBrowserChild"
") (" "Cannot change BrowserChild during nsDocShell lifetime!"
")"); do { *((volatile int*)__null) = 2724; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2723 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"
, 2724); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "oldBrowserChild == newBrowserChild"
") (" "Cannot change BrowserChild during nsDocShell lifetime!"
")"); do { *((volatile int*)__null) = 2724; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2724 "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"
, 2724); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "oldBrowserChild == newBrowserChild"
") (" "Cannot change BrowserChild during nsDocShell lifetime!"
")"); do { *((volatile int*)__null) = 2724; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2725 } else {
2726 mBrowserChild = do_GetWeakReference(newBrowserChild);
2727 }
2728 }
2729
2730 return NS_OK;
2731}
2732
2733NS_IMETHODIMPnsresult
2734nsDocShell::GetHistoryID(nsID& aID) {
2735 aID = mBrowsingContext->GetHistoryID();
2736 return NS_OK;
2737}
2738
2739const nsID& nsDocShell::HistoryID() { return mBrowsingContext->GetHistoryID(); }
2740
2741NS_IMETHODIMPnsresult
2742nsDocShell::GetIsInUnload(bool* aIsInUnload) {
2743 *aIsInUnload = mFiredUnloadEvent;
2744 return NS_OK;
2745}
2746
2747NS_IMETHODIMPnsresult
2748nsDocShell::GetInProcessChildCount(int32_t* aChildCount) {
2749 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"
, 2749); return NS_ERROR_INVALID_POINTER; } } while (false)
;
2750 *aChildCount = mChildList.Length();
2751 return NS_OK;
2752}
2753
2754NS_IMETHODIMPnsresult
2755nsDocShell::AddChild(nsIDocShellTreeItem* aChild) {
2756 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"
, 2756); return NS_ERROR_INVALID_POINTER; } } while (false)
;
2757
2758 RefPtr<nsDocLoader> childAsDocLoader = GetAsDocLoader(aChild);
2759 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"
, 2759); return NS_ERROR_UNEXPECTED; } } while (false)
;
2760
2761 // Make sure we're not creating a loop in the docshell tree
2762 nsDocLoader* ancestor = this;
2763 do {
2764 if (childAsDocLoader == ancestor) {
2765 return NS_ERROR_ILLEGAL_VALUE;
2766 }
2767 ancestor = ancestor->GetParent();
2768 } while (ancestor);
2769
2770 // Make sure to remove the child from its current parent.
2771 nsDocLoader* childsParent = childAsDocLoader->GetParent();
2772 if (childsParent) {
2773 nsresult rv = childsParent->RemoveChildLoader(childAsDocLoader);
2774 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"
, 2774); return rv; } } while (false)
;
2775 }
2776
2777 // Make sure to clear the treeowner in case this child is a different type
2778 // from us.
2779 aChild->SetTreeOwner(nullptr);
2780
2781 nsresult res = AddChildLoader(childAsDocLoader);
2782 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"
, 2782); return res; } } while (false)
;
2783 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"
, 2784); MOZ_PretendNoReturn(); } } while (0)
2784 "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"
, 2784); MOZ_PretendNoReturn(); } } while (0)
;
2785
2786 /* Set the child's global history if the parent has one */
2787 if (mBrowsingContext->GetUseGlobalHistory()) {
2788 // childDocShell->SetUseGlobalHistory(true);
2789 // this should be set through BC inherit
2790 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"
, 2790); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aChild->GetBrowsingContext()->GetUseGlobalHistory()"
")"); do { *((volatile int*)__null) = 2790; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2791 }
2792
2793 if (aChild->ItemType() != mItemType) {
2794 return NS_OK;
2795 }
2796
2797 aChild->SetTreeOwner(mTreeOwner);
2798
2799 nsCOMPtr<nsIDocShell> childAsDocShell(do_QueryInterface(aChild));
2800 if (!childAsDocShell) {
2801 return NS_OK;
2802 }
2803
2804 // charset, style-disabling, and zoom will be inherited in SetupNewViewer()
2805
2806 // Now take this document's charset and set the child's parentCharset field
2807 // to it. We'll later use that field, in the loading process, for the
2808 // charset choosing algorithm.
2809 // If we fail, at any point, we just return NS_OK.
2810 // This code has some performance impact. But this will be reduced when
2811 // the current charset will finally be stored as an Atom, avoiding the
2812 // alias resolution extra look-up.
2813
2814 // we are NOT going to propagate the charset is this Chrome's docshell
2815 if (mItemType == nsIDocShellTreeItem::typeChrome) {
2816 return NS_OK;
2817 }
2818
2819 // get the parent's current charset
2820 if (!mDocumentViewer) {
2821 return NS_OK;
2822 }
2823 Document* doc = mDocumentViewer->GetDocument();
2824 if (!doc) {
2825 return NS_OK;
2826 }
2827
2828 const Encoding* parentCS = doc->GetDocumentCharacterSet();
2829 int32_t charsetSource = doc->GetDocumentCharacterSetSource();
2830 // set the child's parentCharset
2831 childAsDocShell->SetParentCharset(parentCS, charsetSource,
2832 doc->NodePrincipal());
2833
2834 // printf("### 1 >>> Adding child. Parent CS = %s. ItemType = %d.\n",
2835 // NS_LossyConvertUTF16toASCII(parentCS).get(), mItemType);
2836
2837 return NS_OK;
2838}
2839
2840NS_IMETHODIMPnsresult
2841nsDocShell::RemoveChild(nsIDocShellTreeItem* aChild) {
2842 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"
, 2842); return NS_ERROR_INVALID_POINTER; } } while (false)
;
2843
2844 RefPtr<nsDocLoader> childAsDocLoader = GetAsDocLoader(aChild);
2845 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"
, 2845); return NS_ERROR_UNEXPECTED; } } while (false)
;
2846
2847 nsresult rv = RemoveChildLoader(childAsDocLoader);
2848 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"
, 2848); return rv; } } while (false)
;
2849
2850 aChild->SetTreeOwner(nullptr);
2851
2852 return nsDocLoader::AddDocLoaderAsChildOfRoot(childAsDocLoader);
2853}
2854
2855NS_IMETHODIMPnsresult
2856nsDocShell::GetInProcessChildAt(int32_t aIndex, nsIDocShellTreeItem** aChild) {
2857 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"
, 2857); return NS_ERROR_INVALID_POINTER; } } while (false)
;
2858
2859 RefPtr<nsDocShell> child = GetInProcessChildAt(aIndex);
2860 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"
, 2860); return NS_ERROR_UNEXPECTED; } } while (false)
;
2861
2862 child.forget(aChild);
2863
2864 return NS_OK;
2865}
2866
2867nsDocShell* nsDocShell::GetInProcessChildAt(int32_t aIndex) {
2868#ifdef DEBUG1
2869 if (aIndex < 0) {
2870 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"
, 2870)
;
2871 } else if (static_cast<uint32_t>(aIndex) >= mChildList.Length()) {
2872 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"
, 2872)
;
2873 }
2874#endif
2875
2876 nsIDocumentLoader* child = ChildAt(aIndex);
2877
2878 // child may be nullptr here.
2879 return static_cast<nsDocShell*>(child);
2880}
2881
2882nsresult nsDocShell::AddChildSHEntry(nsISHEntry* aCloneRef,
2883 nsISHEntry* aNewEntry,
2884 int32_t aChildOffset, uint32_t aLoadType,
2885 bool aCloneChildren) {
2886 MOZ_ASSERT(!mozilla::SessionHistoryInParent())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mozilla::SessionHistoryInParent())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mozilla::SessionHistoryInParent
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!mozilla::SessionHistoryInParent()", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 2886); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mozilla::SessionHistoryInParent()"
")"); do { *((volatile int*)__null) = 2886; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2887 nsresult rv = NS_OK;
2888
2889 if (mLSHE && aLoadType != LOAD_PUSHSTATE) {
2890 /* You get here if you are currently building a
2891 * hierarchy ie.,you just visited a frameset page
2892 */
2893 if (NS_FAILED(mLSHE->ReplaceChild(aNewEntry))((bool)(__builtin_expect(!!(NS_FAILED_impl(mLSHE->ReplaceChild
(aNewEntry))), 0)))
) {
2894 rv = mLSHE->AddChild(aNewEntry, aChildOffset);
2895 }
2896 } else if (!aCloneRef) {
2897 /* This is an initial load in some subframe. Just append it if we can */
2898 if (mOSHE) {
2899 rv = mOSHE->AddChild(aNewEntry, aChildOffset, UseRemoteSubframes());
2900 }
2901 } else {
2902 RefPtr<ChildSHistory> shistory = GetRootSessionHistory();
2903 if (shistory) {
2904 rv = shistory->LegacySHistory()->AddChildSHEntryHelper(
2905 aCloneRef, aNewEntry, mBrowsingContext->Top(), aCloneChildren);
2906 }
2907 }
2908 return rv;
2909}
2910
2911nsresult nsDocShell::AddChildSHEntryToParent(nsISHEntry* aNewEntry,
2912 int32_t aChildOffset,
2913 bool aCloneChildren) {
2914 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"
, 2914); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mozilla::SessionHistoryInParent()"
")"); do { *((volatile int*)__null) = 2914; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2915 /* You will get here when you are in a subframe and
2916 * a new url has been loaded on you.
2917 * The mOSHE in this subframe will be the previous url's
2918 * mOSHE. This mOSHE will be used as the identification
2919 * for this subframe in the CloneAndReplace function.
2920 */
2921
2922 // In this case, we will end up calling AddEntry, which increases the
2923 // current index by 1
2924 RefPtr<ChildSHistory> rootSH = GetRootSessionHistory();
2925 if (rootSH) {
2926 mPreviousEntryIndex = rootSH->Index();
2927 }
2928
2929 nsresult rv;
2930 // XXX(farre): this is not Fission safe, expect errors. This never
2931 // get's executed once session history in the parent is enabled.
2932 nsCOMPtr<nsIDocShell> parent = do_QueryInterface(GetAsSupports(mParent), &rv);
2933 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"
, 2936); } } while (false)
2934 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"
, 2936); } } while (false)
2935 "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"
, 2936); } } while (false)
2936 "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"
, 2936); } } while (false)
;
2937 if (parent) {
2938 rv = nsDocShell::Cast(parent)->AddChildSHEntry(
2939 mOSHE, aNewEntry, aChildOffset, mLoadType, aCloneChildren);
2940 }
2941
2942 if (rootSH) {
2943 mLoadedEntryIndex = rootSH->Index();
2944
2945 if (MOZ_UNLIKELY(MOZ_LOG_TEST(gPageCacheLog, LogLevel::Verbose))(__builtin_expect(!!((__builtin_expect(!!(mozilla::detail::log_test
(gPageCacheLog, LogLevel::Verbose)), 0))), 0))
) {
2946 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)
2947 ("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)
2948 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)
;
2949 }
2950 }
2951
2952 return rv;
2953}
2954
2955NS_IMETHODIMPnsresult
2956nsDocShell::GetCurrentSHEntry(nsISHEntry** aEntry, bool* aOSHE) {
2957 *aOSHE = false;
2958 *aEntry = nullptr;
2959 if (mLSHE) {
2960 NS_ADDREF(*aEntry = mLSHE)(*aEntry = mLSHE)->AddRef();
2961 } else if (mOSHE) {
2962 NS_ADDREF(*aEntry = mOSHE)(*aEntry = mOSHE)->AddRef();
2963 *aOSHE = true;
2964 }
2965 return NS_OK;
2966}
2967
2968NS_IMETHODIMPnsresult nsDocShell::SynchronizeLayoutHistoryState() {
2969 if (mActiveEntry && mActiveEntry->GetLayoutHistoryState() &&
2970 mBrowsingContext) {
2971 if (XRE_IsContentProcess()) {
2972 dom::ContentChild* contentChild = dom::ContentChild::GetSingleton();
2973 if (contentChild) {
2974 contentChild->SendSynchronizeLayoutHistoryState(
2975 mBrowsingContext, mActiveEntry->GetLayoutHistoryState());
2976 }
2977 } else {
2978 SessionHistoryEntry* entry =
2979 mBrowsingContext->Canonical()->GetActiveSessionHistoryEntry();
2980 if (entry) {
2981 entry->SetLayoutHistoryState(mActiveEntry->GetLayoutHistoryState());
2982 }
2983 }
2984 if (mLoadingEntry &&
2985 mLoadingEntry->mInfo.SharedId() == mActiveEntry->SharedId()) {
2986 mLoadingEntry->mInfo.SetLayoutHistoryState(
2987 mActiveEntry->GetLayoutHistoryState());
2988 }
2989 }
2990
2991 return NS_OK;
2992}
2993
2994void nsDocShell::SetLoadGroupDefaultLoadFlags(nsLoadFlags aLoadFlags) {
2995 if (mLoadGroup) {
2996 mLoadGroup->SetDefaultLoadFlags(aLoadFlags);
2997 } else {
2998 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"
, 3000)
2999 "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"
, 3000)
3000 "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"
, 3000)
;
3001 }
3002}
3003
3004nsIScriptGlobalObject* nsDocShell::GetScriptGlobalObject() {
3005 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"
, 3005); return nullptr; } } while (false)
;
3006 return mScriptGlobal;
3007}
3008
3009Document* nsDocShell::GetDocument() {
3010 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"
, 3010); return nullptr; } } while (false)
;
3011 return mDocumentViewer->GetDocument();
3012}
3013
3014Document* nsDocShell::GetExtantDocument() {
3015 return mDocumentViewer ? mDocumentViewer->GetDocument() : nullptr;
3016}
3017
3018nsPIDOMWindowOuter* nsDocShell::GetWindow() {
3019 if (NS_FAILED(EnsureScriptEnvironment())((bool)(__builtin_expect(!!(NS_FAILED_impl(EnsureScriptEnvironment
())), 0)))
) {
3020 return nullptr;
3021 }
3022 return mScriptGlobal;
3023}
3024
3025NS_IMETHODIMPnsresult
3026nsDocShell::GetDomWindow(mozIDOMWindowProxy** aWindow) {
3027 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"
, 3027); return NS_ERROR_INVALID_POINTER; } } while (false)
;
3028
3029 nsresult rv = EnsureScriptEnvironment();
3030 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"
, 3030); return rv; } } while (false)
;
3031
3032 RefPtr<nsGlobalWindowOuter> window = mScriptGlobal;
3033 window.forget(aWindow);
3034 return NS_OK;
3035}
3036
3037NS_IMETHODIMPnsresult
3038nsDocShell::GetMessageManager(ContentFrameMessageManager** aMessageManager) {
3039 RefPtr<ContentFrameMessageManager> mm;
3040 if (RefPtr<BrowserChild> browserChild = BrowserChild::GetFrom(this)) {
3041 mm = browserChild->GetMessageManager();
3042 } else if (nsPIDOMWindowOuter* win = GetWindow()) {
3043 mm = win->GetMessageManager();
3044 }
3045 mm.forget(aMessageManager);
3046 return NS_OK;
3047}
3048
3049NS_IMETHODIMPnsresult
3050nsDocShell::GetIsNavigating(bool* aOut) {
3051 *aOut = mIsNavigating;
3052 return NS_OK;
3053}
3054
3055void nsDocShell::ClearFrameHistory(nsISHEntry* aEntry) {
3056 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"
, 3056); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mozilla::SessionHistoryInParent()"
")"); do { *((volatile int*)__null) = 3056; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3057 RefPtr<ChildSHistory> rootSH = GetRootSessionHistory();
3058 if (!rootSH || !aEntry) {
3059 return;
3060 }
3061
3062 rootSH->LegacySHistory()->RemoveFrameEntries(aEntry);
3063}
3064
3065//-------------------------------------
3066//-- Helper Method for Print discovery
3067//-------------------------------------
3068bool nsDocShell::NavigationBlockedByPrinting(bool aDisplayErrorDialog) {
3069 if (!mBrowsingContext->Top()->GetIsPrinting()) {
3070 return false;
3071 }
3072 if (aDisplayErrorDialog) {
3073 DisplayLoadError(NS_ERROR_DOCUMENT_IS_PRINTMODE, nullptr, nullptr, nullptr);
3074 }
3075 return true;
3076}
3077
3078bool nsDocShell::IsNavigationAllowed(bool aDisplayPrintErrorDialog,
3079 bool aCheckIfUnloadFired) {
3080 bool isAllowed = !NavigationBlockedByPrinting(aDisplayPrintErrorDialog) &&
3081 (!aCheckIfUnloadFired || !mFiredUnloadEvent);
3082 if (!isAllowed) {
3083 return false;
3084 }
3085 if (!mDocumentViewer) {
3086 return true;
3087 }
3088 bool firingBeforeUnload;
3089 mDocumentViewer->GetBeforeUnloadFiring(&firingBeforeUnload);
3090 return !firingBeforeUnload;
3091}
3092
3093//*****************************************************************************
3094// nsDocShell::nsIWebNavigation
3095//*****************************************************************************
3096
3097NS_IMETHODIMPnsresult
3098nsDocShell::GetCanGoBack(bool* aCanGoBack) {
3099 *aCanGoBack = false;
3100 if (!IsNavigationAllowed(false)) {
3101 return NS_OK; // JS may not handle returning of an error code
3102 }
3103 RefPtr<ChildSHistory> rootSH = GetRootSessionHistory();
3104 if (rootSH) {
3105 *aCanGoBack = rootSH->CanGo(-1);
3106 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)
3107 ("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)
;
3108
3109 return NS_OK;
3110 }
3111 return NS_ERROR_FAILURE;
3112}
3113
3114NS_IMETHODIMPnsresult
3115nsDocShell::GetCanGoForward(bool* aCanGoForward) {
3116 *aCanGoForward = false;
3117 if (!IsNavigationAllowed(false)) {
3118 return NS_OK; // JS may not handle returning of an error code
3119 }
3120 RefPtr<ChildSHistory> rootSH = GetRootSessionHistory();
3121 if (rootSH) {
3122 *aCanGoForward = rootSH->CanGo(1);
3123 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)
3124 ("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)
;
3125 return NS_OK;
3126 }
3127 return NS_ERROR_FAILURE;
3128}
3129
3130NS_IMETHODIMPnsresult
3131nsDocShell::GoBack(bool aRequireUserInteraction, bool aUserActivation) {
3132 if (!IsNavigationAllowed()) {
3133 return NS_OK; // JS may not handle returning of an error code
3134 }
3135
3136 auto cleanupIsNavigating = MakeScopeExit([&]() { mIsNavigating = false; });
3137 mIsNavigating = true;
3138
3139 RefPtr<ChildSHistory> rootSH = GetRootSessionHistory();
3140 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"
, 3140); return NS_ERROR_FAILURE; } } while (false)
;
3141 ErrorResult rv;
3142 rootSH->Go(-1, aRequireUserInteraction, aUserActivation, rv);
3143 return rv.StealNSResult();
3144}
3145
3146NS_IMETHODIMPnsresult
3147nsDocShell::GoForward(bool aRequireUserInteraction, bool aUserActivation) {
3148 if (!IsNavigationAllowed()) {
3149 return NS_OK; // JS may not handle returning of an error code
3150 }
3151
3152 auto cleanupIsNavigating = MakeScopeExit([&]() { mIsNavigating = false; });
3153 mIsNavigating = true;
3154
3155 RefPtr<ChildSHistory> rootSH = GetRootSessionHistory();
3156 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"
, 3156); return NS_ERROR_FAILURE; } } while (false)
;
3157 ErrorResult rv;
3158 rootSH->Go(1, aRequireUserInteraction, aUserActivation, rv);
3159 return rv.StealNSResult();
3160}
3161
3162// XXX(nika): We may want to stop exposing this API in the child process? Going
3163// to a specific index from multiple different processes could definitely race.
3164NS_IMETHODIMPnsresult
3165nsDocShell::GotoIndex(int32_t aIndex, bool aUserActivation) {
3166 if (!IsNavigationAllowed()) {
3167 return NS_OK; // JS may not handle returning of an error code
3168 }
3169
3170 auto cleanupIsNavigating = MakeScopeExit([&]() { mIsNavigating = false; });
3171 mIsNavigating = true;
3172
3173 RefPtr<ChildSHistory> rootSH = GetRootSessionHistory();
3174 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"
, 3174); return NS_ERROR_FAILURE; } } while (false)
;
3175
3176 ErrorResult rv;
3177 rootSH->GotoIndex(aIndex, aIndex - rootSH->Index(), false, aUserActivation,
3178 rv);
3179 return rv.StealNSResult();
3180}
3181
3182nsresult nsDocShell::LoadURI(nsIURI* aURI,
3183 const LoadURIOptions& aLoadURIOptions) {
3184 if (!IsNavigationAllowed()) {
3185 return NS_OK; // JS may not handle returning of an error code
3186 }
3187 RefPtr<nsDocShellLoadState> loadState;
3188 nsresult rv = nsDocShellLoadState::CreateFromLoadURIOptions(
3189 mBrowsingContext, aURI, aLoadURIOptions, getter_AddRefs(loadState));
3190 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"
, 3190); AnnotateMozCrashReason("MOZ_ASSERT" "(" "rv != NS_ERROR_MALFORMED_URI"
")"); do { *((volatile int*)__null) = 3190; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3191 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) || !loadState) {
3192 return NS_ERROR_FAILURE;
3193 }
3194
3195 return LoadURI(loadState, true);
3196}
3197
3198NS_IMETHODIMPnsresult
3199nsDocShell::LoadURIFromScript(nsIURI* aURI,
3200 JS::Handle<JS::Value> aLoadURIOptions,
3201 JSContext* aCx) {
3202 // generate dictionary for aLoadURIOptions and forward call
3203 LoadURIOptions loadURIOptions;
3204 if (!loadURIOptions.Init(aCx, aLoadURIOptions)) {
3205 return NS_ERROR_INVALID_ARG;
3206 }
3207 return LoadURI(aURI, loadURIOptions);
3208}
3209
3210nsresult nsDocShell::FixupAndLoadURIString(
3211 const nsAString& aURIString, const LoadURIOptions& aLoadURIOptions) {
3212 if (!IsNavigationAllowed()) {
3213 return NS_OK; // JS may not handle returning of an error code
3214 }
3215
3216 RefPtr<nsDocShellLoadState> loadState;
3217 nsresult rv = nsDocShellLoadState::CreateFromLoadURIOptions(
3218 mBrowsingContext, aURIString, aLoadURIOptions, getter_AddRefs(loadState));
3219
3220 uint32_t loadFlags = aLoadURIOptions.mLoadFlags;
3221 if (NS_ERROR_MALFORMED_URI == rv) {
3222 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)
3223 ("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)
3224 "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)
3225 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)
;
3226
3227 // We need to store a session history entry. We don't have a valid URI, so
3228 // we use about:blank instead.
3229 nsCOMPtr<nsIURI> uri;
3230 MOZ_ALWAYS_SUCCEEDS(NS_NewURI(getter_AddRefs(uri), "about:blank"_ns))do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(NS_NewURI(getter_AddRefs(uri), "about:blank"_ns))), 1)))), 1
))) { } else { do { static_assert( mozilla::detail::AssertionConditionType
<decltype(false)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("false" " (" "NS_SUCCEEDED(NS_NewURI(getter_AddRefs(uri), \"about:blank\"_ns))"
")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 3230); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "false"
") (" "NS_SUCCEEDED(NS_NewURI(getter_AddRefs(uri), \"about:blank\"_ns))"
")"); do { *((volatile int*)__null) = 3230; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
3231 nsCOMPtr<nsIPrincipal> triggeringPrincipal;
3232 if (aLoadURIOptions.mTriggeringPrincipal) {
3233 triggeringPrincipal = aLoadURIOptions.mTriggeringPrincipal;
3234 } else {
3235 triggeringPrincipal = nsContentUtils::GetSystemPrincipal();
3236 }
3237 if (mozilla::SessionHistoryInParent()) {
3238 mActiveEntry = MakeUnique<SessionHistoryInfo>(
3239 uri, triggeringPrincipal, nullptr, nullptr, nullptr,
3240 nsLiteralCString("text/html"));
3241 mBrowsingContext->SetActiveSessionHistoryEntry(
3242 Nothing(), mActiveEntry.get(), MAKE_LOAD_TYPE(LOAD_NORMAL, loadFlags)((LOAD_NORMAL) | ((loadFlags) << 16)),
3243 /* aUpdatedCacheKey = */ 0);
3244 }
3245 if (DisplayLoadError(rv, nullptr, PromiseFlatStringTPromiseFlatString<char16_t>(aURIString).get(),
3246 nullptr) &&
3247 (loadFlags & LOAD_FLAGS_ERROR_LOAD_CHANGES_RV) != 0) {
3248 return NS_ERROR_LOAD_SHOWED_ERRORPAGE;
3249 }
3250 }
3251
3252 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) || !loadState) {
3253 return NS_ERROR_FAILURE;
3254 }
3255
3256 return LoadURI(loadState, true);
3257}
3258
3259NS_IMETHODIMPnsresult
3260nsDocShell::FixupAndLoadURIStringFromScript(
3261 const nsAString& aURIString, JS::Handle<JS::Value> aLoadURIOptions,
3262 JSContext* aCx) {
3263 // generate dictionary for aLoadURIOptions and forward call
3264 LoadURIOptions loadURIOptions;
3265 if (!loadURIOptions.Init(aCx, aLoadURIOptions)) {
3266 return NS_ERROR_INVALID_ARG;
3267 }
3268 return FixupAndLoadURIString(aURIString, loadURIOptions);
3269}
3270
3271void nsDocShell::UnblockEmbedderLoadEventForFailure(bool aFireFrameErrorEvent) {
3272 // If we're not in a content frame, or are at a BrowsingContext tree boundary,
3273 // such as the content-chrome boundary, don't fire the error event.
3274 if (mBrowsingContext->IsTopContent() || mBrowsingContext->IsChrome()) {
3275 return;
3276 }
3277
3278 // If embedder is same-process, then unblocking the load event is already
3279 // handled by nsDocLoader. Fire the error event on our embedder element if
3280 // requested.
3281 //
3282 // XXX: Bug 1440212 is looking into potentially changing this behaviour to act
3283 // more like the remote case when in-process.
3284 RefPtr<Element> element = mBrowsingContext->GetEmbedderElement();
3285 if (element) {
3286 if (aFireFrameErrorEvent) {
3287 if (RefPtr<nsFrameLoaderOwner> flo = do_QueryObject(element)) {
3288 if (RefPtr<nsFrameLoader> fl = flo->GetFrameLoader()) {
3289 fl->FireErrorEvent();
3290 }
3291 }
3292 }
3293 return;
3294 }
3295
3296 // If we have a cross-process parent document, we must notify it that we no
3297 // longer block its load event. This is necessary for OOP sub-documents
3298 // because error documents do not result in a call to
3299 // SendMaybeFireEmbedderLoadEvents via any of the normal call paths.
3300 // (Obviously, we must do this before any of the returns below.)
3301 RefPtr<BrowserChild> browserChild = BrowserChild::GetFrom(this);
3302 if (browserChild &&
3303 !mBrowsingContext->GetParentWindowContext()->IsInProcess()) {
3304 mozilla::Unused << browserChild->SendMaybeFireEmbedderLoadEvents(
3305 aFireFrameErrorEvent ? EmbedderElementEventType::ErrorEvent
3306 : EmbedderElementEventType::NoEvent);
3307 }
3308}
3309
3310NS_IMETHODIMPnsresult
3311nsDocShell::DisplayLoadError(nsresult aError, nsIURI* aURI,
3312 const char16_t* aURL, nsIChannel* aFailedChannel,
3313 bool* aDisplayedErrorPage) {
3314 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
)
3315 ("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
)
3316 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
)
;
3317
3318 *aDisplayedErrorPage = false;
3319 // Get prompt and string bundle services
3320 nsCOMPtr<nsIPrompt> prompter;
3321 nsCOMPtr<nsIStringBundle> stringBundle;
3322 GetPromptAndStringBundle(getter_AddRefs(prompter),
3323 getter_AddRefs(stringBundle));
3324
3325 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"
, 3325); return NS_ERROR_FAILURE; } } while (false)
;
3326 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"
, 3326); return NS_ERROR_FAILURE; } } while (false)
;
3327
3328 const char* error = nullptr;
3329 // The key used to select the appropriate error message from the properties
3330 // file.
3331 const char* errorDescriptionID = nullptr;
3332 AutoTArray<nsString, 3> formatStrs;
3333 bool addHostPort = false;
3334 bool isBadStsCertError = false;
3335 nsresult rv = NS_OK;
3336 nsAutoString messageStr;
3337 nsAutoCString cssClass;
3338 nsAutoCString errorPage;
3339
3340 errorPage.AssignLiteral("neterror");
3341
3342 // Turn the error code into a human readable error message.
3343 if (NS_ERROR_UNKNOWN_PROTOCOL == aError) {
3344 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"
, 3344); return NS_ERROR_INVALID_POINTER; } } while (false)
;
3345
3346 // Extract the schemes into a comma delimited list.
3347 nsAutoCString scheme;
3348 aURI->GetScheme(scheme);
3349 CopyASCIItoUTF16(scheme, *formatStrs.AppendElement());
3350 nsCOMPtr<nsINestedURI> nestedURI = do_QueryInterface(aURI);
3351 while (nestedURI) {
3352 nsCOMPtr<nsIURI> tempURI;
3353 nsresult rv2;
3354 rv2 = nestedURI->GetInnerURI(getter_AddRefs(tempURI));
3355 if (NS_SUCCEEDED(rv2)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv2)), 1))) && tempURI) {
3356 tempURI->GetScheme(scheme);
3357 formatStrs[0].AppendLiteral(", ");
3358 AppendASCIItoUTF16(scheme, formatStrs[0]);
3359 }
3360 nestedURI = do_QueryInterface(tempURI);
3361 }
3362 error = "unknownProtocolFound";
3363 } else if (NS_ERROR_FILE_NOT_FOUND == aError) {
3364 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"
, 3364); return NS_ERROR_INVALID_POINTER; } } while (false)
;
3365 error = "fileNotFound";
3366 } else if (NS_ERROR_FILE_ACCESS_DENIED == aError) {
3367 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"
, 3367); return NS_ERROR_INVALID_POINTER; } } while (false)
;
3368 error = "fileAccessDenied";
3369 } else if (NS_ERROR_UNKNOWN_HOST == aError) {
3370 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"
, 3370); return NS_ERROR_INVALID_POINTER; } } while (false)
;
3371 // Get the host
3372 nsAutoCString host;
3373 nsCOMPtr<nsIURI> innermostURI = NS_GetInnermostURI(aURI);
3374 innermostURI->GetHost(host);
3375 CopyUTF8toUTF16(host, *formatStrs.AppendElement());
3376 errorDescriptionID = "dnsNotFound2";
3377 error = "dnsNotFound";
3378 } else if (NS_ERROR_CONNECTION_REFUSED == aError ||
3379 NS_ERROR_PROXY_BAD_GATEWAY == 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 = "connectionFailure";
3383 } else if (NS_ERROR_NET_INTERRUPT == aError) {
3384 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"
, 3384); return NS_ERROR_INVALID_POINTER; } } while (false)
;
3385 addHostPort = true;
3386 error = "netInterrupt";
3387 } else if (NS_ERROR_NET_TIMEOUT == aError ||
3388 NS_ERROR_PROXY_GATEWAY_TIMEOUT == aError ||
3389 NS_ERROR_NET_TIMEOUT_EXTERNAL == aError) {
3390 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"
, 3390); return NS_ERROR_INVALID_POINTER; } } while (false)
;
3391 // Get the host
3392 nsAutoCString host;
3393 aURI->GetHost(host);
3394 CopyUTF8toUTF16(host, *formatStrs.AppendElement());
3395 error = "netTimeout";
3396 } else if (NS_ERROR_CSP_FRAME_ANCESTOR_VIOLATION == aError ||
3397 NS_ERROR_CSP_FORM_ACTION_VIOLATION == aError) {
3398 // CSP error
3399 cssClass.AssignLiteral("neterror");
3400 error = "cspBlocked";
3401 } else if (NS_ERROR_XFO_VIOLATION == aError) {
3402 // XFO error
3403 cssClass.AssignLiteral("neterror");
3404 error = "xfoBlocked";
3405 } else if (NS_ERROR_GET_MODULE(aError) == NS_ERROR_MODULE_SECURITY21) {
3406 nsCOMPtr<nsINSSErrorsService> nsserr =
3407 do_GetService(NS_NSS_ERRORS_SERVICE_CONTRACTID"@mozilla.org/nss_errors_service;1");
3408
3409 uint32_t errorClass;
3410 if (!nsserr || NS_FAILED(nsserr->GetErrorClass(aError, &errorClass))((bool)(__builtin_expect(!!(NS_FAILED_impl(nsserr->GetErrorClass
(aError, &errorClass))), 0)))
) {
3411 errorClass = nsINSSErrorsService::ERROR_CLASS_SSL_PROTOCOL;
3412 }
3413
3414 nsCOMPtr<nsITransportSecurityInfo> tsi;
3415 if (aFailedChannel) {
3416 aFailedChannel->GetSecurityInfo(getter_AddRefs(tsi));
3417 }
3418 if (tsi) {
3419 uint32_t securityState;
3420 tsi->GetSecurityState(&securityState);
3421 if (securityState & nsIWebProgressListener::STATE_USES_SSL_3) {
3422 error = "sslv3Used";
3423 addHostPort = true;
3424 } else if (securityState &
3425 nsIWebProgressListener::STATE_USES_WEAK_CRYPTO) {
3426 error = "weakCryptoUsed";
Value stored to 'error' is never read
3427 addHostPort = true;
3428 }
3429 } else {
3430 // No channel, let's obtain the generic error message
3431 if (nsserr) {
3432 nsserr->GetErrorMessage(aError, messageStr);
3433 }
3434 }
3435 // We don't have a message string here anymore but DisplayLoadError
3436 // requires a non-empty messageStr.
3437 messageStr.Truncate();
3438 messageStr.AssignLiteral(u" ");
3439 if (errorClass == nsINSSErrorsService::ERROR_CLASS_BAD_CERT) {
3440 error = "nssBadCert";
3441
3442 // If this is an HTTP Strict Transport Security host or a pinned host
3443 // and the certificate is bad, don't allow overrides (RFC 6797 section
3444 // 12.1).
3445 bool isStsHost = false;
3446 bool isPinnedHost = false;
3447 OriginAttributes attrsForHSTS;
3448 if (aFailedChannel) {
3449 StoragePrincipalHelper::GetOriginAttributesForHSTS(aFailedChannel,
3450 attrsForHSTS);
3451 } else {
3452 attrsForHSTS = GetOriginAttributes();
3453 }
3454
3455 if (XRE_IsParentProcess()) {
3456 nsCOMPtr<nsISiteSecurityService> sss =
3457 do_GetService(NS_SSSERVICE_CONTRACTID"@mozilla.org/ssservice;1", &rv);
3458 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"
, 3458); return rv; } } while (false)
;
3459 rv = sss->IsSecureURI(aURI, attrsForHSTS, &isStsHost);
3460 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"
, 3460); return rv; } } while (false)
;
3461 } else {
3462 mozilla::dom::ContentChild* cc =
3463 mozilla::dom::ContentChild::GetSingleton();
3464 cc->SendIsSecureURI(aURI, attrsForHSTS, &isStsHost);
3465 }
3466 nsCOMPtr<nsIPublicKeyPinningService> pkps =
3467 do_GetService(NS_PKPSERVICE_CONTRACTID"@mozilla.org/security/publickeypinningservice;1", &rv);
3468 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"
, 3468); return rv; } } while (false)
;
3469 rv = pkps->HostHasPins(aURI, &isPinnedHost);
3470
3471 if (Preferences::GetBool("browser.xul.error_pages.expert_bad_cert",
3472 false)) {
3473 cssClass.AssignLiteral("expertBadCert");
3474 }
3475
3476 // HSTS/pinning takes precedence over the expert bad cert pref. We
3477 // never want to show the "Add Exception" button for these sites.
3478 // In the future we should differentiate between an HSTS host and a
3479 // pinned host and display a more informative message to the user.
3480 if (isStsHost || isPinnedHost) {
3481 isBadStsCertError = true;
3482 cssClass.AssignLiteral("badStsCert");
3483 }
3484
3485 errorPage.Assign("certerror");
3486 } else {
3487 error = "nssFailure2";
3488 }
3489 } else if (NS_ERROR_PHISHING_URI == aError ||
3490 NS_ERROR_MALWARE_URI == aError ||
3491 NS_ERROR_UNWANTED_URI == aError ||
3492 NS_ERROR_HARMFUL_URI == aError) {
3493 nsAutoCString host;
3494 aURI->GetHost(host);
3495 CopyUTF8toUTF16(host, *formatStrs.AppendElement());
3496
3497 // Malware and phishing detectors may want to use an alternate error
3498 // page, but if the pref's not set, we'll fall back on the standard page
3499 nsAutoCString alternateErrorPage;
3500 nsresult rv = Preferences::GetCString("urlclassifier.alternate_error_page",
3501 alternateErrorPage);
3502 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
3503 errorPage.Assign(alternateErrorPage);
3504 }
3505
3506 if (NS_ERROR_PHISHING_URI == aError) {
3507 error = "deceptiveBlocked";
3508 } else if (NS_ERROR_MALWARE_URI == aError) {
3509 error = "malwareBlocked";
3510 } else if (NS_ERROR_UNWANTED_URI == aError) {
3511 error = "unwantedBlocked";
3512 } else if (NS_ERROR_HARMFUL_URI == aError) {
3513 error = "harmfulBlocked";
3514 }
3515
3516 cssClass.AssignLiteral("blacklist");
3517 } else if (NS_ERROR_CONTENT_CRASHED == aError) {
3518 errorPage.AssignLiteral("tabcrashed");
3519 error = "tabcrashed";
3520
3521 RefPtr<EventTarget> handler = mChromeEventHandler;
3522 if (handler) {
3523 nsCOMPtr<Element> element = do_QueryInterface(handler);
3524 element->GetAttribute(u"crashedPageTitle"_ns, messageStr);
3525 }
3526
3527 // DisplayLoadError requires a non-empty messageStr to proceed and call
3528 // LoadErrorPage. If the page doesn't have a title, we will use a blank
3529 // space which will be trimmed and thus treated as empty by the front-end.
3530 if (messageStr.IsEmpty()) {
3531 messageStr.AssignLiteral(u" ");
3532 }
3533 } else if (NS_ERROR_FRAME_CRASHED == aError) {
3534 errorPage.AssignLiteral("framecrashed");
3535 error = "framecrashed";
3536 messageStr.AssignLiteral(u" ");
3537 } else if (NS_ERROR_BUILDID_MISMATCH == aError) {
3538 errorPage.AssignLiteral("restartrequired");
3539 error = "restartrequired";
3540
3541 // DisplayLoadError requires a non-empty messageStr to proceed and call
3542 // LoadErrorPage. If the page doesn't have a title, we will use a blank
3543 // space which will be trimmed and thus treated as empty by the front-end.
3544 if (messageStr.IsEmpty()) {
3545 messageStr.AssignLiteral(u" ");
3546 }
3547 } else {
3548 // Errors requiring simple formatting
3549 switch (aError) {
3550 case NS_ERROR_MALFORMED_URI:
3551 // URI is malformed
3552 error = "malformedURI";
3553 errorDescriptionID = "malformedURI2";
3554 break;
3555 case NS_ERROR_REDIRECT_LOOP:
3556 // Doc failed to load because the server generated too many redirects
3557 error = "redirectLoop";
3558 break;
3559 case NS_ERROR_UNKNOWN_SOCKET_TYPE:
3560 // Doc failed to load because PSM is not installed
3561 error = "unknownSocketType";
3562 break;
3563 case NS_ERROR_NET_RESET:
3564 // Doc failed to load because the server kept reseting the connection
3565 // before we could read any data from it
3566 error = "netReset";
3567 break;
3568 case NS_ERROR_DOCUMENT_NOT_CACHED:
3569 // Doc failed to load because the cache does not contain a copy of
3570 // the document.
3571 error = "notCached";
3572 break;
3573 case NS_ERROR_OFFLINE:
3574 // Doc failed to load because we are offline.
3575 error = "netOffline";
3576 break;
3577 case NS_ERROR_DOCUMENT_IS_PRINTMODE:
3578 // Doc navigation attempted while Printing or Print Preview
3579 error = "isprinting";
3580 break;
3581 case NS_ERROR_PORT_ACCESS_NOT_ALLOWED:
3582 // Port blocked for security reasons
3583 addHostPort = true;
3584 error = "deniedPortAccess";
3585 break;
3586 case NS_ERROR_UNKNOWN_PROXY_HOST:
3587 // Proxy hostname could not be resolved.
3588 error = "proxyResolveFailure";
3589 break;
3590 case NS_ERROR_PROXY_CONNECTION_REFUSED:
3591 case NS_ERROR_PROXY_FORBIDDEN:
3592 case NS_ERROR_PROXY_NOT_IMPLEMENTED:
3593 case NS_ERROR_PROXY_AUTHENTICATION_FAILED:
3594 case NS_ERROR_PROXY_TOO_MANY_REQUESTS:
3595 // Proxy connection was refused.
3596 error = "proxyConnectFailure";
3597 break;
3598 case NS_ERROR_INVALID_CONTENT_ENCODING:
3599 // Bad Content Encoding.
3600 error = "contentEncodingError";
3601 break;
3602 case NS_ERROR_UNSAFE_CONTENT_TYPE:
3603 // Channel refused to load from an unrecognized content type.
3604 error = "unsafeContentType";
3605 break;
3606 case NS_ERROR_CORRUPTED_CONTENT:
3607 // Broken Content Detected. e.g. Content-MD5 check failure.
3608 error = "corruptedContentErrorv2";
3609 break;
3610 case NS_ERROR_INTERCEPTION_FAILED:
3611 // ServiceWorker intercepted request, but something went wrong.
3612 error = "corruptedContentErrorv2";
3613 break;
3614 case NS_ERROR_NET_INADEQUATE_SECURITY:
3615 // Server negotiated bad TLS for HTTP/2.
3616 error = "inadequateSecurityError";
3617 addHostPort = true;
3618 break;
3619 case NS_ERROR_BLOCKED_BY_POLICY:
3620 case NS_ERROR_DOM_COOP_FAILED:
3621 case NS_ERROR_DOM_COEP_FAILED:
3622 // Page blocked by policy
3623 error = "blockedByPolicy";
3624 break;
3625 case NS_ERROR_NET_HTTP2_SENT_GOAWAY:
3626 case NS_ERROR_NET_HTTP3_PROTOCOL_ERROR:
3627 // HTTP/2 or HTTP/3 stack detected a protocol error
3628 error = "networkProtocolError";
3629 break;
3630
3631 default:
3632 break;
3633 }
3634 }
3635
3636 nsresult delegateErrorCode = aError;
3637 // If the HTTPS-Only Mode upgraded this request and the upgrade might have
3638 // caused this error, we replace the error-page with about:httpsonlyerror
3639 if (nsHTTPSOnlyUtils::CouldBeHttpsOnlyError(aFailedChannel, aError)) {
3640 errorPage.AssignLiteral("httpsonlyerror");
3641 delegateErrorCode = NS_ERROR_HTTPS_ONLY;
3642 } else if (isBadStsCertError) {
3643 delegateErrorCode = NS_ERROR_BAD_HSTS_CERT;
3644 }
3645
3646 if (nsCOMPtr<nsILoadURIDelegate> loadURIDelegate = GetLoadURIDelegate()) {
3647 nsCOMPtr<nsIURI> errorPageURI;
3648 rv = loadURIDelegate->HandleLoadError(
3649 aURI, delegateErrorCode, NS_ERROR_GET_MODULE(delegateErrorCode),
3650 getter_AddRefs(errorPageURI));
3651 // If the docshell is going away there's no point in showing an error page.
3652 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) || mIsBeingDestroyed) {
3653 *aDisplayedErrorPage = false;
3654 return NS_OK;
3655 }
3656
3657 if (errorPageURI) {
3658 *aDisplayedErrorPage =
3659 NS_SUCCEEDED(LoadErrorPage(errorPageURI, aURI, aFailedChannel))((bool)(__builtin_expect(!!(!NS_FAILED_impl(LoadErrorPage(errorPageURI
, aURI, aFailedChannel))), 1)))
;
3660 return NS_OK;
3661 }
3662 }
3663
3664 // Test if the error should be displayed
3665 if (!error) {
3666 return NS_OK;
3667 }
3668
3669 if (!errorDescriptionID) {
3670 errorDescriptionID = error;
3671 }
3672
3673 Telemetry::AccumulateCategoricalKeyed(
3674 IsSubframe() ? "frame"_ns : "top"_ns,
3675 mozilla::dom::LoadErrorToTelemetryLabel(aError));
3676
3677 // Test if the error needs to be formatted
3678 if (!messageStr.IsEmpty()) {
3679 // already obtained message
3680 } else {
3681 if (addHostPort) {
3682 // Build up the host:port string.
3683 nsAutoCString hostport;
3684 if (aURI) {
3685 aURI->GetHostPort(hostport);
3686 } else {
3687 hostport.Assign('?');
3688 }
3689 CopyUTF8toUTF16(hostport, *formatStrs.AppendElement());
3690 }
3691
3692 nsAutoCString spec;
3693 rv = NS_ERROR_NOT_AVAILABLE;
3694 auto& nextFormatStr = *formatStrs.AppendElement();
3695 if (aURI) {
3696 // displaying "file://" is aesthetically unpleasing and could even be
3697 // confusing to the user
3698 if (SchemeIsFile(aURI)) {
3699 aURI->GetPathQueryRef(spec);
3700 } else {
3701 aURI->GetSpec(spec);
3702 }
3703
3704 nsCOMPtr<nsITextToSubURI> textToSubURI(
3705 do_GetService(NS_ITEXTTOSUBURI_CONTRACTID"@mozilla.org/intl/texttosuburi;1", &rv));
3706 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
3707 rv = textToSubURI->UnEscapeURIForUI(spec, nextFormatStr);
3708 }
3709 } else {
3710 spec.Assign('?');
3711 }
3712 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3713 CopyUTF8toUTF16(spec, nextFormatStr);
3714 }
3715 rv = NS_OK;
3716
3717 nsAutoString str;
3718 rv =
3719 stringBundle->FormatStringFromName(errorDescriptionID, formatStrs, str);
3720 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"
, 3720); return rv; } } while (false)
;
3721 messageStr.Assign(str);
3722 }
3723
3724 // Display the error as a page or an alert prompt
3725 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"
, 3725); return NS_ERROR_FAILURE; } } while (false)
;
3726
3727 if ((NS_ERROR_NET_INTERRUPT == aError || NS_ERROR_NET_RESET == aError) &&
3728 SchemeIsHTTPS(aURI)) {
3729 // Maybe TLS intolerant. Treat this as an SSL error.
3730 error = "nssFailure2";
3731 }
3732
3733 if (mBrowsingContext->GetUseErrorPages()) {
3734 // Display an error page
3735 nsresult loadedPage =
3736 LoadErrorPage(aURI, aURL, errorPage.get(), error, messageStr.get(),
3737 cssClass.get(), aFailedChannel);
3738 *aDisplayedErrorPage = NS_SUCCEEDED(loadedPage)((bool)(__builtin_expect(!!(!NS_FAILED_impl(loadedPage)), 1))
)
;
3739 } else {
3740 // The prompter reqires that our private window has a document (or it
3741 // asserts). Satisfy that assertion now since GetDoc will force
3742 // creation of one if it hasn't already been created.
3743 if (mScriptGlobal) {
3744 Unused << mScriptGlobal->GetDoc();
3745 }
3746
3747 // Display a message box
3748 prompter->Alert(nullptr, messageStr.get());
3749 }
3750
3751 return NS_OK;
3752}
3753
3754#define PREF_SAFEBROWSING_ALLOWOVERRIDE"browser.safebrowsing.allowOverride" "browser.safebrowsing.allowOverride"
3755
3756nsresult nsDocShell::LoadErrorPage(nsIURI* aURI, const char16_t* aURL,
3757 const char* aErrorPage,
3758 const char* aErrorType,
3759 const char16_t* aDescription,
3760 const char* aCSSClass,
3761 nsIChannel* aFailedChannel) {
3762 if (mIsBeingDestroyed) {
3763 return NS_ERROR_NOT_AVAILABLE;
3764 }
3765
3766#if defined(DEBUG1)
3767 if (MOZ_LOG_TEST(gDocShellLog, LogLevel::Debug)(__builtin_expect(!!(mozilla::detail::log_test(gDocShellLog, LogLevel
::Debug)), 0))
) {
3768 nsAutoCString chanName;
3769 if (aFailedChannel) {
3770 aFailedChannel->GetName(chanName);
3771 } else {
3772 chanName.AssignLiteral("<no channel>");
3773 }
3774
3775 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)
3776 ("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)
3777 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)
3778 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)
;
3779 }
3780#endif
3781
3782 nsAutoCString url;
3783 if (aURI) {
3784 nsresult rv = aURI->GetSpec(url);
3785 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"
, 3785); return rv; } } while (false)
;
3786 } else if (aURL) {
3787 CopyUTF16toUTF8(MakeStringSpan(aURL), url);
3788 } else {
3789 return NS_ERROR_INVALID_POINTER;
3790 }
3791
3792 // Create a URL to pass all the error information through to the page.
3793
3794#undef SAFE_ESCAPE
3795#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"
, 3795)) { return NS_ERROR_OUT_OF_MEMORY; }
\
3796 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"
, 3796)
) { \
3797 return NS_ERROR_OUT_OF_MEMORY; \
3798 }
3799
3800 nsCString escapedUrl, escapedError, escapedDescription, escapedCSSClass;
3801 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"
, 3801)) { return NS_ERROR_OUT_OF_MEMORY; }
;
3802 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"
, 3802)) { return NS_ERROR_OUT_OF_MEMORY; }
;
3803 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"
, 3804)) { return NS_ERROR_OUT_OF_MEMORY; }
3804 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"
, 3804)) { return NS_ERROR_OUT_OF_MEMORY; }
;
3805 if (aCSSClass) {
3806 nsCString cssClass(aCSSClass);
3807 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"
, 3807)) { return NS_ERROR_OUT_OF_MEMORY; }
;
3808 }
3809 nsCString errorPageUrl("about:");
3810 errorPageUrl.AppendASCII(aErrorPage);
3811 errorPageUrl.AppendLiteral("?e=");
3812
3813 errorPageUrl.AppendASCII(escapedError.get());
3814 errorPageUrl.AppendLiteral("&u=");
3815 errorPageUrl.AppendASCII(escapedUrl.get());
3816 if ((strcmp(aErrorPage, "blocked") == 0) &&
3817 Preferences::GetBool(PREF_SAFEBROWSING_ALLOWOVERRIDE"browser.safebrowsing.allowOverride", true)) {
3818 errorPageUrl.AppendLiteral("&o=1");
3819 }
3820 if (!escapedCSSClass.IsEmpty()) {
3821 errorPageUrl.AppendLiteral("&s=");
3822 errorPageUrl.AppendASCII(escapedCSSClass.get());
3823 }
3824 errorPageUrl.AppendLiteral("&c=UTF-8");
3825
3826 nsCOMPtr<nsICaptivePortalService> cps = do_GetService(NS_CAPTIVEPORTAL_CID{ 0xbdbe0555, 0xfc3d, 0x4f7b, { 0x92, 0x05, 0xc3, 0x09, 0xce,
0xb2, 0xd6, 0x41 } }
);
3827 int32_t cpsState;
3828 if (cps && NS_SUCCEEDED(cps->GetState(&cpsState))((bool)(__builtin_expect(!!(!NS_FAILED_impl(cps->GetState(
&cpsState))), 1)))
&&
3829 cpsState == nsICaptivePortalService::LOCKED_PORTAL) {
3830 errorPageUrl.AppendLiteral("&captive=true");
3831 }
3832
3833 errorPageUrl.AppendLiteral("&d=");
3834 errorPageUrl.AppendASCII(escapedDescription.get());
3835
3836 nsCOMPtr<nsIURI> errorPageURI;
3837 nsresult rv = NS_NewURI(getter_AddRefs(errorPageURI), errorPageUrl);
3838 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"
, 3838); return rv; } } while (false)
;
3839
3840 return LoadErrorPage(errorPageURI, aURI, aFailedChannel);
3841}
3842
3843nsresult nsDocShell::LoadErrorPage(nsIURI* aErrorURI, nsIURI* aFailedURI,
3844 nsIChannel* aFailedChannel) {
3845 mFailedChannel = aFailedChannel;
3846 mFailedURI = aFailedURI;
3847 mFailedLoadType = mLoadType;
3848
3849 if (mLSHE) {
3850 // Abandon mLSHE's BFCache entry and create a new one. This way, if
3851 // we go back or forward to another SHEntry with the same doc
3852 // identifier, the error page won't persist.
3853 mLSHE->AbandonBFCacheEntry();
3854 }
3855
3856 RefPtr<nsDocShellLoadState> loadState = new nsDocShellLoadState(aErrorURI);
3857 loadState->SetTriggeringPrincipal(nsContentUtils::GetSystemPrincipal());
3858 if (mBrowsingContext) {
3859 loadState->SetTriggeringSandboxFlags(mBrowsingContext->GetSandboxFlags());
3860 loadState->SetTriggeringWindowId(
3861 mBrowsingContext->GetCurrentInnerWindowId());
3862 nsPIDOMWindowInner* innerWin = mScriptGlobal->GetCurrentInnerWindow();
3863 if (innerWin) {
3864 loadState->SetTriggeringStorageAccess(innerWin->UsingStorageAccess());
3865 }
3866 }
3867 loadState->SetLoadType(LOAD_ERROR_PAGE);
3868 loadState->SetFirstParty(true);
3869 loadState->SetSourceBrowsingContext(mBrowsingContext);
3870 if (mozilla::SessionHistoryInParent() && mLoadingEntry) {
3871 // We keep the loading entry for the load that failed here. If the user
3872 // reloads we want to try to reload the original load, not the error page.
3873 loadState->SetLoadingSessionHistoryInfo(
3874 MakeUnique<LoadingSessionHistoryInfo>(*mLoadingEntry));
3875 }
3876 return InternalLoad(loadState);
3877}
3878
3879NS_IMETHODIMPnsresult
3880nsDocShell::Reload(uint32_t aReloadFlags) {
3881 if (!IsNavigationAllowed()) {
3882 return NS_OK; // JS may not handle returning of an error code
3883 }
3884
3885 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"
, 3886); MOZ_PretendNoReturn(); } } while (0)
3886 "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"
, 3886); MOZ_PretendNoReturn(); } } while (0)
;
3887 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"
, 3888); MOZ_PretendNoReturn(); } } while (0)
3888 "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"
, 3888); MOZ_PretendNoReturn(); } } while (0)
;
3889
3890 uint32_t loadType = MAKE_LOAD_TYPE(LOAD_RELOAD_NORMAL, aReloadFlags)((LOAD_RELOAD_NORMAL) | ((aReloadFlags) << 16));
3891 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"
, 3891); return NS_ERROR_INVALID_ARG; } } while (false)
;
3892
3893 // Send notifications to the HistoryListener if any, about the impending
3894 // reload
3895 RefPtr<ChildSHistory> rootSH = GetRootSessionHistory();
3896 if (mozilla::SessionHistoryInParent()) {
3897 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)
;
3898 bool forceReload = IsForceReloadType(loadType);
3899 if (!XRE_IsParentProcess()) {
3900 ++mPendingReloadCount;
3901 RefPtr<nsDocShell> docShell(this);
3902 nsCOMPtr<nsIDocumentViewer> viewer(mDocumentViewer);
3903 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"
, 3903); return NS_ERROR_UNEXPECTED; } } while (false)
;
3904
3905 bool okToUnload = true;
3906 MOZ_TRY(viewer->PermitUnload(&okToUnload))do { auto mozTryTempResult_ = ::mozilla::ToResult(viewer->
PermitUnload(&okToUnload)); if ((__builtin_expect(!!(mozTryTempResult_
.isErr()), 0))) { return mozTryTempResult_.propagateErr(); } }
while (0)
;
3907 if (!okToUnload) {
3908 return NS_OK;
3909 }
3910
3911 RefPtr<Document> doc(GetDocument());
3912 RefPtr<BrowsingContext> browsingContext(mBrowsingContext);
3913 nsCOMPtr<nsIURI> currentURI(mCurrentURI);
3914 nsCOMPtr<nsIReferrerInfo> referrerInfo(mReferrerInfo);
3915 RefPtr<StopDetector> stopDetector = new StopDetector();
3916 nsCOMPtr<nsILoadGroup> loadGroup;
3917 GetLoadGroup(getter_AddRefs(loadGroup));
3918 if (loadGroup) {
3919 // loadGroup may be null in theory. In that case stopDetector just
3920 // doesn't do anything.
3921 loadGroup->AddRequest(stopDetector, nullptr);
3922 }
3923
3924 ContentChild::GetSingleton()->SendNotifyOnHistoryReload(
3925 mBrowsingContext, forceReload,
3926 [docShell, doc, loadType, browsingContext, currentURI, referrerInfo,
3927 loadGroup, stopDetector](
3928 std::tuple<bool, Maybe<NotNull<RefPtr<nsDocShellLoadState>>>,
3929 Maybe<bool>>&& aResult) {
3930 auto scopeExit = MakeScopeExit([loadGroup, stopDetector]() {
3931 if (loadGroup) {
3932 loadGroup->RemoveRequest(stopDetector, nullptr, NS_OK);
3933 }
3934 });
3935
3936 // Decrease mPendingReloadCount before any other early returns!
3937 if (--(docShell->mPendingReloadCount) > 0) {
3938 return;
3939 }
3940
3941 if (stopDetector->Canceled()) {
3942 return;
3943 }
3944 bool canReload;
3945 Maybe<NotNull<RefPtr<nsDocShellLoadState>>> loadState;
3946 Maybe<bool> reloadingActiveEntry;
3947
3948 std::tie(canReload, loadState, reloadingActiveEntry) = aResult;
3949
3950 if (!canReload) {
3951 return;
3952 }
3953
3954 if (loadState.isSome()) {
3955 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)
3956 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)
3957 ("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)
;
3958 loadState.ref()->SetNotifiedBeforeUnloadListeners(true);
3959 docShell->LoadHistoryEntry(loadState.ref(), loadType,
3960 reloadingActiveEntry.ref());
3961 } else {
3962 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)
3963 ("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)
;
3964 ReloadDocument(docShell, doc, loadType, browsingContext,
3965 currentURI, referrerInfo,
3966 /* aNotifiedBeforeUnloadListeners */ true);
3967 }
3968 },
3969 [](mozilla::ipc::ResponseRejectReason) {});
3970 } else {
3971 // Parent process
3972 bool canReload = false;
3973 Maybe<NotNull<RefPtr<nsDocShellLoadState>>> loadState;
3974 Maybe<bool> reloadingActiveEntry;
3975 if (!mBrowsingContext->IsDiscarded()) {
3976 mBrowsingContext->Canonical()->NotifyOnHistoryReload(
3977 forceReload, canReload, loadState, reloadingActiveEntry);
3978 }
3979 if (canReload) {
3980 if (loadState.isSome()) {
3981 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)
3982 ("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)
;
3983 LoadHistoryEntry(loadState.ref(), loadType,
3984 reloadingActiveEntry.ref());
3985 } else {
3986 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)
3987 ("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)
;
3988 RefPtr<Document> doc = GetDocument();
3989 RefPtr<BrowsingContext> bc = mBrowsingContext;
3990 nsCOMPtr<nsIURI> currentURI = mCurrentURI;
3991 nsCOMPtr<nsIReferrerInfo> referrerInfo = mReferrerInfo;
3992 ReloadDocument(this, doc, loadType, bc, currentURI, referrerInfo);
3993 }
3994 }
3995 }
3996 return NS_OK;
3997 }
3998
3999 bool canReload = true;
4000 if (rootSH) {
4001 rootSH->LegacySHistory()->NotifyOnHistoryReload(&canReload);
4002 }
4003
4004 if (!canReload) {
4005 return NS_OK;
4006 }
4007
4008 /* If you change this part of code, make sure bug 45297 does not re-occur */
4009 if (mOSHE) {
4010 nsCOMPtr<nsISHEntry> oshe = mOSHE;
4011 return LoadHistoryEntry(
4012 oshe, loadType,
4013 aReloadFlags & nsIWebNavigation::LOAD_FLAGS_USER_ACTIVATION);
4014 }
4015
4016 if (mLSHE) { // In case a reload happened before the current load is done
4017 nsCOMPtr<nsISHEntry> lshe = mLSHE;
4018 return LoadHistoryEntry(
4019 lshe, loadType,
4020 aReloadFlags & nsIWebNavigation::LOAD_FLAGS_USER_ACTIVATION);
4021 }
4022
4023 RefPtr<Document> doc = GetDocument();
4024 RefPtr<BrowsingContext> bc = mBrowsingContext;
4025 nsCOMPtr<nsIURI> currentURI = mCurrentURI;
4026 nsCOMPtr<nsIReferrerInfo> referrerInfo = mReferrerInfo;
4027 return ReloadDocument(this, doc, loadType, bc, currentURI, referrerInfo);
4028}
4029
4030/* static */
4031nsresult nsDocShell::ReloadDocument(nsDocShell* aDocShell, Document* aDocument,
4032 uint32_t aLoadType,
4033 BrowsingContext* aBrowsingContext,
4034 nsIURI* aCurrentURI,
4035 nsIReferrerInfo* aReferrerInfo,
4036 bool aNotifiedBeforeUnloadListeners) {
4037 if (!aDocument) {
4038 return NS_OK;
4039 }
4040
4041 // Do not inherit owner from document
4042 uint32_t flags = INTERNAL_LOAD_FLAGS_NONE;
4043 nsAutoString srcdoc;
4044 nsIURI* baseURI = nullptr;
4045 nsCOMPtr<nsIURI> originalURI;
4046 nsCOMPtr<nsIURI> resultPrincipalURI;
4047 bool loadReplace = false;
4048
4049 nsIPrincipal* triggeringPrincipal = aDocument->NodePrincipal();
4050 nsCOMPtr<nsIContentSecurityPolicy> csp = aDocument->GetCsp();
4051 uint32_t triggeringSandboxFlags = aDocument->GetSandboxFlags();
4052 uint64_t triggeringWindowId = aDocument->InnerWindowID();
4053 bool triggeringStorageAccess = aDocument->UsingStorageAccess();
4054
4055 nsAutoString contentTypeHint;
4056 aDocument->GetContentType(contentTypeHint);
4057
4058 if (aDocument->IsSrcdocDocument()) {
4059 aDocument->GetSrcdocData(srcdoc);
4060 flags |= INTERNAL_LOAD_FLAGS_IS_SRCDOC;
4061 baseURI = aDocument->GetBaseURI();
4062 } else {
4063 srcdoc = VoidString();
4064 }
4065 nsCOMPtr<nsIChannel> chan = aDocument->GetChannel();
4066 if (chan) {
4067 uint32_t loadFlags;
4068 chan->GetLoadFlags(&loadFlags);
4069 loadReplace = loadFlags & nsIChannel::LOAD_REPLACE;
4070 nsCOMPtr<nsIHttpChannel> httpChan(do_QueryInterface(chan));
4071 if (httpChan) {
4072 httpChan->GetOriginalURI(getter_AddRefs(originalURI));
4073 }
4074
4075 nsCOMPtr<nsILoadInfo> loadInfo = chan->LoadInfo();
4076 loadInfo->GetResultPrincipalURI(getter_AddRefs(resultPrincipalURI));
4077 }
4078
4079 if (!triggeringPrincipal) {
4080 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"
, 4080); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"Reload needs a valid triggeringPrincipal" ")"); do { *((volatile
int*)__null) = 4080; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
4081 return NS_ERROR_FAILURE;
4082 }
4083
4084 // Stack variables to ensure changes to the member variables don't affect to
4085 // the call.
4086 nsCOMPtr<nsIURI> currentURI = aCurrentURI;
4087
4088 // Reload always rewrites result principal URI.
4089 Maybe<nsCOMPtr<nsIURI>> emplacedResultPrincipalURI;
4090 emplacedResultPrincipalURI.emplace(std::move(resultPrincipalURI));
4091
4092 RefPtr<WindowContext> context = aBrowsingContext->GetCurrentWindowContext();
4093 RefPtr<nsDocShellLoadState> loadState = new nsDocShellLoadState(currentURI);
4094 loadState->SetReferrerInfo(aReferrerInfo);
4095 loadState->SetOriginalURI(originalURI);
4096 loadState->SetMaybeResultPrincipalURI(emplacedResultPrincipalURI);
4097 loadState->SetLoadReplace(loadReplace);
4098 loadState->SetTriggeringPrincipal(triggeringPrincipal);
4099 loadState->SetTriggeringSandboxFlags(triggeringSandboxFlags);
4100 loadState->SetTriggeringWindowId(triggeringWindowId);
4101 loadState->SetTriggeringStorageAccess(triggeringStorageAccess);
4102 loadState->SetPrincipalToInherit(triggeringPrincipal);
4103 loadState->SetCsp(csp);
4104 loadState->SetInternalLoadFlags(flags);
4105 loadState->SetTypeHint(NS_ConvertUTF16toUTF8(contentTypeHint));
4106 loadState->SetLoadType(aLoadType);
4107 loadState->SetFirstParty(true);
4108 loadState->SetSrcdocData(srcdoc);
4109 loadState->SetSourceBrowsingContext(aBrowsingContext);
4110 loadState->SetBaseURI(baseURI);
4111 loadState->SetHasValidUserGestureActivation(
4112 context && context->HasValidTransientUserGestureActivation());
4113
4114 loadState->SetTextDirectiveUserActivation(
4115 aDocument->ConsumeTextDirectiveUserActivation() ||
4116 loadState->HasValidUserGestureActivation());
4117
4118 loadState->SetNotifiedBeforeUnloadListeners(aNotifiedBeforeUnloadListeners);
4119 return aDocShell->InternalLoad(loadState);
4120}
4121
4122NS_IMETHODIMPnsresult
4123nsDocShell::Stop(uint32_t aStopFlags) {
4124 // Revoke any pending event related to content viewer restoration
4125 mRestorePresentationEvent.Revoke();
4126
4127 if (mLoadType == LOAD_ERROR_PAGE) {
4128 if (mLSHE) {
4129 // Since error page loads never unset mLSHE, do so now
4130 SetHistoryEntryAndUpdateBC(Some(nullptr), Some<nsISHEntry*>(mLSHE));
4131 }
4132 mActiveEntryIsLoadingFromSessionHistory = false;
4133
4134 mFailedChannel = nullptr;
4135 mFailedURI = nullptr;
4136 }
4137
4138 if (nsIWebNavigation::STOP_CONTENT & aStopFlags) {
4139 // Stop the document loading and animations
4140 if (mDocumentViewer) {
4141 nsCOMPtr<nsIDocumentViewer> viewer = mDocumentViewer;
4142 viewer->Stop();
4143 }
4144 } else if (nsIWebNavigation::STOP_NETWORK & aStopFlags) {
4145 // Stop the document loading only
4146 if (mDocumentViewer) {
4147 RefPtr<Document> doc = mDocumentViewer->GetDocument();
4148 if (doc) {
4149 doc->StopDocumentLoad();
4150 }
4151 }
4152 }
4153
4154 if (nsIWebNavigation::STOP_NETWORK & aStopFlags) {
4155 // Suspend any timers that were set for this loader. We'll clear
4156 // them out for good in CreateDocumentViewer.
4157 if (mRefreshURIList) {
4158 SuspendRefreshURIs();
4159 mSavedRefreshURIList.swap(mRefreshURIList);
4160 mRefreshURIList = nullptr;
4161 }
4162
4163 // XXXbz We could also pass |this| to nsIURILoader::Stop. That will
4164 // just call Stop() on us as an nsIDocumentLoader... We need fewer
4165 // redundant apis!
4166 Stop();
4167
4168 // Clear out mChannelToDisconnectOnPageHide. This page won't go in the
4169 // BFCache now, and the Stop above will have removed the DocumentChannel
4170 // from the loadgroup.
4171 mChannelToDisconnectOnPageHide = 0;
4172 }
4173
4174 for (auto* child : mChildList.ForwardRange()) {
4175 nsCOMPtr<nsIWebNavigation> shellAsNav(do_QueryObject(child));
4176 if (shellAsNav) {
4177 shellAsNav->Stop(aStopFlags);
4178 }
4179 }
4180
4181 return NS_OK;
4182}
4183
4184NS_IMETHODIMPnsresult
4185nsDocShell::GetDocument(Document** aDocument) {
4186 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"
, 4186); return NS_ERROR_INVALID_POINTER; } } while (false)
;
4187 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"
, 4187); return NS_ERROR_FAILURE; } } while (false)
;
4188
4189 RefPtr<Document> doc = mDocumentViewer->GetDocument();
4190 if (!doc) {
4191 return NS_ERROR_NOT_AVAILABLE;
4192 }
4193
4194 doc.forget(aDocument);
4195 return NS_OK;
4196}
4197
4198NS_IMETHODIMPnsresult
4199nsDocShell::GetCurrentURI(nsIURI** aURI) {
4200 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"
, 4200); return NS_ERROR_INVALID_POINTER; } } while (false)
;
4201
4202 nsCOMPtr<nsIURI> uri = mCurrentURI;
4203 uri.forget(aURI);
4204 return NS_OK;
4205}
4206
4207NS_IMETHODIMPnsresult
4208nsDocShell::GetSessionHistoryXPCOM(nsISupports** aSessionHistory) {
4209 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"
, 4209); return NS_ERROR_INVALID_POINTER; } } while (false)
;
4210 RefPtr<ChildSHistory> shistory = GetSessionHistory();
4211 shistory.forget(aSessionHistory);
4212 return NS_OK;
4213}
4214
4215//*****************************************************************************
4216// nsDocShell::nsIWebPageDescriptor
4217//*****************************************************************************
4218
4219NS_IMETHODIMPnsresult
4220nsDocShell::LoadPageAsViewSource(nsIDocShell* aOtherDocShell,
4221 const nsAString& aURI) {
4222 if (!aOtherDocShell) {
4223 return NS_ERROR_INVALID_POINTER;
4224 }
4225 nsCOMPtr<nsIURI> newURI;
4226 nsresult rv = NS_NewURI(getter_AddRefs(newURI), aURI);
4227 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
4228 return rv;
4229 }
4230
4231 RefPtr<nsDocShellLoadState> loadState;
4232 uint32_t cacheKey;
4233 auto* otherDocShell = nsDocShell::Cast(aOtherDocShell);
4234 if (mozilla::SessionHistoryInParent()) {
4235 loadState = new nsDocShellLoadState(newURI);
4236 if (!otherDocShell->FillLoadStateFromCurrentEntry(*loadState)) {
4237 return NS_ERROR_INVALID_POINTER;
4238 }
4239 cacheKey = otherDocShell->GetCacheKeyFromCurrentEntry().valueOr(0);
4240 } else {
4241 nsCOMPtr<nsISHEntry> entry;
4242 bool isOriginalSHE;
4243 otherDocShell->GetCurrentSHEntry(getter_AddRefs(entry), &isOriginalSHE);
4244 if (!entry) {
4245 return NS_ERROR_INVALID_POINTER;
4246 }
4247 rv = entry->CreateLoadInfo(getter_AddRefs(loadState));
4248 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"
, 4248); return rv; } } while (false)
;
4249 entry->GetCacheKey(&cacheKey);
4250 loadState->SetURI(newURI);
4251 loadState->SetSHEntry(nullptr);
4252 }
4253
4254 // We're doing a load of the page, via an API that
4255 // is only exposed to system code. The triggering principal for this load
4256 // should be the system principal.
4257 loadState->SetTriggeringPrincipal(nsContentUtils::GetSystemPrincipal());
4258 loadState->SetOriginalURI(nullptr);
4259 loadState->SetResultPrincipalURI(nullptr);
4260
4261 return InternalLoad(loadState, Some(cacheKey));
4262}
4263
4264NS_IMETHODIMPnsresult
4265nsDocShell::GetCurrentDescriptor(nsISupports** aPageDescriptor) {
4266 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"
, 4266); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPageDescriptor"
") (" "Null out param?" ")"); do { *((volatile int*)__null) =
4266; __attribute__((nomerge)) ::abort(); } while (false); }
} while (false)
;
4267
4268 *aPageDescriptor = nullptr;
4269
4270 nsISHEntry* src = mOSHE ? mOSHE : mLSHE;
4271 if (src) {
4272 nsCOMPtr<nsISHEntry> dest;
4273
4274 nsresult rv = src->Clone(getter_AddRefs(dest));
4275 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
4276 return rv;
4277 }
4278
4279 // null out inappropriate cloned attributes...
4280 dest->SetParent(nullptr);
4281 dest->SetIsSubFrame(false);
4282
4283 return CallQueryInterface(dest, aPageDescriptor);
4284 }
4285
4286 return NS_ERROR_NOT_AVAILABLE;
4287}
4288
4289already_AddRefed<nsIInputStream> nsDocShell::GetPostDataFromCurrentEntry()
4290 const {
4291 nsCOMPtr<nsIInputStream> postData;
4292 if (mozilla::SessionHistoryInParent()) {
4293 if (mActiveEntry) {
4294 postData = mActiveEntry->GetPostData();
4295 } else if (mLoadingEntry) {
4296 postData = mLoadingEntry->mInfo.GetPostData();
4297 }
4298 } else {
4299 if (mOSHE) {
4300 postData = mOSHE->GetPostData();
4301 } else if (mLSHE) {
4302 postData = mLSHE->GetPostData();
4303 }
4304 }
4305
4306 return postData.forget();
4307}
4308
4309Maybe<uint32_t> nsDocShell::GetCacheKeyFromCurrentEntry() const {
4310 if (mozilla::SessionHistoryInParent()) {
4311 if (mActiveEntry) {
4312 return Some(mActiveEntry->GetCacheKey());
4313 }
4314
4315 if (mLoadingEntry) {
4316 return Some(mLoadingEntry->mInfo.GetCacheKey());
4317 }
4318 } else {
4319 if (mOSHE) {
4320 return Some(mOSHE->GetCacheKey());
4321 }
4322
4323 if (mLSHE) {
4324 return Some(mLSHE->GetCacheKey());
4325 }
4326 }
4327
4328 return Nothing();
4329}
4330
4331bool nsDocShell::FillLoadStateFromCurrentEntry(
4332 nsDocShellLoadState& aLoadState) {
4333 if (mLoadingEntry) {
4334 mLoadingEntry->mInfo.FillLoadInfo(aLoadState);
4335 return true;
4336 }
4337 if (mActiveEntry) {
4338 mActiveEntry->FillLoadInfo(aLoadState);
4339 return true;
4340 }
4341 return false;
4342}
4343
4344//*****************************************************************************
4345// nsDocShell::nsIBaseWindow
4346//*****************************************************************************
4347
4348NS_IMETHODIMPnsresult
4349nsDocShell::InitWindow(nativeWindow aParentNativeWindow,
4350 nsIWidget* aParentWidget, int32_t aX, int32_t aY,
4351 int32_t aWidth, int32_t aHeight) {
4352 SetParentWidget(aParentWidget);
4353 SetPositionAndSize(aX, aY, aWidth, aHeight, 0);
4354 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"
, 4354); return NS_ERROR_FAILURE; } } while (false)
;
4355
4356 return NS_OK;
4357}
4358
4359NS_IMETHODIMPnsresult
4360nsDocShell::Destroy() {
4361 // XXX: We allow this function to be called just once. If you are going to
4362 // reset new variables in this function, please make sure the variables will
4363 // never be re-initialized. Adding assertions to check |mIsBeingDestroyed|
4364 // in the setter functions for the variables would be enough.
4365 if (mIsBeingDestroyed) {
4366 return NS_ERROR_DOCSHELL_DYING;
4367 }
4368
4369 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"
, 4370); MOZ_PretendNoReturn(); } } while (0)
4370 "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"
, 4370); MOZ_PretendNoReturn(); } } while (0)
;
4371
4372 nsCOMPtr<nsIObserverService> serv = services::GetObserverService();
4373 if (serv) {
4374 const char* msg = mItemType == typeContent
4375 ? NS_WEBNAVIGATION_DESTROY"webnavigation-destroy"
4376 : NS_CHROME_WEBNAVIGATION_DESTROY"chrome-webnavigation-destroy";
4377 serv->NotifyObservers(GetAsSupports(this), msg, nullptr);
4378 }
4379
4380 mIsBeingDestroyed = true;
4381
4382 // Brak the cycle with the initial client, if present.
4383 mInitialClientSource.reset();
4384
4385 // Make sure to blow away our mLoadingURI just in case. No loads
4386 // from inside this pagehide.
4387 mLoadingURI = nullptr;
4388
4389 // Fire unload event before we blow anything away.
4390 (void)FirePageHideNotification(true);
4391
4392 // Clear pointers to any detached nsEditorData that's lying
4393 // around in shistory entries. Breaks cycle. See bug 430921.
4394 if (mOSHE) {
4395 mOSHE->SetEditorData(nullptr);
4396 }
4397 if (mLSHE) {
4398 mLSHE->SetEditorData(nullptr);
4399 }
4400
4401 // Note: mContentListener can be null if Init() failed and we're being
4402 // called from the destructor.
4403 if (mContentListener) {
4404 mContentListener->DropDocShellReference();
4405 mContentListener->SetParentContentListener(nullptr);
4406 // Note that we do NOT set mContentListener to null here; that
4407 // way if someone tries to do a load in us after this point
4408 // the nsDSURIContentListener will block it. All of which
4409 // means that we should do this before calling Stop(), of
4410 // course.
4411 }
4412
4413 // Stop any URLs that are currently being loaded...
4414 Stop(nsIWebNavigation::STOP_ALL);
4415
4416 mEditorData = nullptr;
4417
4418 // Save the state of the current document, before destroying the window.
4419 // This is needed to capture the state of a frameset when the new document
4420 // causes the frameset to be destroyed...
4421 PersistLayoutHistoryState();
4422
4423 // Remove this docshell from its parent's child list
4424 nsCOMPtr<nsIDocShellTreeItem> docShellParentAsItem =
4425 do_QueryInterface(GetAsSupports(mParent));
4426 if (docShellParentAsItem) {
4427 docShellParentAsItem->RemoveChild(this);
4428 }
4429
4430 if (mDocumentViewer) {
4431 mDocumentViewer->Close(nullptr);
4432 mDocumentViewer->Destroy();
4433 mDocumentViewer = nullptr;
4434 }
4435
4436 nsDocLoader::Destroy();
4437
4438 mParentWidget = nullptr;
4439 SetCurrentURIInternal(nullptr);
4440
4441 if (mScriptGlobal) {
4442 mScriptGlobal->DetachFromDocShell(!mWillChangeProcess);
4443 mScriptGlobal = nullptr;
4444 }
4445
4446 if (GetSessionHistory()) {
4447 // We want to destroy these content viewers now rather than
4448 // letting their destruction wait for the session history
4449 // entries to get garbage collected. (Bug 488394)
4450 GetSessionHistory()->EvictLocalDocumentViewers();
4451 }
4452
4453 if (mWillChangeProcess && !mBrowsingContext->IsDiscarded()) {
4454 mBrowsingContext->PrepareForProcessChange();
4455 }
4456
4457 SetTreeOwner(nullptr);
4458
4459 mBrowserChild = nullptr;
4460
4461 mChromeEventHandler = nullptr;
4462
4463 // Cancel any timers that were set for this docshell; this is needed
4464 // to break the cycle between us and the timers.
4465 CancelRefreshURITimers();
4466
4467 return NS_OK;
4468}
4469
4470double nsDocShell::GetWidgetCSSToDeviceScale() {
4471 if (mParentWidget) {
4472 return mParentWidget->GetDefaultScale().scale;
4473 }
4474 if (nsCOMPtr<nsIBaseWindow> ownerWindow = do_QueryInterface(mTreeOwner)) {
4475 return ownerWindow->GetWidgetCSSToDeviceScale();
4476 }
4477 return 1.0;
4478}
4479
4480NS_IMETHODIMPnsresult
4481nsDocShell::GetDevicePixelsPerDesktopPixel(double* aScale) {
4482 if (mParentWidget) {
4483 *aScale = mParentWidget->GetDesktopToDeviceScale().scale;
4484 return NS_OK;
4485 }
4486
4487 nsCOMPtr<nsIBaseWindow> ownerWindow(do_QueryInterface(mTreeOwner));
4488 if (ownerWindow) {
4489 return ownerWindow->GetDevicePixelsPerDesktopPixel(aScale);
4490 }
4491
4492 *aScale = 1.0;
4493 return NS_OK;
4494}
4495
4496NS_IMETHODIMPnsresult
4497nsDocShell::SetPosition(int32_t aX, int32_t aY) {
4498 mBounds.MoveTo(aX, aY);
4499
4500 if (mDocumentViewer) {
4501 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"
, 4501); return NS_ERROR_FAILURE; } } while (false)
;
4502 }
4503
4504 return NS_OK;
4505}
4506
4507NS_IMETHODIMPnsresult
4508nsDocShell::SetPositionDesktopPix(int32_t aX, int32_t aY) {
4509 nsCOMPtr<nsIBaseWindow> ownerWindow(do_QueryInterface(mTreeOwner));
4510 if (ownerWindow) {
4511 return ownerWindow->SetPositionDesktopPix(aX, aY);
4512 }
4513
4514 double scale = 1.0;
4515 GetDevicePixelsPerDesktopPixel(&scale);
4516 return SetPosition(NSToIntRound(aX * scale), NSToIntRound(aY * scale));
4517}
4518
4519NS_IMETHODIMPnsresult
4520nsDocShell::GetPosition(int32_t* aX, int32_t* aY) {
4521 return GetPositionAndSize(aX, aY, nullptr, nullptr);
4522}
4523
4524NS_IMETHODIMPnsresult
4525nsDocShell::SetSize(int32_t aWidth, int32_t aHeight, bool aRepaint) {
4526 int32_t x = 0, y = 0;
4527 GetPosition(&x, &y);
4528 return SetPositionAndSize(x, y, aWidth, aHeight,
4529 aRepaint ? nsIBaseWindow::eRepaint : 0);
4530}
4531
4532NS_IMETHODIMPnsresult
4533nsDocShell::GetSize(int32_t* aWidth, int32_t* aHeight) {
4534 return GetPositionAndSize(nullptr, nullptr, aWidth, aHeight);
4535}
4536
4537NS_IMETHODIMPnsresult
4538nsDocShell::SetPositionAndSize(int32_t aX, int32_t aY, int32_t aWidth,
4539 int32_t aHeight, uint32_t aFlags) {
4540 mBounds.SetRect(aX, aY, aWidth, aHeight);
4541
4542 // Hold strong ref, since SetBounds can make us null out mDocumentViewer
4543 nsCOMPtr<nsIDocumentViewer> viewer = mDocumentViewer;
4544 if (viewer) {
4545 uint32_t cvflags = (aFlags & nsIBaseWindow::eDelayResize)
4546 ? nsIDocumentViewer::eDelayResize
4547 : 0;
4548 // XXX Border figured in here or is that handled elsewhere?
4549 nsresult rv = viewer->SetBoundsWithFlags(mBounds, cvflags);
4550 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"
, 4550); return NS_ERROR_FAILURE; } } while (false)
;
4551 }
4552
4553 return NS_OK;
4554}
4555
4556NS_IMETHODIMPnsresult
4557nsDocShell::GetPositionAndSize(int32_t* aX, int32_t* aY, int32_t* aWidth,
4558 int32_t* aHeight) {
4559 if (mParentWidget) {
4560 // ensure size is up-to-date if window has changed resolution
4561 LayoutDeviceIntRect r = mParentWidget->GetClientBounds();
4562 SetPositionAndSize(mBounds.X(), mBounds.Y(), r.Width(), r.Height(), 0);
4563 }
4564
4565 // We should really consider just getting this information from
4566 // our window instead of duplicating the storage and code...
4567 if (aWidth || aHeight) {
4568 // Caller wants to know our size; make sure to give them up to
4569 // date information.
4570 RefPtr<Document> doc(do_GetInterface(GetAsSupports(mParent)));
4571 if (doc) {
4572 doc->FlushPendingNotifications(FlushType::Layout);
4573 }
4574 }
4575
4576 DoGetPositionAndSize(aX, aY, aWidth, aHeight);
4577 return NS_OK;
4578}
4579
4580void nsDocShell::DoGetPositionAndSize(int32_t* aX, int32_t* aY, int32_t* aWidth,
4581 int32_t* aHeight) {
4582 if (aX) {
4583 *aX = mBounds.X();
4584 }
4585 if (aY) {
4586 *aY = mBounds.Y();
4587 }
4588 if (aWidth) {
4589 *aWidth = mBounds.Width();
4590 }
4591 if (aHeight) {
4592 *aHeight = mBounds.Height();
4593 }
4594}
4595
4596NS_IMETHODIMPnsresult
4597nsDocShell::SetDimensions(DimensionRequest&& aRequest) {
4598 return NS_ERROR_NOT_IMPLEMENTED;
4599}
4600
4601NS_IMETHODIMPnsresult
4602nsDocShell::GetDimensions(DimensionKind aDimensionKind, int32_t* aX,
4603 int32_t* aY, int32_t* aCX, int32_t* aCY) {
4604 return NS_ERROR_NOT_IMPLEMENTED;
4605}
4606
4607NS_IMETHODIMPnsresult
4608nsDocShell::Repaint(bool aForce) {
4609 PresShell* presShell = GetPresShell();
4610 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"
, 4610); return NS_ERROR_FAILURE; } } while (false)
;
4611
4612 RefPtr<nsViewManager> viewManager = presShell->GetViewManager();
4613 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"
, 4613); return NS_ERROR_FAILURE; } } while (false)
;
4614
4615 viewManager->InvalidateAllViews();
4616 return NS_OK;
4617}
4618
4619NS_IMETHODIMPnsresult
4620nsDocShell::GetParentWidget(nsIWidget** aParentWidget) {
4621 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"
, 4621); return NS_ERROR_INVALID_POINTER; } } while (false)
;
4622
4623 *aParentWidget = mParentWidget;
4624 NS_IF_ADDREF(*aParentWidget)ns_if_addref(*aParentWidget);
4625
4626 return NS_OK;
4627}
4628
4629NS_IMETHODIMPnsresult
4630nsDocShell::SetParentWidget(nsIWidget* aParentWidget) {
4631 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"
, 4631); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mIsBeingDestroyed"
")"); do { *((volatile int*)__null) = 4631; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4632 mParentWidget = aParentWidget;
4633
4634 return NS_OK;
4635}
4636
4637NS_IMETHODIMPnsresult
4638nsDocShell::GetParentNativeWindow(nativeWindow* aParentNativeWindow) {
4639 NS_ENSURE_ARG_POINTER(aParentNativeWindow)do { if ((__builtin_expect(!!(!(aParentNativeWindow)), 0))) {
NS_DebugBreak(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aParentNativeWindow"
") failed", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 4639); return NS_ERROR_INVALID_POINTER; } } while (false)
;
4640
4641 if (mParentWidget) {
4642 *aParentNativeWindow = mParentWidget->GetNativeData(NS_NATIVE_WIDGET3);
4643 } else {
4644 *aParentNativeWindow = nullptr;
4645 }
4646
4647 return NS_OK;
4648}
4649
4650NS_IMETHODIMPnsresult
4651nsDocShell::SetParentNativeWindow(nativeWindow aParentNativeWindow) {
4652 return NS_ERROR_NOT_IMPLEMENTED;
4653}
4654
4655NS_IMETHODIMPnsresult
4656nsDocShell::GetNativeHandle(nsAString& aNativeHandle) {
4657 // the nativeHandle should be accessed from nsIAppWindow
4658 return NS_ERROR_NOT_IMPLEMENTED;
4659}
4660
4661NS_IMETHODIMPnsresult
4662nsDocShell::GetVisibility(bool* aVisibility) {
4663 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"
, 4663); return NS_ERROR_INVALID_POINTER; } } while (false)
;
4664
4665 *aVisibility = false;
4666
4667 if (!mDocumentViewer) {
4668 return NS_OK;
4669 }
4670
4671 PresShell* presShell = GetPresShell();
4672 if (!presShell) {
4673 return NS_OK;
4674 }
4675
4676 // get the view manager
4677 nsViewManager* vm = presShell->GetViewManager();
4678 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"
, 4678); return NS_ERROR_FAILURE; } } while (false)
;
4679
4680 // get the root view
4681 nsView* view = vm->GetRootView(); // views are not ref counted
4682 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"
, 4682); return NS_ERROR_FAILURE; } } while (false)
;
4683
4684 // if our root view is hidden, we are not visible
4685 if (view->GetVisibility() == ViewVisibility::Hide) {
4686 return NS_OK;
4687 }
4688
4689 // otherwise, we must walk up the document and view trees checking
4690 // for a hidden view, unless we're an off screen browser, which
4691 // would make this test meaningless.
4692
4693 RefPtr<nsDocShell> docShell = this;
4694 RefPtr<nsDocShell> parentItem = docShell->GetInProcessParentDocshell();
4695 while (parentItem) {
4696 // Null-check for crash in bug 267804
4697 if (!parentItem->GetPresShell()) {
4698 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"
, 4698); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "parent docshell has null pres shell"
")"); do { *((volatile int*)__null) = 4698; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4699 return NS_OK;
4700 }
4701
4702 vm = docShell->GetPresShell()->GetViewManager();
4703 if (vm) {
4704 view = vm->GetRootView();
4705 }
4706
4707 if (view) {
4708 view = view->GetParent(); // anonymous inner view
4709 if (view) {
4710 view = view->GetParent(); // subdocumentframe's view
4711 }
4712 }
4713
4714 nsIFrame* frame = view ? view->GetFrame() : nullptr;
4715 if (frame && !frame->IsVisibleConsideringAncestors(
4716 nsIFrame::VISIBILITY_CROSS_CHROME_CONTENT_BOUNDARY)) {
4717 return NS_OK;
4718 }
4719
4720 docShell = parentItem;
4721 parentItem = docShell->GetInProcessParentDocshell();
4722 }
4723
4724 nsCOMPtr<nsIBaseWindow> treeOwnerAsWin(do_QueryInterface(mTreeOwner));
4725 if (!treeOwnerAsWin) {
4726 *aVisibility = true;
4727 return NS_OK;
4728 }
4729
4730 // Check with the tree owner as well to give embedders a chance to
4731 // expose visibility as well.
4732 nsresult rv = treeOwnerAsWin->GetVisibility(aVisibility);
4733 if (rv == NS_ERROR_NOT_IMPLEMENTED) {
4734 // The tree owner had no opinion on our visibility.
4735 *aVisibility = true;
4736 return NS_OK;
4737 }
4738 return rv;
4739}
4740
4741void nsDocShell::ActivenessMaybeChanged() {
4742 const bool isActive = mBrowsingContext->IsActive();
4743 if (RefPtr<PresShell> presShell = GetPresShell()) {
4744 presShell->ActivenessMaybeChanged();
4745 }
4746
4747 // Tell the window about it
4748 if (mScriptGlobal) {
4749 mScriptGlobal->SetIsBackground(!isActive);
4750 if (RefPtr<Document> doc = mScriptGlobal->GetExtantDoc()) {
4751 // Update orientation when the top-level browsing context becomes active.
4752 if (isActive && mBrowsingContext->IsTop()) {
4753 // We only care about the top-level browsing context.
4754 auto orientation = mBrowsingContext->GetOrientationLock();
4755 ScreenOrientation::UpdateActiveOrientationLock(orientation);
4756 }
4757
4758 doc->PostVisibilityUpdateEvent();
4759 }
4760 }
4761
4762 // Tell the nsDOMNavigationTiming about it
4763 RefPtr<nsDOMNavigationTiming> timing = mTiming;
4764 if (!timing && mDocumentViewer) {
4765 if (Document* doc = mDocumentViewer->GetDocument()) {
4766 timing = doc->GetNavigationTiming();
4767 }
4768 }
4769 if (timing) {
4770 timing->NotifyDocShellStateChanged(
4771 isActive ? nsDOMNavigationTiming::DocShellState::eActive
4772 : nsDOMNavigationTiming::DocShellState::eInactive);
4773 }
4774
4775 // Restart or stop meta refresh timers if necessary
4776 if (mDisableMetaRefreshWhenInactive) {
4777 if (isActive) {
4778 ResumeRefreshURIs();
4779 } else {
4780 SuspendRefreshURIs();
4781 }
4782 }
4783
4784 if (InputTaskManager::CanSuspendInputEvent()) {
4785 mBrowsingContext->Group()->UpdateInputTaskManagerIfNeeded(isActive);
4786 }
4787}
4788
4789NS_IMETHODIMPnsresult
4790nsDocShell::SetDefaultLoadFlags(uint32_t aDefaultLoadFlags) {
4791 if (!mWillChangeProcess) {
4792 // Intentionally ignoring handling discarded browsing contexts.
4793 Unused << mBrowsingContext->SetDefaultLoadFlags(aDefaultLoadFlags);
4794 } else {
4795 // Bug 1623565: DevTools tries to clean up defaultLoadFlags on
4796 // shutdown. Sorry DevTools, your DocShell is in another process.
4797 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"
, 4797)
;
4798 }
4799 return NS_OK;
4800}
4801
4802NS_IMETHODIMPnsresult
4803nsDocShell::GetDefaultLoadFlags(uint32_t* aDefaultLoadFlags) {
4804 *aDefaultLoadFlags = mBrowsingContext->GetDefaultLoadFlags();
4805 return NS_OK;
4806}
4807
4808NS_IMETHODIMPnsresult
4809nsDocShell::GetFailedChannel(nsIChannel** aFailedChannel) {
4810 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"
, 4810); return NS_ERROR_INVALID_POINTER; } } while (false)
;
4811 Document* doc = GetDocument();
4812 if (!doc) {
4813 *aFailedChannel = nullptr;
4814 return NS_OK;
4815 }
4816 NS_IF_ADDREF(*aFailedChannel = doc->GetFailedChannel())ns_if_addref(*aFailedChannel = doc->GetFailedChannel());
4817 return NS_OK;
4818}
4819
4820NS_IMETHODIMPnsresult
4821nsDocShell::SetVisibility(bool aVisibility) {
4822 // Show()/Hide() may change mDocumentViewer.
4823 nsCOMPtr<nsIDocumentViewer> viewer = mDocumentViewer;
4824 if (!viewer) {
4825 return NS_OK;
4826 }
4827 if (aVisibility) {
4828 viewer->Show();
4829 } else {
4830 viewer->Hide();
4831 }
4832
4833 return NS_OK;
4834}
4835
4836NS_IMETHODIMPnsresult
4837nsDocShell::GetEnabled(bool* aEnabled) {
4838 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"
, 4838); return NS_ERROR_INVALID_POINTER; } } while (false)
;
4839 *aEnabled = true;
4840 return NS_ERROR_NOT_IMPLEMENTED;
4841}
4842
4843NS_IMETHODIMPnsresult
4844nsDocShell::SetEnabled(bool aEnabled) { return NS_ERROR_NOT_IMPLEMENTED; }
4845
4846NS_IMETHODIMPnsresult
4847nsDocShell::GetMainWidget(nsIWidget** aMainWidget) {
4848 // We don't create our own widget, so simply return the parent one.
4849 return GetParentWidget(aMainWidget);
4850}
4851
4852NS_IMETHODIMPnsresult
4853nsDocShell::GetTitle(nsAString& aTitle) {
4854 aTitle = mTitle;
4855 return NS_OK;
4856}
4857
4858NS_IMETHODIMPnsresult
4859nsDocShell::SetTitle(const nsAString& aTitle) {
4860 // Avoid unnecessary updates of the title if the URI and the title haven't
4861 // changed.
4862 if (mTitleValidForCurrentURI && mTitle == aTitle) {
4863 return NS_OK;
4864 }
4865
4866 // Store local title
4867 mTitle = aTitle;
4868 mTitleValidForCurrentURI = true;
4869
4870 // When title is set on the top object it should then be passed to the
4871 // tree owner.
4872 if (mBrowsingContext->IsTop()) {
4873 nsCOMPtr<nsIBaseWindow> treeOwnerAsWin(do_QueryInterface(mTreeOwner));
4874 if (treeOwnerAsWin) {
4875 treeOwnerAsWin->SetTitle(aTitle);
4876 }
4877 }
4878
4879 if (mCurrentURI && mLoadType != LOAD_ERROR_PAGE) {
4880 UpdateGlobalHistoryTitle(mCurrentURI);
4881 }
4882
4883 // Update SessionHistory with the document's title.
4884 if (mLoadType != LOAD_BYPASS_HISTORY && mLoadType != LOAD_ERROR_PAGE) {
4885 SetTitleOnHistoryEntry(true);
4886 }
4887
4888 return NS_OK;
4889}
4890
4891void nsDocShell::SetTitleOnHistoryEntry(bool aUpdateEntryInSessionHistory) {
4892 if (mOSHE) {
4893 mOSHE->SetTitle(mTitle);
4894 }
4895
4896 if (mActiveEntry && mBrowsingContext) {
4897 mActiveEntry->SetTitle(mTitle);
4898 if (aUpdateEntryInSessionHistory) {
4899 if (XRE_IsParentProcess()) {
4900 SessionHistoryEntry* entry =
4901 mBrowsingContext->Canonical()->GetActiveSessionHistoryEntry();
4902 if (entry) {
4903 entry->SetTitle(mTitle);
4904 }
4905 } else {
4906 mozilla::Unused
4907 << ContentChild::GetSingleton()->SendSessionHistoryEntryTitle(
4908 mBrowsingContext, mTitle);
4909 }
4910 }
4911 }
4912}
4913
4914nsPoint nsDocShell::GetCurScrollPos() {
4915 nsPoint scrollPos;
4916 if (ScrollContainerFrame* sf = GetRootScrollContainerFrame()) {
4917 scrollPos = sf->GetVisualViewportOffset();
4918 }
4919 return scrollPos;
4920}
4921
4922nsresult nsDocShell::SetCurScrollPosEx(int32_t aCurHorizontalPos,
4923 int32_t aCurVerticalPos) {
4924 ScrollContainerFrame* sf = GetRootScrollContainerFrame();
4925 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"
, 4925); return NS_ERROR_FAILURE; } } while (false)
;
4926
4927 ScrollMode scrollMode =
4928 sf->IsSmoothScroll() ? ScrollMode::SmoothMsd : ScrollMode::Instant;
4929
4930 nsPoint targetPos(aCurHorizontalPos, aCurVerticalPos);
4931 sf->ScrollTo(targetPos, scrollMode);
4932
4933 // Set the visual viewport offset as well.
4934
4935 RefPtr<PresShell> presShell = GetPresShell();
4936 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"
, 4936); return NS_ERROR_FAILURE; } } while (false)
;
4937
4938 nsPresContext* presContext = presShell->GetPresContext();
4939 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"
, 4939); return NS_ERROR_FAILURE; } } while (false)
;
4940
4941 // Only the root content document can have a distinct visual viewport offset.
4942 if (!presContext->IsRootContentDocumentCrossProcess()) {
4943 return NS_OK;
4944 }
4945
4946 // Not on a platform with a distinct visual viewport - don't bother setting
4947 // the visual viewport offset.
4948 if (!presShell->IsVisualViewportSizeSet()) {
4949 return NS_OK;
4950 }
4951
4952 presShell->ScrollToVisual(targetPos, layers::FrameMetrics::eMainThread,
4953 scrollMode);
4954
4955 return NS_OK;
4956}
4957
4958void nsDocShell::SetScrollbarPreference(mozilla::ScrollbarPreference aPref) {
4959 if (mScrollbarPref == aPref) {
4960 return;
4961 }
4962 mScrollbarPref = aPref;
4963 auto* ps = GetPresShell();
4964 if (!ps) {
4965 return;
4966 }
4967 nsIFrame* rootScrollContainerFrame = ps->GetRootScrollContainerFrame();
4968 if (!rootScrollContainerFrame) {
4969 return;
4970 }
4971 ps->FrameNeedsReflow(rootScrollContainerFrame,
4972 IntrinsicDirty::FrameAncestorsAndDescendants,
4973 NS_FRAME_IS_DIRTY);
4974}
4975
4976//*****************************************************************************
4977// nsDocShell::nsIRefreshURI
4978//*****************************************************************************
4979
4980NS_IMETHODIMPnsresult
4981nsDocShell::RefreshURI(nsIURI* aURI, nsIPrincipal* aPrincipal,
4982 uint32_t aDelay) {
4983 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"
, 4983); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mIsBeingDestroyed"
")"); do { *((volatile int*)__null) = 4983; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4984
4985 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"
, 4985); return NS_ERROR_INVALID_ARG; } } while (false)
;
4986
4987 /* Check if Meta refresh/redirects are permitted. Some
4988 * embedded applications may not want to do this.
4989 * Must do this before sending out NOTIFY_REFRESH events
4990 * because listeners may have side effects (e.g. displaying a
4991 * button to manually trigger the refresh later).
4992 */
4993 bool allowRedirects = true;
4994 GetAllowMetaRedirects(&allowRedirects);
4995 if (!allowRedirects) {
4996 return NS_OK;
4997 }
4998
4999 // If any web progress listeners are listening for NOTIFY_REFRESH events,
5000 // give them a chance to block this refresh.
5001 bool sameURI;
5002 nsresult rv = aURI->Equals(mCurrentURI, &sameURI);
5003 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
5004 sameURI = false;
5005 }
5006 if (!RefreshAttempted(this, aURI, aDelay, sameURI)) {
5007 return NS_OK;
5008 }
5009
5010 nsCOMPtr<nsITimerCallback> refreshTimer =
5011 new nsRefreshTimer(this, aURI, aPrincipal, aDelay);
5012
5013 BusyFlags busyFlags = GetBusyFlags();
5014
5015 if (!mRefreshURIList) {
5016 mRefreshURIList = nsArray::Create();
5017 }
5018
5019 if (busyFlags & BUSY_FLAGS_BUSY ||
5020 (!mBrowsingContext->IsActive() && mDisableMetaRefreshWhenInactive)) {
5021 // We don't want to create the timer right now. Instead queue up the
5022 // request and trigger the timer in EndPageLoad() or whenever we become
5023 // active.
5024 mRefreshURIList->AppendElement(refreshTimer);
5025 } else {
5026 // There is no page loading going on right now. Create the
5027 // timer and fire it right away.
5028 nsCOMPtr<nsPIDOMWindowOuter> win = GetWindow();
5029 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"
, 5029); return NS_ERROR_FAILURE; } } while (false)
;
5030
5031 nsCOMPtr<nsITimer> timer;
5032 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)
5033 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)
;
5034
5035 mRefreshURIList->AppendElement(timer); // owning timer ref
5036 }
5037 return NS_OK;
5038}
5039
5040nsresult nsDocShell::ForceRefreshURIFromTimer(nsIURI* aURI,
5041 nsIPrincipal* aPrincipal,
5042 uint32_t aDelay,
5043 nsITimer* aTimer) {
5044 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"
, 5044); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aTimer" ") ("
"Must have a timer here" ")"); do { *((volatile int*)__null)
= 5044; __attribute__((nomerge)) ::abort(); } while (false);
} } while (false)
;
5045
5046 // Remove aTimer from mRefreshURIList if needed
5047 if (mRefreshURIList) {
5048 uint32_t n = 0;
5049 mRefreshURIList->GetLength(&n);
5050
5051 for (uint32_t i = 0; i < n; ++i) {
5052 nsCOMPtr<nsITimer> timer = do_QueryElementAt(mRefreshURIList, i);
5053 if (timer == aTimer) {
5054 mRefreshURIList->RemoveElementAt(i);
5055 break;
5056 }
5057 }
5058 }
5059
5060 return ForceRefreshURI(aURI, aPrincipal, aDelay);
5061}
5062
5063NS_IMETHODIMPnsresult
5064nsDocShell::ForceRefreshURI(nsIURI* aURI, nsIPrincipal* aPrincipal,
5065 uint32_t aDelay) {
5066 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"
, 5066); return NS_ERROR_INVALID_ARG; } } while (false)
;
5067
5068 RefPtr<nsDocShellLoadState> loadState = new nsDocShellLoadState(aURI);
5069 loadState->SetOriginalURI(mCurrentURI);
5070 loadState->SetResultPrincipalURI(aURI);
5071 loadState->SetResultPrincipalURIIsSome(true);
5072 loadState->SetKeepResultPrincipalURIIfSet(true);
5073 loadState->SetIsMetaRefresh(true);
5074
5075 // Set the triggering pricipal to aPrincipal if available, or current
5076 // document's principal otherwise.
5077 nsCOMPtr<nsIPrincipal> principal = aPrincipal;
5078 RefPtr<Document> doc = GetDocument();
5079 if (!principal) {
5080 if (!doc) {
5081 return NS_ERROR_FAILURE;
5082 }
5083 principal = doc->NodePrincipal();
5084 }
5085 loadState->SetTriggeringPrincipal(principal);
5086 if (doc) {
5087 loadState->SetCsp(doc->GetCsp());
5088 loadState->SetHasValidUserGestureActivation(
5089 doc->HasValidTransientUserGestureActivation());
5090
5091 loadState->SetTextDirectiveUserActivation(
5092 doc->ConsumeTextDirectiveUserActivation() ||
5093 loadState->HasValidUserGestureActivation());
5094 loadState->SetTriggeringSandboxFlags(doc->GetSandboxFlags());
5095 loadState->SetTriggeringWindowId(doc->InnerWindowID());
5096 loadState->SetTriggeringStorageAccess(doc->UsingStorageAccess());
5097 }
5098
5099 loadState->SetPrincipalIsExplicit(true);
5100
5101 /* Check if this META refresh causes a redirection
5102 * to another site.
5103 */
5104 bool equalUri = false;
5105 nsresult rv = aURI->Equals(mCurrentURI, &equalUri);
5106
5107 nsCOMPtr<nsIReferrerInfo> referrerInfo;
5108 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && !equalUri && aDelay <= REFRESH_REDIRECT_TIMER15000) {
5109 /* It is a META refresh based redirection within the threshold time
5110 * we have in mind (15000 ms as defined by REFRESH_REDIRECT_TIMER).
5111 * Pass a REPLACE flag to LoadURI().
5112 */
5113 loadState->SetLoadType(LOAD_REFRESH_REPLACE);
5114
5115 /* For redirects we mimic HTTP, which passes the
5116 * original referrer.
5117 * We will pass in referrer but will not send to server
5118 */
5119 if (mReferrerInfo) {
5120 referrerInfo = static_cast<ReferrerInfo*>(mReferrerInfo.get())
5121 ->CloneWithNewSendReferrer(false);
5122 }
5123 } else {
5124 loadState->SetLoadType(LOAD_REFRESH);
5125 /* We do need to pass in a referrer, but we don't want it to
5126 * be sent to the server.
5127 * For most refreshes the current URI is an appropriate
5128 * internal referrer.
5129 */
5130 referrerInfo = new ReferrerInfo(mCurrentURI, ReferrerPolicy::_empty, false);
5131 }
5132
5133 loadState->SetReferrerInfo(referrerInfo);
5134 loadState->SetLoadFlags(
5135 nsIWebNavigation::LOAD_FLAGS_DISALLOW_INHERIT_PRINCIPAL);
5136 loadState->SetFirstParty(true);
5137
5138 /*
5139 * LoadURI(...) will cancel all refresh timers... This causes the
5140 * Timer and its refreshData instance to be released...
5141 */
5142 LoadURI(loadState, false);
5143
5144 return NS_OK;
5145}
5146
5147static const char16_t* SkipASCIIWhitespace(const char16_t* aStart,
5148 const char16_t* aEnd) {
5149 const char16_t* iter = aStart;
5150 while (iter != aEnd && mozilla::IsAsciiWhitespace(*iter)) {
5151 ++iter;
5152 }
5153 return iter;
5154}
5155
5156static std::tuple<const char16_t*, const char16_t*> ExtractURLString(
5157 const char16_t* aPosition, const char16_t* aEnd) {
5158 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"
, 5158); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPosition != aEnd"
")"); do { *((volatile int*)__null) = 5158; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5159
5160 // 1. Let urlString be the substring of input from the code point at
5161 // position to the end of the string.
5162 const char16_t* urlStart = aPosition;
5163 const char16_t* urlEnd = aEnd;
5164
5165 // 2. If the code point in input pointed to by position is U+0055 (U) or
5166 // U+0075 (u), then advance position to the next code point.
5167 // Otherwise, jump to the step labeled skip quotes.
5168 if (*aPosition == 'U' || *aPosition == 'u') {
5169 ++aPosition;
5170
5171 // 3. If the code point in input pointed to by position is U+0052 (R) or
5172 // U+0072 (r), then advance position to the next code point.
5173 // Otherwise, jump to the step labeled parse.
5174 if (aPosition == aEnd || (*aPosition != 'R' && *aPosition != 'r')) {
5175 return std::make_tuple(urlStart, urlEnd);
5176 }
5177
5178 ++aPosition;
5179
5180 // 4. If the code point in input pointed to by position is U+004C (L) or
5181 // U+006C (l), then advance position to the next code point.
5182 // Otherwise, jump to the step labeled parse.
5183 if (aPosition == aEnd || (*aPosition != 'L' && *aPosition != 'l')) {
5184 return std::make_tuple(urlStart, urlEnd);
5185 }
5186
5187 ++aPosition;
5188
5189 // 5. Skip ASCII whitespace within input given position.
5190 aPosition = SkipASCIIWhitespace(aPosition, aEnd);
5191
5192 // 6. If the code point in input pointed to by position is U+003D (=),
5193 // then advance position to the next code point. Otherwise, jump to
5194 // the step labeled parse.
5195 if (aPosition == aEnd || *aPosition != '=') {
5196 return std::make_tuple(urlStart, urlEnd);
5197 }
5198
5199 ++aPosition;
5200
5201 // 7. Skip ASCII whitespace within input given position.
5202 aPosition = SkipASCIIWhitespace(aPosition, aEnd);
5203 }
5204
5205 // 8. Skip quotes: If the code point in input pointed to by position is
5206 // U+0027 (') or U+0022 ("), then let quote be that code point, and
5207 // advance position to the next code point. Otherwise, let quote be
5208 // the empty string.
5209 Maybe<char> quote;
5210 if (aPosition != aEnd && (*aPosition == '\'' || *aPosition == '"')) {
5211 quote.emplace(*aPosition);
5212 ++aPosition;
5213 }
5214
5215 // 9. Set urlString to the substring of input from the code point at
5216 // position to the end of the string.
5217 urlStart = aPosition;
5218 urlEnd = aEnd;
5219
5220 // 10. If quote is not the empty string, and there is a code point in
5221 // urlString equal to quote, then truncate urlString at that code
5222 // point, so that it and all subsequent code points are removed.
5223 const char16_t* quotePos;
5224 if (quote.isSome() &&
5225 (quotePos = nsCharTraits<char16_t>::find(
5226 urlStart, std::distance(urlStart, aEnd), quote.value()))) {
5227 urlEnd = quotePos;
5228 }
5229
5230 return std::make_tuple(urlStart, urlEnd);
5231}
5232
5233void nsDocShell::SetupRefreshURIFromHeader(Document* aDocument,
5234 const nsAString& aHeader) {
5235 if (mIsBeingDestroyed) {
5236 return;
5237 }
5238
5239 const char16_t* position = aHeader.BeginReading();
5240 const char16_t* end = aHeader.EndReading();
5241
5242 // See
5243 // https://html.spec.whatwg.org/#pragma-directives:shared-declarative-refresh-steps.
5244
5245 // 3. Skip ASCII whitespace
5246 position = SkipASCIIWhitespace(position, end);
5247
5248 // 4. Let time be 0.
5249 CheckedInt<uint32_t> milliSeconds;
5250
5251 // 5. Collect a sequence of code points that are ASCII digits
5252 const char16_t* digitsStart = position;
5253 while (position != end && mozilla::IsAsciiDigit(*position)) {
5254 ++position;
5255 }
5256
5257 if (position == digitsStart) {
5258 // 6. If timeString is the empty string, then:
5259 // 1. If the code point in input pointed to by position is not U+002E
5260 // (.), then return.
5261 if (position == end || *position != '.') {
5262 return;
5263 }
5264 } else {
5265 // 7. Otherwise, set time to the result of parsing timeString using the
5266 // rules for parsing non-negative integers.
5267 nsContentUtils::ParseHTMLIntegerResultFlags result;
5268 uint32_t seconds =
5269 nsContentUtils::ParseHTMLInteger(digitsStart, position, &result);
5270 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"
, 5270); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!(result & nsContentUtils::eParseHTMLInteger_Negative)"
")"); do { *((volatile int*)__null) = 5270; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5271 if (result & nsContentUtils::eParseHTMLInteger_Error) {
5272 // The spec assumes no errors here (since we only pass ASCII digits in),
5273 // but we can still overflow, so this block should deal with that (and
5274 // only that).
5275 MOZ_ASSERT(!(result & nsContentUtils::eParseHTMLInteger_ErrorOverflow))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!(result & nsContentUtils::eParseHTMLInteger_ErrorOverflow
))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!(result & nsContentUtils::eParseHTMLInteger_ErrorOverflow
)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!(result & nsContentUtils::eParseHTMLInteger_ErrorOverflow)"
, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 5275); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!(result & nsContentUtils::eParseHTMLInteger_ErrorOverflow)"
")"); do { *((volatile int*)__null) = 5275; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5276 return;
5277 }
5278 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"
, 5279); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!(result & nsContentUtils::eParseHTMLInteger_DidNotConsumeAllInput)"
")"); do { *((volatile int*)__null) = 5279; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
5279 !(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"
, 5279); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!(result & nsContentUtils::eParseHTMLInteger_DidNotConsumeAllInput)"
")"); do { *((volatile int*)__null) = 5279; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5280
5281 milliSeconds = seconds;
5282 milliSeconds *= 1000;
5283 if (!milliSeconds.isValid()) {
5284 return;
5285 }
5286 }
5287
5288 // 8. Collect a sequence of code points that are ASCII digits and U+002E FULL
5289 // STOP characters (.) from input given position. Ignore any collected
5290 // characters.
5291 while (position != end &&
5292 (mozilla::IsAsciiDigit(*position) || *position == '.')) {
5293 ++position;
5294 }
5295
5296 // 9. Let urlRecord be document's URL.
5297 nsCOMPtr<nsIURI> urlRecord(aDocument->GetDocumentURI());
5298
5299 // 10. If position is not past the end of input
5300 if (position != end) {
5301 // 1. If the code point in input pointed to by position is not U+003B (;),
5302 // U+002C (,), or ASCII whitespace, then return.
5303 if (*position != ';' && *position != ',' &&
5304 !mozilla::IsAsciiWhitespace(*position)) {
5305 return;
5306 }
5307
5308 // 2. Skip ASCII whitespace within input given position.
5309 position = SkipASCIIWhitespace(position, end);
5310
5311 // 3. If the code point in input pointed to by position is U+003B (;) or
5312 // U+002C (,), then advance position to the next code point.
5313 if (position != end && (*position == ';' || *position == ',')) {
5314 ++position;
5315
5316 // 4. Skip ASCII whitespace within input given position.
5317 position = SkipASCIIWhitespace(position, end);
5318 }
5319
5320 // 11. If position is not past the end of input, then:
5321 if (position != end) {
5322 const char16_t* urlStart;
5323 const char16_t* urlEnd;
5324
5325 // 1-10. See ExtractURLString.
5326 std::tie(urlStart, urlEnd) = ExtractURLString(position, end);
5327
5328 // 11. Parse: Parse urlString relative to document. If that fails, return.
5329 // Otherwise, set urlRecord to the resulting URL record.
5330 nsresult rv =
5331 NS_NewURI(getter_AddRefs(urlRecord),
5332 Substring(urlStart, std::distance(urlStart, urlEnd)),
5333 /* charset = */ nullptr, aDocument->GetDocBaseURI());
5334 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"
, 5334); return; } } while (false)
;
5335 }
5336 }
5337
5338 nsIPrincipal* principal = aDocument->NodePrincipal();
5339 nsCOMPtr<nsIScriptSecurityManager> securityManager =
5340 nsContentUtils::GetSecurityManager();
5341 nsresult rv = securityManager->CheckLoadURIWithPrincipal(
5342 principal, urlRecord,
5343 nsIScriptSecurityManager::LOAD_IS_AUTOMATIC_DOCUMENT_REPLACEMENT,
5344 aDocument->InnerWindowID());
5345 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"
, 5345); return; } } while (false)
;
5346
5347 bool isjs = true;
5348 rv = NS_URIChainHasFlags(
5349 urlRecord, nsIProtocolHandler::URI_OPENING_EXECUTES_SCRIPT, &isjs);
5350 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"
, 5350); return; } } while (false)
;
5351
5352 if (isjs) {
5353 return;
5354 }
5355
5356 RefreshURI(urlRecord, principal, milliSeconds.value());
5357}
5358
5359static void DoCancelRefreshURITimers(nsIMutableArray* aTimerList) {
5360 if (!aTimerList) {
5361 return;
5362 }
5363
5364 uint32_t n = 0;
5365 aTimerList->GetLength(&n);
5366
5367 while (n) {
5368 nsCOMPtr<nsITimer> timer(do_QueryElementAt(aTimerList, --n));
5369
5370 aTimerList->RemoveElementAt(n); // bye bye owning timer ref
5371
5372 if (timer) {
5373 timer->Cancel();
5374 }
5375 }
5376}
5377
5378NS_IMETHODIMPnsresult
5379nsDocShell::CancelRefreshURITimers() {
5380 DoCancelRefreshURITimers(mRefreshURIList);
5381 DoCancelRefreshURITimers(mSavedRefreshURIList);
5382 DoCancelRefreshURITimers(mBFCachedRefreshURIList);
5383 mRefreshURIList = nullptr;
5384 mSavedRefreshURIList = nullptr;
5385 mBFCachedRefreshURIList = nullptr;
5386
5387 return NS_OK;
5388}
5389
5390NS_IMETHODIMPnsresult
5391nsDocShell::GetRefreshPending(bool* aResult) {
5392 if (!mRefreshURIList) {
5393 *aResult = false;
5394 return NS_OK;
5395 }
5396
5397 uint32_t count;
5398 nsresult rv = mRefreshURIList->GetLength(&count);
5399 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
5400 *aResult = (count != 0);
5401 }
5402 return rv;
5403}
5404
5405void nsDocShell::RefreshURIToQueue() {
5406 if (mRefreshURIList) {
5407 uint32_t n = 0;
5408 mRefreshURIList->GetLength(&n);
5409
5410 for (uint32_t i = 0; i < n; ++i) {
5411 nsCOMPtr<nsITimer> timer = do_QueryElementAt(mRefreshURIList, i);
5412 if (!timer) {
5413 continue; // this must be a nsRefreshURI already
5414 }
5415
5416 // Replace this timer object with a nsRefreshTimer object.
5417 nsCOMPtr<nsITimerCallback> callback;
5418 timer->GetCallback(getter_AddRefs(callback));
5419
5420 timer->Cancel();
5421
5422 mRefreshURIList->ReplaceElementAt(callback, i);
5423 }
5424 }
5425}
5426
5427NS_IMETHODIMPnsresult
5428nsDocShell::SuspendRefreshURIs() {
5429 RefreshURIToQueue();
5430
5431 // Suspend refresh URIs for our child shells as well.
5432 for (auto* child : mChildList.ForwardRange()) {
5433 nsCOMPtr<nsIDocShell> shell = do_QueryObject(child);
5434 if (shell) {
5435 shell->SuspendRefreshURIs();
5436 }
5437 }
5438
5439 return NS_OK;
5440}
5441
5442NS_IMETHODIMPnsresult
5443nsDocShell::ResumeRefreshURIs() {
5444 RefreshURIFromQueue();
5445
5446 // Resume refresh URIs for our child shells as well.
5447 for (auto* child : mChildList.ForwardRange()) {
5448 nsCOMPtr<nsIDocShell> shell = do_QueryObject(child);
5449 if (shell) {
5450 shell->ResumeRefreshURIs();
5451 }
5452 }
5453
5454 return NS_OK;
5455}
5456
5457nsresult nsDocShell::RefreshURIFromQueue() {
5458 if (!mRefreshURIList) {
5459 return NS_OK;
5460 }
5461 uint32_t n = 0;
5462 mRefreshURIList->GetLength(&n);
5463
5464 while (n) {
5465 nsCOMPtr<nsITimerCallback> refreshInfo =
5466 do_QueryElementAt(mRefreshURIList, --n);
5467
5468 if (refreshInfo) {
5469 // This is the nsRefreshTimer object, waiting to be
5470 // setup in a timer object and fired.
5471 // Create the timer and trigger it.
5472 uint32_t delay = static_cast<nsRefreshTimer*>(
5473 static_cast<nsITimerCallback*>(refreshInfo))
5474 ->GetDelay();
5475 nsCOMPtr<nsPIDOMWindowOuter> win = GetWindow();
5476 if (win) {
5477 nsCOMPtr<nsITimer> timer;
5478 NS_NewTimerWithCallback(getter_AddRefs(timer), refreshInfo, delay,
5479 nsITimer::TYPE_ONE_SHOT);
5480
5481 if (timer) {
5482 // Replace the nsRefreshTimer element in the queue with
5483 // its corresponding timer object, so that in case another
5484 // load comes through before the timer can go off, the timer will
5485 // get cancelled in CancelRefreshURITimer()
5486 mRefreshURIList->ReplaceElementAt(timer, n);
5487 }
5488 }
5489 }
5490 }
5491
5492 return NS_OK;
5493}
5494
5495static bool IsFollowupPartOfMultipart(nsIRequest* aRequest) {
5496 nsCOMPtr<nsIMultiPartChannel> multiPartChannel = do_QueryInterface(aRequest);
5497 bool firstPart = false;
5498 return multiPartChannel &&
5499 NS_SUCCEEDED(multiPartChannel->GetIsFirstPart(&firstPart))((bool)(__builtin_expect(!!(!NS_FAILED_impl(multiPartChannel->
GetIsFirstPart(&firstPart))), 1)))
&&
5500 !firstPart;
5501}
5502
5503nsresult nsDocShell::Embed(nsIDocumentViewer* aDocumentViewer,
5504 WindowGlobalChild* aWindowActor,
5505 bool aIsTransientAboutBlank, bool aPersist,
5506 nsIRequest* aRequest, nsIURI* aPreviousURI) {
5507 // Save the LayoutHistoryState of the previous document, before
5508 // setting up new document
5509 PersistLayoutHistoryState();
5510
5511 nsresult rv = SetupNewViewer(aDocumentViewer, aWindowActor);
5512 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"
, 5512); return rv; } } while (false)
;
5513
5514 // XXX What if SetupNewViewer fails?
5515 if (mozilla::SessionHistoryInParent() ? !!mLoadingEntry : !!mLSHE) {
5516 // Set history.state
5517 SetDocCurrentStateObj(mLSHE,
5518 mLoadingEntry ? &mLoadingEntry->mInfo : nullptr);
5519 }
5520
5521 if (mLSHE) {
5522 // Restore the editing state, if it's stored in session history.
5523 if (mLSHE->HasDetachedEditor()) {
5524 ReattachEditorToWindow(mLSHE);
5525 }
5526
5527 SetHistoryEntryAndUpdateBC(Nothing(), Some<nsISHEntry*>(mLSHE));
5528 }
5529
5530 if (!aIsTransientAboutBlank && mozilla::SessionHistoryInParent() &&
5531 !IsFollowupPartOfMultipart(aRequest)) {
5532 bool expired = false;
5533 uint32_t cacheKey = 0;
5534 nsCOMPtr<nsICacheInfoChannel> cacheChannel = do_QueryInterface(aRequest);
5535 if (cacheChannel) {
5536 // Check if the page has expired from cache
5537 uint32_t expTime = 0;
5538 cacheChannel->GetCacheTokenExpirationTime(&expTime);
5539 uint32_t now = PRTimeToSeconds(PR_Now());
5540 if (expTime <= now) {
5541 expired = true;
5542 }
5543
5544 // The checks for updating cache key are similar to the old session
5545 // history in OnNewURI. Try to update the cache key if
5546 // - we should update session history and aren't doing a session
5547 // history load.
5548 // - we're doing a forced reload.
5549 if (((!mLoadingEntry || !mLoadingEntry->mLoadIsFromSessionHistory) &&
5550 mBrowsingContext->ShouldUpdateSessionHistory(mLoadType)) ||
5551 IsForceReloadType(mLoadType)) {
5552 cacheChannel->GetCacheKey(&cacheKey);
5553 }
5554 }
5555
5556 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)
;
5557 MoveLoadingToActiveEntry(aPersist, expired, cacheKey, aPreviousURI);
5558 }
5559
5560 bool updateHistory = true;
5561
5562 // Determine if this type of load should update history
5563 switch (mLoadType) {
5564 case LOAD_NORMAL_REPLACE:
5565 case LOAD_REFRESH_REPLACE:
5566 case LOAD_STOP_CONTENT_AND_REPLACE:
5567 case LOAD_RELOAD_BYPASS_CACHE:
5568 case LOAD_RELOAD_BYPASS_PROXY:
5569 case LOAD_RELOAD_BYPASS_PROXY_AND_CACHE:
5570 case LOAD_REPLACE_BYPASS_CACHE:
5571 updateHistory = false;
5572 break;
5573 default:
5574 break;
5575 }
5576
5577 if (!updateHistory) {
5578 SetLayoutHistoryState(nullptr);
5579 }
5580
5581 return NS_OK;
5582}
5583
5584//*****************************************************************************
5585// nsDocShell::nsIWebProgressListener
5586//*****************************************************************************
5587
5588NS_IMETHODIMPnsresult
5589nsDocShell::OnProgressChange(nsIWebProgress* aProgress, nsIRequest* aRequest,
5590 int32_t aCurSelfProgress, int32_t aMaxSelfProgress,
5591 int32_t aCurTotalProgress,
5592 int32_t aMaxTotalProgress) {
5593 return NS_OK;
5594}
5595
5596NS_IMETHODIMPnsresult
5597nsDocShell::OnStateChange(nsIWebProgress* aProgress, nsIRequest* aRequest,
5598 uint32_t aStateFlags, nsresult aStatus) {
5599 if ((~aStateFlags & (STATE_START | STATE_IS_NETWORK)) == 0) {
5600 // Save timing statistics.
5601 nsCOMPtr<nsIChannel> channel(do_QueryInterface(aRequest));
5602 nsCOMPtr<nsIURI> uri;
5603 channel->GetURI(getter_AddRefs(uri));
5604 nsAutoCString aURI;
5605 uri->GetAsciiSpec(aURI);
5606
5607 if (this == aProgress) {
5608 mozilla::Unused << MaybeInitTiming();
5609 mTiming->NotifyFetchStart(uri,
5610 ConvertLoadTypeToNavigationType(mLoadType));
5611 // If we are starting a DocumentChannel, we need to pass the timing
5612 // statistics so that should a process switch occur, the starting type can
5613 // be passed to the new DocShell running in the other content process.
5614 if (RefPtr<DocumentChannel> docChannel = do_QueryObject(aRequest)) {
5615 docChannel->SetNavigationTiming(mTiming);
5616 }
5617 }
5618
5619 // Page has begun to load
5620 mBusyFlags = (BusyFlags)(BUSY_FLAGS_BUSY | BUSY_FLAGS_BEFORE_PAGE_LOAD);
5621
5622 if ((aStateFlags & STATE_RESTORING) == 0) {
5623 if (SessionStorePlatformCollection()) {
5624 if (IsForceReloadType(mLoadType)) {
5625 if (WindowContext* windowContext =
5626 mBrowsingContext->GetCurrentWindowContext()) {
5627 SessionStoreChild::From(windowContext->GetWindowGlobalChild())
5628 ->ResetSessionStore(mBrowsingContext,
5629 mBrowsingContext->GetSessionStoreEpoch());
5630 }
5631 }
5632 }
5633 }
5634 } else if ((~aStateFlags & (STATE_TRANSFERRING | STATE_IS_DOCUMENT)) == 0) {
5635 // Page is loading
5636 mBusyFlags = (BusyFlags)(BUSY_FLAGS_BUSY | BUSY_FLAGS_PAGE_LOADING);
5637 } else if ((aStateFlags & STATE_STOP) && (aStateFlags & STATE_IS_NETWORK)) {
5638 // Page has finished loading
5639 mBusyFlags = BUSY_FLAGS_NONE;
5640 }
5641
5642 if ((~aStateFlags & (STATE_IS_DOCUMENT | STATE_STOP)) == 0) {
5643 nsCOMPtr<nsIWebProgress> webProgress =
5644 do_QueryInterface(GetAsSupports(this));
5645 // Is the document stop notification for this document?
5646 if (aProgress == webProgress.get()) {
5647 nsCOMPtr<nsIChannel> channel(do_QueryInterface(aRequest));
5648 EndPageLoad(aProgress, channel, aStatus);
5649 }
5650 }
5651 // note that redirect state changes will go through here as well, but it
5652 // is better to handle those in OnRedirectStateChange where more
5653 // information is available.
5654 return NS_OK;
5655}
5656
5657NS_IMETHODIMPnsresult
5658nsDocShell::OnLocationChange(nsIWebProgress* aProgress, nsIRequest* aRequest,
5659 nsIURI* aURI, uint32_t aFlags) {
5660 // Since we've now changed Documents, notify the BrowsingContext that we've
5661 // changed. Ideally we'd just let the BrowsingContext do this when it
5662 // changes the current window global, but that happens before this and we
5663 // have a lot of tests that depend on the specific ordering of messages.
5664 bool isTopLevel = false;
5665 if (XRE_IsParentProcess() &&
5666 !(aFlags & nsIWebProgressListener::LOCATION_CHANGE_SAME_DOCUMENT) &&
5667 NS_SUCCEEDED(aProgress->GetIsTopLevel(&isTopLevel))((bool)(__builtin_expect(!!(!NS_FAILED_impl(aProgress->GetIsTopLevel
(&isTopLevel))), 1)))
&& isTopLevel) {
5668 GetBrowsingContext()->Canonical()->UpdateSecurityState();
5669 }
5670 return NS_OK;
5671}
5672
5673void nsDocShell::OnRedirectStateChange(nsIChannel* aOldChannel,
5674 nsIChannel* aNewChannel,
5675 uint32_t aRedirectFlags,
5676 uint32_t aStateFlags) {
5677 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"
, 5678); MOZ_PretendNoReturn(); } } while (0)
5678 "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"
, 5678); MOZ_PretendNoReturn(); } } while (0)
;
5679
5680 if (!(aStateFlags & STATE_IS_DOCUMENT)) {
5681 return; // not a toplevel document
5682 }
5683
5684 nsCOMPtr<nsIURI> oldURI, newURI;
5685 aOldChannel->GetURI(getter_AddRefs(oldURI));
5686 aNewChannel->GetURI(getter_AddRefs(newURI));
5687 if (!oldURI || !newURI) {
5688 return;
5689 }
5690
5691 // DocumentChannel adds redirect chain to global history in the parent
5692 // process. The redirect chain can't be queried from the content process, so
5693 // there's no need to update global history here.
5694 RefPtr<DocumentChannel> docChannel = do_QueryObject(aOldChannel);
5695 if (!docChannel) {
5696 // Below a URI visit is saved (see AddURIVisit method doc).
5697 // The visit chain looks something like:
5698 // ...
5699 // Site N - 1
5700 // => Site N
5701 // (redirect to =>) Site N + 1 (we are here!)
5702
5703 // Get N - 1 and transition type
5704 nsCOMPtr<nsIURI> previousURI;
5705 uint32_t previousFlags = 0;
5706 ExtractLastVisit(aOldChannel, getter_AddRefs(previousURI), &previousFlags);
5707
5708 if (aRedirectFlags & nsIChannelEventSink::REDIRECT_INTERNAL ||
5709 net::ChannelIsPost(aOldChannel)) {
5710 // 1. Internal redirects are ignored because they are specific to the
5711 // channel implementation.
5712 // 2. POSTs are not saved by global history.
5713 //
5714 // Regardless, we need to propagate the previous visit to the new
5715 // channel.
5716 SaveLastVisit(aNewChannel, previousURI, previousFlags);
5717 } else {
5718 // Get the HTTP response code, if available.
5719 uint32_t responseStatus = 0;
5720 nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(aOldChannel);
5721 if (httpChannel) {
5722 Unused << httpChannel->GetResponseStatus(&responseStatus);
5723 }
5724
5725 // Add visit N -1 => N
5726 AddURIVisit(oldURI, previousURI, previousFlags, responseStatus);
5727
5728 // Since N + 1 could be the final destination, we will not save N => N + 1
5729 // here. OnNewURI will do that, so we will cache it.
5730 SaveLastVisit(aNewChannel, oldURI, aRedirectFlags);
5731 }
5732 }
5733
5734 if (!(aRedirectFlags & nsIChannelEventSink::REDIRECT_INTERNAL) &&
5735 mLoadType & (LOAD_CMD_RELOAD | LOAD_CMD_HISTORY)) {
5736 mLoadType = LOAD_NORMAL_REPLACE;
5737 SetHistoryEntryAndUpdateBC(Some(nullptr), Nothing());
5738 }
5739}
5740
5741NS_IMETHODIMPnsresult
5742nsDocShell::OnStatusChange(nsIWebProgress* aWebProgress, nsIRequest* aRequest,
5743 nsresult aStatus, const char16_t* aMessage) {
5744 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"
, 5744); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "notification excluded in AddProgressListener(...)"
")"); do { *((volatile int*)__null) = 5744; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5745 return NS_OK;
5746}
5747
5748NS_IMETHODIMPnsresult
5749nsDocShell::OnSecurityChange(nsIWebProgress* aWebProgress, nsIRequest* aRequest,
5750 uint32_t aState) {
5751 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"
, 5751); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "notification excluded in AddProgressListener(...)"
")"); do { *((volatile int*)__null) = 5751; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5752 return NS_OK;
5753}
5754
5755NS_IMETHODIMPnsresult
5756nsDocShell::OnContentBlockingEvent(nsIWebProgress* aWebProgress,
5757 nsIRequest* aRequest, uint32_t aEvent) {
5758 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"
, 5758); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "notification excluded in AddProgressListener(...)"
")"); do { *((volatile int*)__null) = 5758; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5759 return NS_OK;
5760}
5761
5762already_AddRefed<nsIURIFixupInfo> nsDocShell::KeywordToURI(
5763 const nsACString& aKeyword, bool aIsPrivateContext) {
5764 nsCOMPtr<nsIURIFixupInfo> info;
5765 if (!XRE_IsContentProcess()) {
5766 nsCOMPtr<nsIURIFixup> uriFixup = components::URIFixup::Service();
5767 if (uriFixup) {
5768 uriFixup->KeywordToURI(aKeyword, aIsPrivateContext, getter_AddRefs(info));
5769 }
5770 }
5771 return info.forget();
5772}
5773
5774/* static */
5775already_AddRefed<nsIURI> nsDocShell::MaybeFixBadCertDomainErrorURI(
5776 nsIChannel* aChannel, nsIURI* aUrl) {
5777 if (!aChannel) {
5778 return nullptr;
5779 }
5780
5781 nsresult rv = NS_OK;
5782 nsAutoCString host;
5783 rv = aUrl->GetAsciiHost(host);
5784 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"
, 5784)
) {
5785 return nullptr;
5786 }
5787
5788 // Return if fixup enable pref is turned off.
5789 if (!mozilla::StaticPrefs::security_bad_cert_domain_error_url_fix_enabled()) {
5790 return nullptr;
5791 }
5792
5793 // Return if scheme is not HTTPS.
5794 if (!SchemeIsHTTPS(aUrl)) {
5795 return nullptr;
5796 }
5797
5798 nsCOMPtr<nsILoadInfo> info = aChannel->LoadInfo();
5799 if (!info) {
5800 return nullptr;
5801 }
5802
5803 // Skip doing the fixup if our channel was redirected, because we
5804 // shouldn't be guessing things about the post-redirect URI.
5805 if (!info->RedirectChain().IsEmpty()) {
5806 return nullptr;
5807 }
5808
5809 int32_t port = 0;
5810 rv = aUrl->GetPort(&port);
5811 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"
, 5811)
) {
5812 return nullptr;
5813 }
5814
5815 // Don't fix up hosts with ports.
5816 if (port != -1) {
5817 return nullptr;
5818 }
5819
5820 // Don't fix up localhost url.
5821 if (host == "localhost") {
5822 return nullptr;
5823 }
5824
5825 // Don't fix up hostnames with IP address.
5826 if (net_IsValidIPv4Addr(host) || net_IsValidIPv6Addr(host)) {
5827 return nullptr;
5828 }
5829
5830 nsAutoCString userPass;
5831 rv = aUrl->GetUserPass(userPass);
5832 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"
, 5832)
) {
5833 return nullptr;
5834 }
5835
5836 // Security - URLs with user / password info should NOT be modified.
5837 if (!userPass.IsEmpty()) {
5838 return nullptr;
5839 }
5840
5841 nsCOMPtr<nsITransportSecurityInfo> tsi;
5842 rv = aChannel->GetSecurityInfo(getter_AddRefs(tsi));
5843 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"
, 5843)
) {
5844 return nullptr;
5845 }
5846
5847 if (NS_WARN_IF(!tsi)NS_warn_if_impl(!tsi, "!tsi", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 5847)
) {
5848 return nullptr;
5849 }
5850
5851 nsCOMPtr<nsIX509Cert> cert;
5852 rv = tsi->GetServerCert(getter_AddRefs(cert));
5853 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"
, 5853)
) {
5854 return nullptr;
5855 }
5856
5857 nsTArray<uint8_t> certBytes;
5858 rv = cert->GetRawDER(certBytes);
5859 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
5860 return nullptr;
5861 }
5862
5863 mozilla::pkix::Input serverCertInput;
5864 mozilla::pkix::Result result =
5865 serverCertInput.Init(certBytes.Elements(), certBytes.Length());
5866 if (result != mozilla::pkix::Success) {
5867 return nullptr;
5868 }
5869
5870 constexpr auto wwwPrefix = "www."_ns;
5871 nsAutoCString newHost;
5872 if (StringBeginsWith(host, wwwPrefix)) {
5873 // Try www.example.com -> example.com
5874 newHost.Assign(Substring(host, wwwPrefix.Length()));
5875 } else {
5876 // Try example.com -> www.example.com
5877 newHost.Assign(wwwPrefix);
5878 newHost.Append(host);
5879 }
5880
5881 mozilla::pkix::Input newHostInput;
5882 result = newHostInput.Init(
5883 BitwiseCast<const uint8_t*, const char*>(newHost.BeginReading()),
5884 newHost.Length());
5885 if (result != mozilla::pkix::Success) {
5886 return nullptr;
5887 }
5888
5889 // Because certificate verification returned Result::ERROR_BAD_CERT_DOMAIN /
5890 // SSL_ERROR_BAD_CERT_DOMAIN, a chain was built and we know whether or not
5891 // the root was a built-in.
5892 bool rootIsBuiltIn;
5893 if (NS_FAILED(tsi->GetIsBuiltCertChainRootBuiltInRoot(&rootIsBuiltIn))((bool)(__builtin_expect(!!(NS_FAILED_impl(tsi->GetIsBuiltCertChainRootBuiltInRoot
(&rootIsBuiltIn))), 0)))
) {
5894 return nullptr;
5895 }
5896 mozilla::psm::SkipInvalidSANsForNonBuiltInRootsPolicy nameMatchingPolicy(
5897 rootIsBuiltIn);
5898
5899 // Check if the certificate is valid for the new hostname.
5900 result = mozilla::pkix::CheckCertHostname(serverCertInput, newHostInput,
5901 nameMatchingPolicy);
5902 if (result != mozilla::pkix::Success) {
5903 return nullptr;
5904 }
5905
5906 nsCOMPtr<nsIURI> newURI;
5907 Unused << NS_MutateURI(aUrl).SetHost(newHost).Finalize(
5908 getter_AddRefs(newURI));
5909
5910 return newURI.forget();
5911}
5912
5913/* static */
5914already_AddRefed<nsIURI> nsDocShell::AttemptURIFixup(
5915 nsIChannel* aChannel, nsresult aStatus,
5916 const mozilla::Maybe<nsCString>& aOriginalURIString, uint32_t aLoadType,
5917 bool aIsTopFrame, bool aAllowKeywordFixup, bool aUsePrivateBrowsing,
5918 bool aNotifyKeywordSearchLoading, nsIInputStream** aNewPostData,
5919 bool* outWasSchemelessInput) {
5920 if (aStatus != NS_ERROR_UNKNOWN_HOST && aStatus != NS_ERROR_NET_RESET &&
5921 aStatus != NS_ERROR_CONNECTION_REFUSED &&
5922 aStatus !=
5923 mozilla::psm::GetXPCOMFromNSSError(SSL_ERROR_BAD_CERT_DOMAIN)) {
5924 return nullptr;
5925 }
5926
5927 if (!(aLoadType == LOAD_NORMAL && aIsTopFrame) && !aAllowKeywordFixup) {
5928 return nullptr;
5929 }
5930
5931 nsCOMPtr<nsIURI> url;
5932 nsresult rv = aChannel->GetURI(getter_AddRefs(url));
5933 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
5934 return nullptr;
5935 }
5936
5937 //
5938 // Try and make an alternative URI from the old one
5939 //
5940 nsCOMPtr<nsIURI> newURI;
5941 nsCOMPtr<nsIInputStream> newPostData;
5942
5943 nsAutoCString oldSpec;
5944 url->GetSpec(oldSpec);
5945
5946 //
5947 // First try keyword fixup
5948 //
5949 nsAutoString keywordProviderName, keywordAsSent;
5950 if (aStatus == NS_ERROR_UNKNOWN_HOST && aAllowKeywordFixup) {
5951 // we should only perform a keyword search under the following
5952 // conditions:
5953 // (0) Pref keyword.enabled is true
5954 // (1) the url scheme is http (or https)
5955 // (2) the url does not have a protocol scheme
5956 // If we don't enforce such a policy, then we end up doing
5957 // keyword searchs on urls we don't intend like imap, file,
5958 // mailbox, etc. This could lead to a security problem where we
5959 // send data to the keyword server that we shouldn't be.
5960 // Someone needs to clean up keywords in general so we can
5961 // determine on a per url basis if we want keywords
5962 // enabled...this is just a bandaid...
5963 nsAutoCString scheme;
5964 Unused << url->GetScheme(scheme);
5965 if (Preferences::GetBool("keyword.enabled", false) &&
5966 StringBeginsWith(scheme, "http"_ns)) {
5967 bool attemptFixup = false;
5968 nsAutoCString host;
5969 Unused << url->GetHost(host);
5970 if (host.FindChar('.') == kNotFound) {
5971 attemptFixup = true;
5972 } else {
5973 // For domains with dots, we check the public suffix validity.
5974 nsCOMPtr<nsIEffectiveTLDService> tldService =
5975 do_GetService(NS_EFFECTIVETLDSERVICE_CONTRACTID"@mozilla.org/network/effective-tld-service;1");
5976 if (tldService) {
5977 nsAutoCString suffix;
5978 attemptFixup =
5979 NS_SUCCEEDED(tldService->GetKnownPublicSuffix(url, suffix))((bool)(__builtin_expect(!!(!NS_FAILED_impl(tldService->GetKnownPublicSuffix
(url, suffix))), 1)))
&&
5980 suffix.IsEmpty();
5981 }
5982 }
5983 if (attemptFixup) {
5984 nsCOMPtr<nsIURIFixupInfo> info;
5985 // only send non-qualified hosts to the keyword server
5986 if (aOriginalURIString && !aOriginalURIString->IsEmpty()) {
5987 info = KeywordToURI(*aOriginalURIString, aUsePrivateBrowsing);
5988 } else {
5989 //
5990 // If this string was passed through nsStandardURL by
5991 // chance, then it may have been converted from UTF-8 to
5992 // ACE, which would result in a completely bogus keyword
5993 // query. Here we try to recover the original Unicode
5994 // value, but this is not 100% correct since the value may
5995 // have been normalized per the IDN normalization rules.
5996 //
5997 // Since we don't have access to the exact original string
5998 // that was entered by the user, this will just have to do.
5999 //
6000 // XXX: Since we are not trying to use the result as an
6001 // actual domain name, label-wise Punycode decode would
6002 // likely be more appropriate than the full ToUnicode
6003 // operation.
6004 bool isACE;
6005 nsAutoCString utf8Host;
6006 nsCOMPtr<nsIIDNService> idnSrv =
6007 do_GetService(NS_IDNSERVICE_CONTRACTID"@mozilla.org/network/idn-service;1");
6008 if (idnSrv && NS_SUCCEEDED(idnSrv->IsACE(host, &isACE))((bool)(__builtin_expect(!!(!NS_FAILED_impl(idnSrv->IsACE(
host, &isACE))), 1)))
&& isACE &&
6009 NS_SUCCEEDED(idnSrv->ConvertACEtoUTF8(host, utf8Host))((bool)(__builtin_expect(!!(!NS_FAILED_impl(idnSrv->ConvertACEtoUTF8
(host, utf8Host))), 1)))
) {
6010 info = KeywordToURI(utf8Host, aUsePrivateBrowsing);
6011
6012 } else {
6013 info = KeywordToURI(host, aUsePrivateBrowsing);
6014 }
6015 }
6016 if (info) {
6017 info->GetPreferredURI(getter_AddRefs(newURI));
6018 info->GetWasSchemelessInput(outWasSchemelessInput);
6019 if (newURI) {
6020 info->GetKeywordAsSent(keywordAsSent);
6021 info->GetKeywordProviderName(keywordProviderName);
6022 info->GetPostData(getter_AddRefs(newPostData));
6023 }
6024 }
6025 }
6026 }
6027 }
6028
6029 //
6030 // Now try change the address, e.g. turn http://foo into
6031 // http://www.foo.com, and if that doesn't work try https with
6032 // https://foo and https://www.foo.com.
6033 //
6034 if (aStatus == NS_ERROR_UNKNOWN_HOST || aStatus == NS_ERROR_NET_RESET) {
6035 // Skip fixup for anything except a normal document load
6036 // operation on the topframe.
6037 bool doCreateAlternate = aLoadType == LOAD_NORMAL && aIsTopFrame;
6038
6039 if (doCreateAlternate) {
6040 nsCOMPtr<nsILoadInfo> loadInfo = aChannel->LoadInfo();
6041 nsIPrincipal* principal = loadInfo->TriggeringPrincipal();
6042 // Only do this if our channel was loaded directly by the user from the
6043 // URL bar or similar (system principal) and not redirected, because we
6044 // shouldn't be guessing things about links from other sites, or a
6045 // post-redirect URI.
6046 doCreateAlternate = principal && principal->IsSystemPrincipal() &&
6047 loadInfo->RedirectChain().IsEmpty();
6048 }
6049 // Test if keyword lookup produced a new URI or not
6050 if (doCreateAlternate && newURI) {
6051 bool sameURI = false;
6052 url->Equals(newURI, &sameURI);
6053 if (!sameURI) {
6054 // Keyword lookup made a new URI so no need to try
6055 // an alternate one.
6056 doCreateAlternate = false;
6057 }
6058 }
6059 if (doCreateAlternate) {
6060 newURI = nullptr;
6061 newPostData = nullptr;
6062 keywordProviderName.Truncate();
6063 keywordAsSent.Truncate();
6064 nsCOMPtr<nsIURIFixup> uriFixup = components::URIFixup::Service();
6065 if (uriFixup) {
6066 nsCOMPtr<nsIURIFixupInfo> fixupInfo;
6067 uriFixup->GetFixupURIInfo(oldSpec, nsIURIFixup::FIXUP_FLAG_NONE,
6068 getter_AddRefs(fixupInfo));
6069 if (fixupInfo) {
6070 fixupInfo->GetPreferredURI(getter_AddRefs(newURI));
6071 }
6072 }
6073 }
6074 } else if (aStatus == NS_ERROR_CONNECTION_REFUSED &&
6075 Preferences::GetBool("browser.fixup.fallback-to-https", false)) {
6076 // Try HTTPS, since http didn't work
6077 if (SchemeIsHTTP(url)) {
6078 int32_t port = 0;
6079 url->GetPort(&port);
6080
6081 // Fall back to HTTPS only if port is default
6082 if (port == -1) {
6083 newURI = nullptr;
6084 newPostData = nullptr;
6085 Unused << NS_MutateURI(url)
6086 .SetScheme("https"_ns)
6087 .Finalize(getter_AddRefs(newURI));
6088 }
6089 }
6090 }
6091
6092 // If we have a SSL_ERROR_BAD_CERT_DOMAIN error, try adding or removing
6093 // "www." to/from the beginning of the domain name to see if we can avoid
6094 // showing the cert error page. For example, https://example.com ->
6095 // https://www.example.com or https://www.example.com -> https://example.com.
6096 if (aStatus ==
6097 mozilla::psm::GetXPCOMFromNSSError(SSL_ERROR_BAD_CERT_DOMAIN)) {
6098 newPostData = nullptr;
6099 newURI = MaybeFixBadCertDomainErrorURI(aChannel, url);
6100 }
6101
6102 // Did we make a new URI that is different to the old one? If so
6103 // load it.
6104 //
6105 if (newURI) {
6106 // Make sure the new URI is different from the old one,
6107 // otherwise there's little point trying to load it again.
6108 bool sameURI = false;
6109 url->Equals(newURI, &sameURI);
6110 if (!sameURI) {
6111 if (aNewPostData) {
6112 newPostData.forget(aNewPostData);
6113 }
6114 if (aNotifyKeywordSearchLoading) {
6115 // This notification is meant for Firefox Health Report so it
6116 // can increment counts from the search engine
6117 MaybeNotifyKeywordSearchLoading(keywordProviderName, keywordAsSent);
6118 }
6119 return newURI.forget();
6120 }
6121 }
6122
6123 return nullptr;
6124}
6125
6126nsresult nsDocShell::FilterStatusForErrorPage(
6127 nsresult aStatus, nsIChannel* aChannel, uint32_t aLoadType,
6128 bool aIsTopFrame, bool aUseErrorPages, bool aIsInitialDocument,
6129 bool* aSkippedUnknownProtocolNavigation) {
6130 // Errors to be shown only on top-level frames
6131 if ((aStatus == NS_ERROR_UNKNOWN_HOST ||
6132 aStatus == NS_ERROR_CONNECTION_REFUSED ||
6133 aStatus == NS_ERROR_UNKNOWN_PROXY_HOST ||
6134 aStatus == NS_ERROR_PROXY_CONNECTION_REFUSED ||
6135 aStatus == NS_ERROR_PROXY_FORBIDDEN ||
6136 aStatus == NS_ERROR_PROXY_NOT_IMPLEMENTED ||
6137 aStatus == NS_ERROR_PROXY_AUTHENTICATION_FAILED ||
6138 aStatus == NS_ERROR_PROXY_TOO_MANY_REQUESTS ||
6139 aStatus == NS_ERROR_MALFORMED_URI ||
6140 aStatus == NS_ERROR_BLOCKED_BY_POLICY ||
6141 aStatus == NS_ERROR_DOM_COOP_FAILED ||
6142 aStatus == NS_ERROR_DOM_COEP_FAILED) &&
6143 (aIsTopFrame || aUseErrorPages)) {
6144 return aStatus;
6145 }
6146
6147 if (aStatus == NS_ERROR_NET_TIMEOUT ||
6148 aStatus == NS_ERROR_NET_TIMEOUT_EXTERNAL ||
6149 aStatus == NS_ERROR_PROXY_GATEWAY_TIMEOUT ||
6150 aStatus == NS_ERROR_REDIRECT_LOOP ||
6151 aStatus == NS_ERROR_UNKNOWN_SOCKET_TYPE ||
6152 aStatus == NS_ERROR_NET_INTERRUPT || aStatus == NS_ERROR_NET_RESET ||
6153 aStatus == NS_ERROR_PROXY_BAD_GATEWAY || aStatus == NS_ERROR_OFFLINE ||
6154 aStatus == NS_ERROR_MALWARE_URI || aStatus == NS_ERROR_PHISHING_URI ||
6155 aStatus == NS_ERROR_UNWANTED_URI || aStatus == NS_ERROR_HARMFUL_URI ||
6156 aStatus == NS_ERROR_UNSAFE_CONTENT_TYPE ||
6157 aStatus == NS_ERROR_INTERCEPTION_FAILED ||
6158 aStatus == NS_ERROR_NET_INADEQUATE_SECURITY ||
6159 aStatus == NS_ERROR_NET_HTTP2_SENT_GOAWAY ||
6160 aStatus == NS_ERROR_NET_HTTP3_PROTOCOL_ERROR ||
6161 aStatus == NS_ERROR_DOM_BAD_URI || aStatus == NS_ERROR_FILE_NOT_FOUND ||
6162 aStatus == NS_ERROR_FILE_ACCESS_DENIED ||
6163 aStatus == NS_ERROR_CORRUPTED_CONTENT ||
6164 aStatus == NS_ERROR_INVALID_CONTENT_ENCODING ||
6165 NS_ERROR_GET_MODULE(aStatus) == NS_ERROR_MODULE_SECURITY21) {
6166 // Errors to be shown for any frame
6167 return aStatus;
6168 }
6169
6170 if (aStatus == NS_ERROR_UNKNOWN_PROTOCOL) {
6171 // For unknown protocols we only display an error if the load is triggered
6172 // by the browser itself, or we're replacing the initial document (and
6173 // nothing else). Showing the error for page-triggered navigations causes
6174 // annoying behavior for users, see bug 1528305.
6175 //
6176 // We could, maybe, try to detect if this is in response to some user
6177 // interaction (like clicking a link, or something else) and maybe show
6178 // the error page in that case. But this allows for ctrl+clicking and such
6179 // to see the error page.
6180 nsCOMPtr<nsILoadInfo> info = aChannel->LoadInfo();
6181 if (!info->TriggeringPrincipal()->IsSystemPrincipal() &&
6182 !aIsInitialDocument) {
6183 if (aSkippedUnknownProtocolNavigation) {
6184 *aSkippedUnknownProtocolNavigation = true;
6185 }
6186 return NS_OK;
6187 }
6188 return aStatus;
6189 }
6190
6191 if (aStatus == NS_ERROR_DOCUMENT_NOT_CACHED) {
6192 // Non-caching channels will simply return NS_ERROR_OFFLINE.
6193 // Caching channels would have to look at their flags to work
6194 // out which error to return. Or we can fix up the error here.
6195 if (!(aLoadType & LOAD_CMD_HISTORY)) {
6196 return NS_ERROR_OFFLINE;
6197 }
6198 return aStatus;
6199 }
6200
6201 return NS_OK;
6202}
6203
6204nsresult nsDocShell::EndPageLoad(nsIWebProgress* aProgress,
6205 nsIChannel* aChannel, nsresult aStatus) {
6206 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)
6207 ("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)
6208 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)
;
6209 if (!aChannel) {
6210 return NS_ERROR_NULL_POINTER;
6211 }
6212
6213 // Make sure to discard the initial client if we never created the initial
6214 // about:blank document. Do this before possibly returning from the method
6215 // due to an error.
6216 mInitialClientSource.reset();
6217
6218 nsCOMPtr<nsIConsoleReportCollector> reporter = do_QueryInterface(aChannel);
6219 if (reporter) {
6220 nsCOMPtr<nsILoadGroup> loadGroup;
6221 aChannel->GetLoadGroup(getter_AddRefs(loadGroup));
6222 if (loadGroup) {
6223 reporter->FlushConsoleReports(loadGroup);
6224 } else {
6225 reporter->FlushConsoleReports(GetDocument());
6226 }
6227 }
6228
6229 nsCOMPtr<nsIURI> url;
6230 nsresult rv = aChannel->GetURI(getter_AddRefs(url));
6231 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
6232 return rv;
6233 }
6234
6235 nsCOMPtr<nsITimedChannel> timingChannel = do_QueryInterface(aChannel);
6236 if (timingChannel) {
6237 TimeStamp channelCreationTime;
6238 rv = timingChannel->GetChannelCreation(&channelCreationTime);
6239 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && !channelCreationTime.IsNull()) {
6240 glean::performance_page::total_content_page_load.AccumulateRawDuration(
6241 TimeStamp::Now() - channelCreationTime);
6242 }
6243 }
6244
6245 // Timing is picked up by the window, we don't need it anymore
6246 mTiming = nullptr;
6247
6248 // clean up reload state for meta charset
6249 if (eCharsetReloadRequested == mCharsetReloadState) {
6250 mCharsetReloadState = eCharsetReloadStopOrigional;
6251 } else {
6252 mCharsetReloadState = eCharsetReloadInit;
6253 }
6254
6255 // Save a pointer to the currently-loading history entry.
6256 // nsDocShell::EndPageLoad will clear mLSHE, but we may need this history
6257 // entry further down in this method.
6258 nsCOMPtr<nsISHEntry> loadingSHE = mLSHE;
6259 mozilla::Unused << loadingSHE; // XXX: Not sure if we need this anymore
6260
6261 //
6262 // one of many safeguards that prevent death and destruction if
6263 // someone is so very very rude as to bring this window down
6264 // during this load handler.
6265 //
6266 nsCOMPtr<nsIDocShell> kungFuDeathGrip(this);
6267
6268 // Notify the DocumentViewer that the Document has finished loading. This
6269 // will cause any OnLoad(...) and PopState(...) handlers to fire.
6270 if (!mEODForCurrentDocument && mDocumentViewer) {
6271 mIsExecutingOnLoadHandler = true;
6272 nsCOMPtr<nsIDocumentViewer> viewer = mDocumentViewer;
6273 viewer->LoadComplete(aStatus);
6274 mIsExecutingOnLoadHandler = false;
6275
6276 mEODForCurrentDocument = true;
6277 }
6278 /* Check if the httpChannel has any cache-control related response headers,
6279 * like no-store, no-cache. If so, update SHEntry so that
6280 * when a user goes back/forward to this page, we appropriately do
6281 * form value restoration or load from server.
6282 */
6283 nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(aChannel));
6284 if (!httpChannel) {
6285 // HttpChannel could be hiding underneath a Multipart channel.
6286 GetHttpChannel(aChannel, getter_AddRefs(httpChannel));
6287 }
6288
6289 if (httpChannel) {
6290 // figure out if SH should be saving layout state.
6291 bool discardLayoutState = ShouldDiscardLayoutState(httpChannel);
6292 if (mLSHE && discardLayoutState && (mLoadType & LOAD_CMD_NORMAL) &&
6293 (mLoadType != LOAD_BYPASS_HISTORY) && (mLoadType != LOAD_ERROR_PAGE)) {
6294 mLSHE->SetSaveLayoutStateFlag(false);
6295 }
6296 }
6297
6298 // Clear mLSHE after calling the onLoadHandlers. This way, if the
6299 // onLoadHandler tries to load something different in
6300 // itself or one of its children, we can deal with it appropriately.
6301 if (mLSHE) {
6302 mLSHE->SetLoadType(LOAD_HISTORY);
6303
6304 // Clear the mLSHE reference to indicate document loading is done one
6305 // way or another.
6306 SetHistoryEntryAndUpdateBC(Some(nullptr), Nothing());
6307 }
6308 mActiveEntryIsLoadingFromSessionHistory = false;
6309
6310 // if there's a refresh header in the channel, this method
6311 // will set it up for us.
6312 if (mBrowsingContext->IsActive() || !mDisableMetaRefreshWhenInactive)
6313 RefreshURIFromQueue();
6314
6315 // Test whether this is the top frame or a subframe
6316 bool isTopFrame = mBrowsingContext->IsTop();
6317
6318 bool hadErrorStatus = false;
6319 // If status code indicates an error it means that DocumentChannel already
6320 // tried to fixup the uri and failed. Throw an error dialog box here.
6321 if (NS_FAILED(aStatus)((bool)(__builtin_expect(!!(NS_FAILED_impl(aStatus)), 0)))) {
6322 // If we got CONTENT_BLOCKED from EndPageLoad, then we need to fire
6323 // the error event to our embedder, since tests are relying on this.
6324 // The error event is usually fired by the caller of InternalLoad, but
6325 // this particular error can happen asynchronously.
6326 // Bug 1629201 is filed for having much clearer decision making around
6327 // which cases need error events.
6328 bool fireFrameErrorEvent = (aStatus == NS_ERROR_CONTENT_BLOCKED_SHOW_ALT ||
6329 aStatus == NS_ERROR_CONTENT_BLOCKED);
6330 UnblockEmbedderLoadEventForFailure(fireFrameErrorEvent);
6331
6332 bool isInitialDocument =
6333 !GetExtantDocument() || GetExtantDocument()->IsInitialDocument();
6334 bool skippedUnknownProtocolNavigation = false;
6335 aStatus = FilterStatusForErrorPage(aStatus, aChannel, mLoadType, isTopFrame,
6336 mBrowsingContext->GetUseErrorPages(),
6337 isInitialDocument,
6338 &skippedUnknownProtocolNavigation);
6339 hadErrorStatus = true;
6340 if (NS_FAILED(aStatus)((bool)(__builtin_expect(!!(NS_FAILED_impl(aStatus)), 0)))) {
6341 if (!mIsBeingDestroyed) {
6342 DisplayLoadError(aStatus, url, nullptr, aChannel);
6343 }
6344 } else if (skippedUnknownProtocolNavigation) {
6345 nsTArray<nsString> params;
6346 if (NS_FAILED(((bool)(__builtin_expect(!!(NS_FAILED_impl(NS_GetSanitizedURIStringFromURI
(url, *params.AppendElement()))), 0)))
6347 NS_GetSanitizedURIStringFromURI(url, *params.AppendElement()))((bool)(__builtin_expect(!!(NS_FAILED_impl(NS_GetSanitizedURIStringFromURI
(url, *params.AppendElement()))), 0)))
) {
6348 params.LastElement().AssignLiteral(u"(unknown uri)");
6349 }
6350 nsContentUtils::ReportToConsole(
6351 nsIScriptError::warningFlag, "DOM"_ns, GetExtantDocument(),
6352 nsContentUtils::eDOM_PROPERTIES, "UnknownProtocolNavigationPrevented",
6353 params);
6354 }
6355 } else {
6356 // If we have a host
6357 nsCOMPtr<nsILoadInfo> loadInfo = aChannel->LoadInfo();
6358 PredictorLearnRedirect(url, aChannel, loadInfo->GetOriginAttributes());
6359 }
6360
6361 if (hadErrorStatus) {
6362 // Don't send session store updates if the reason EndPageLoad was called is
6363 // because we are process switching. Sometimes the update takes too long and
6364 // incorrectly overrides session store data from the following load.
6365 return NS_OK;
6366 }
6367 if (SessionStorePlatformCollection()) {
6368 if (WindowContext* windowContext =
6369 mBrowsingContext->GetCurrentWindowContext()) {
6370 using Change = SessionStoreChangeListener::Change;
6371
6372 // We've finished loading the page and now we want to collect all the
6373 // session store state that the page is initialized with.
6374 SessionStoreChangeListener::CollectSessionStoreData(
6375 windowContext,
6376 EnumSet<Change>(Change::Input, Change::Scroll, Change::SessionHistory,
6377 Change::WireFrame));
6378 }
6379 }
6380
6381 return NS_OK;
6382}
6383
6384//*****************************************************************************
6385// nsDocShell: Content Viewer Management
6386//*****************************************************************************
6387
6388nsresult nsDocShell::EnsureDocumentViewer() {
6389 if (mDocumentViewer) {
6390 return NS_OK;
6391 }
6392 if (mIsBeingDestroyed) {
6393 return NS_ERROR_FAILURE;
6394 }
6395
6396 nsCOMPtr<nsIContentSecurityPolicy> cspToInheritForAboutBlank;
6397 nsCOMPtr<nsIURI> baseURI;
6398 nsIPrincipal* principal = GetInheritedPrincipal(false);
6399 nsIPrincipal* partitionedPrincipal = GetInheritedPrincipal(false, true);
6400
6401 nsCOMPtr<nsIDocShellTreeItem> parentItem;
6402 GetInProcessSameTypeParent(getter_AddRefs(parentItem));
6403 if (parentItem) {
6404 if (nsCOMPtr<nsPIDOMWindowOuter> domWin = GetWindow()) {
6405 nsCOMPtr<Element> parentElement = domWin->GetFrameElementInternal();
6406 if (parentElement) {
6407 baseURI = parentElement->GetBaseURI();
6408 cspToInheritForAboutBlank = parentElement->GetCsp();
6409 }
6410 }
6411 }
6412
6413 nsresult rv = CreateAboutBlankDocumentViewer(
6414 principal, partitionedPrincipal, cspToInheritForAboutBlank, baseURI,
6415 /* aIsInitialDocument */ true);
6416
6417 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"
, 6417); return NS_ERROR_UNEXPECTED; } } while (false)
;
6418
6419 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
6420 RefPtr<Document> doc(GetDocument());
6421 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"
, 6423); AnnotateMozCrashReason("MOZ_ASSERT" "(" "doc" ") (" "Should have doc if CreateAboutBlankDocumentViewer "
"succeeded!" ")"); do { *((volatile int*)__null) = 6423; __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
6422 "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"
, 6423); AnnotateMozCrashReason("MOZ_ASSERT" "(" "doc" ") (" "Should have doc if CreateAboutBlankDocumentViewer "
"succeeded!" ")"); do { *((volatile int*)__null) = 6423; __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
6423 "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"
, 6423); AnnotateMozCrashReason("MOZ_ASSERT" "(" "doc" ") (" "Should have doc if CreateAboutBlankDocumentViewer "
"succeeded!" ")"); do { *((volatile int*)__null) = 6423; __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
;
6424 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"
, 6424); AnnotateMozCrashReason("MOZ_ASSERT" "(" "doc->IsInitialDocument()"
") (" "Document should be initial document" ")"); do { *((volatile
int*)__null) = 6424; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
6425
6426 // Documents created using EnsureDocumentViewer may be transient
6427 // placeholders created by framescripts before content has a
6428 // chance to load. In some cases, window.open(..., "noopener")
6429 // will create such a document and then synchronously tear it
6430 // down, firing a "pagehide" event. Doing so violates our
6431 // assertions about DocGroups. It's easier to silence the
6432 // assertion here than to avoid creating the extra document.
6433 doc->IgnoreDocGroupMismatches();
6434 }
6435
6436 return rv;
6437}
6438
6439nsresult nsDocShell::CreateAboutBlankDocumentViewer(
6440 nsIPrincipal* aPrincipal, nsIPrincipal* aPartitionedPrincipal,
6441 nsIContentSecurityPolicy* aCSP, nsIURI* aBaseURI, bool aIsInitialDocument,
6442 const Maybe<nsILoadInfo::CrossOriginEmbedderPolicy>& aCOEP,
6443 bool aTryToSaveOldPresentation, bool aCheckPermitUnload,
6444 WindowGlobalChild* aActor) {
6445 RefPtr<Document> blankDoc;
6446 nsCOMPtr<nsIDocumentViewer> viewer;
6447 nsresult rv = NS_ERROR_FAILURE;
6448
6449 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
)
6450 MarkerStack::Capture())do { ; do { if (profiler_is_collecting_markers()) { ::profiler_add_marker_impl
("CreateAboutBlankDocumentViewer", ::geckoprofiler::category::
DOM, MarkerStack::Capture()); } } while (false); } while (false
)
;
6451
6452 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"
, 6452); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aActor->DocumentPrincipal() == aPrincipal"
")"); do { *((volatile int*)__null) = 6452; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
6453
6454 /* mCreatingDocument should never be true at this point. However, it's
6455 a theoretical possibility. We want to know about it and make it stop,
6456 and this sounds like a job for an assertion. */
6457 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"
, 6458); MOZ_PretendNoReturn(); } } while (0)
6458 "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"
, 6458); MOZ_PretendNoReturn(); } } while (0)
;
6459 if (mCreatingDocument) {
6460 return NS_ERROR_FAILURE;
6461 }
6462
6463 if (!mBrowsingContext->AncestorsAreCurrent() ||
6464 mBrowsingContext->IsInBFCache()) {
6465 mBrowsingContext->RemoveRootFromBFCacheSync();
6466 return NS_ERROR_NOT_AVAILABLE;
6467 }
6468
6469 // mDocumentViewer->PermitUnload may release |this| docshell.
6470 nsCOMPtr<nsIDocShell> kungFuDeathGrip(this);
6471
6472 AutoRestore<bool> creatingDocument(mCreatingDocument);
6473 mCreatingDocument = true;
6474
6475 if (aPrincipal && !aPrincipal->IsSystemPrincipal() &&
6476 mItemType != typeChrome) {
6477 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"
, 6478); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPrincipal->OriginAttributesRef() == mBrowsingContext->OriginAttributesRef()"
")"); do { *((volatile int*)__null) = 6478; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6478 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"
, 6478); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPrincipal->OriginAttributesRef() == mBrowsingContext->OriginAttributesRef()"
")"); do { *((volatile int*)__null) = 6478; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6479 }
6480
6481 // Make sure timing is created. But first record whether we had it
6482 // already, so we don't clobber the timing for an in-progress load.
6483 bool hadTiming = mTiming;
6484 bool toBeReset = MaybeInitTiming();
6485 if (mDocumentViewer) {
6486 if (aCheckPermitUnload) {
6487 // We've got a content viewer already. Make sure the user
6488 // permits us to discard the current document and replace it
6489 // with about:blank. And also ensure we fire the unload events
6490 // in the current document.
6491
6492 // Unload gets fired first for
6493 // document loaded from the session history.
6494 mTiming->NotifyBeforeUnload();
6495
6496 bool okToUnload;
6497 rv = mDocumentViewer->PermitUnload(&okToUnload);
6498
6499 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && !okToUnload) {
6500 // The user chose not to unload the page, interrupt the load.
6501 MaybeResetInitTiming(toBeReset);
6502 return NS_ERROR_FAILURE;
6503 }
6504 if (mTiming) {
6505 mTiming->NotifyUnloadAccepted(mCurrentURI);
6506 }
6507 }
6508
6509 mSavingOldViewer =
6510 aTryToSaveOldPresentation &&
6511 CanSavePresentation(LOAD_NORMAL, nullptr, nullptr,
6512 /* aReportBFCacheComboTelemetry */ true);
6513
6514 // Make sure to blow away our mLoadingURI just in case. No loads
6515 // from inside this pagehide.
6516 mLoadingURI = nullptr;
6517
6518 // Stop any in-progress loading, so that we don't accidentally trigger any
6519 // PageShow notifications from Embed() interrupting our loading below.
6520 Stop();
6521
6522 // Notify the current document that it is about to be unloaded!!
6523 //
6524 // It is important to fire the unload() notification *before* any state
6525 // is changed within the DocShell - otherwise, javascript will get the
6526 // wrong information :-(
6527 //
6528 (void)FirePageHideNotification(!mSavingOldViewer);
6529 // pagehide notification might destroy this docshell.
6530 if (mIsBeingDestroyed) {
6531 return NS_ERROR_DOCSHELL_DYING;
6532 }
6533 }
6534
6535 // Now make sure we don't think we're in the middle of firing unload after
6536 // this point. This will make us fire unload when the about:blank document
6537 // unloads... but that's ok, more or less. Would be nice if it fired load
6538 // too, of course.
6539 mFiredUnloadEvent = false;
6540
6541 nsCOMPtr<nsIDocumentLoaderFactory> docFactory =
6542 nsContentUtils::FindInternalDocumentViewer("text/html"_ns);
6543
6544 if (docFactory) {
6545 nsCOMPtr<nsIPrincipal> principal, partitionedPrincipal;
6546 const uint32_t sandboxFlags =
6547 mBrowsingContext->GetHasLoadedNonInitialDocument()
6548 ? mBrowsingContext->GetSandboxFlags()
6549 : mBrowsingContext->GetInitialSandboxFlags();
6550 // If we're sandboxed, then create a new null principal. We skip
6551 // this if we're being created from WindowGlobalChild, since in
6552 // that case we already have a null principal if required.
6553 // We can't compare againt the BrowsingContext sandbox flag, since
6554 // the value was taken when the load initiated and may have since
6555 // changed.
6556 if ((sandboxFlags & SANDBOXED_ORIGIN) && !aActor) {
6557 if (aPrincipal) {
6558 principal = NullPrincipal::CreateWithInheritedAttributes(aPrincipal);
6559 } else {
6560 principal = NullPrincipal::Create(GetOriginAttributes());
6561 }
6562 partitionedPrincipal = principal;
6563 } else {
6564 principal = aPrincipal;
6565 partitionedPrincipal = aPartitionedPrincipal;
6566 }
6567
6568 // We cannot get the foreign partitioned prinicpal for the initial
6569 // about:blank page. So, we change to check if we need to use the
6570 // partitioned principal for the service worker here.
6571 MaybeCreateInitialClientSource(
6572 StoragePrincipalHelper::ShouldUsePartitionPrincipalForServiceWorker(
6573 this)
6574 ? partitionedPrincipal
6575 : principal);
6576
6577 // generate (about:blank) document to load
6578 blankDoc = nsContentDLF::CreateBlankDocument(mLoadGroup, principal,
6579 partitionedPrincipal, this);
6580 if (blankDoc) {
6581 // Hack: manually set the CSP for the new document
6582 // Please create an actual copy of the CSP (do not share the same
6583 // reference) otherwise appending a new policy within the new
6584 // document will be incorrectly propagated to the opening doc.
6585 if (aCSP) {
6586 RefPtr<nsCSPContext> cspToInherit = new nsCSPContext();
6587 cspToInherit->InitFromOther(static_cast<nsCSPContext*>(aCSP));
6588 blankDoc->SetCsp(cspToInherit);
6589 }
6590
6591 blankDoc->SetIsInitialDocument(aIsInitialDocument);
6592
6593 blankDoc->SetEmbedderPolicy(aCOEP);
6594
6595 // Hack: set the base URI manually, since this document never
6596 // got Reset() with a channel.
6597 blankDoc->SetBaseURI(aBaseURI);
6598
6599 // Copy our sandbox flags to the document. These are immutable
6600 // after being set here.
6601 blankDoc->SetSandboxFlags(sandboxFlags);
6602
6603 // create a content viewer for us and the new document
6604 docFactory->CreateInstanceForDocument(
6605 NS_ISUPPORTS_CAST(nsIDocShell*, this)static_cast<nsISupports*>(static_cast<nsIDocShell*>
(this))
, blankDoc, "view",
6606 getter_AddRefs(viewer));
6607
6608 // hook 'em up
6609 if (viewer) {
6610 viewer->SetContainer(this);
6611 rv = Embed(viewer, aActor, true, false, nullptr, mCurrentURI);
6612 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"
, 6612); return rv; } } while (false)
;
6613
6614 SetCurrentURI(blankDoc->GetDocumentURI(), nullptr,
6615 /* aFireLocationChange */ true,
6616 /* aIsInitialAboutBlank */ true,
6617 /* aLocationFlags */ 0);
6618 rv = mIsBeingDestroyed ? NS_ERROR_NOT_AVAILABLE : NS_OK;
6619 }
6620
6621 if (Element* embedderElement = blankDoc->GetEmbedderElement()) {
6622 blankDoc->InitFeaturePolicy(AsVariant(embedderElement));
6623 } else {
6624 blankDoc->InitFeaturePolicy(AsVariant(Nothing{}));
6625 }
6626 }
6627 }
6628
6629 // The transient about:blank viewer doesn't have a session history entry.
6630 SetHistoryEntryAndUpdateBC(Nothing(), Some(nullptr));
6631
6632 // Clear out our mTiming like we would in EndPageLoad, if we didn't
6633 // have one before entering this function.
6634 if (!hadTiming) {
6635 mTiming = nullptr;
6636 mBlankTiming = true;
6637 }
6638
6639 return rv;
6640}
6641
6642NS_IMETHODIMPnsresult
6643nsDocShell::CreateAboutBlankDocumentViewer(nsIPrincipal* aPrincipal,
6644 nsIPrincipal* aPartitionedPrincipal,
6645 nsIContentSecurityPolicy* aCSP) {
6646 return CreateAboutBlankDocumentViewer(aPrincipal, aPartitionedPrincipal, aCSP,
6647 nullptr,
6648 /* aIsInitialDocument */ false);
6649}
6650
6651nsresult nsDocShell::CreateDocumentViewerForActor(
6652 WindowGlobalChild* aWindowActor) {
6653 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"
, 6653); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aWindowActor"
")"); do { *((volatile int*)__null) = 6653; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6654
6655 // FIXME: WindowGlobalChild should provide the PartitionedPrincipal.
6656 // FIXME: We may want to support non-initial documents here.
6657 nsresult rv = CreateAboutBlankDocumentViewer(
6658 aWindowActor->DocumentPrincipal(), aWindowActor->DocumentPrincipal(),
6659 /* aCsp */ nullptr,
6660 /* aBaseURI */ nullptr,
6661 /* aIsInitialDocument */ true,
6662 /* aCOEP */ Nothing(),
6663 /* aTryToSaveOldPresentation */ true,
6664 /* aCheckPermitUnload */ true, aWindowActor);
6665#ifdef DEBUG1
6666 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
6667 RefPtr<Document> doc(GetDocument());
6668 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"
, 6670); AnnotateMozCrashReason("MOZ_ASSERT" "(" "doc" ") (" "Should have a document if CreateAboutBlankDocumentViewer succeeded"
")"); do { *((volatile int*)__null) = 6670; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6669 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"
, 6670); AnnotateMozCrashReason("MOZ_ASSERT" "(" "doc" ") (" "Should have a document if CreateAboutBlankDocumentViewer succeeded"
")"); do { *((volatile int*)__null) = 6670; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6670 "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"
, 6670); AnnotateMozCrashReason("MOZ_ASSERT" "(" "doc" ") (" "Should have a document if CreateAboutBlankDocumentViewer succeeded"
")"); do { *((volatile int*)__null) = 6670; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6671 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"
, 6672); AnnotateMozCrashReason("MOZ_ASSERT" "(" "doc->GetOwnerGlobal() == aWindowActor->GetWindowGlobal()"
") (" "New document should be in the same global as our actor"
")"); do { *((volatile int*)__null) = 6672; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6672 "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"
, 6672); AnnotateMozCrashReason("MOZ_ASSERT" "(" "doc->GetOwnerGlobal() == aWindowActor->GetWindowGlobal()"
") (" "New document should be in the same global as our actor"
")"); do { *((volatile int*)__null) = 6672; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6673 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"
, 6674); AnnotateMozCrashReason("MOZ_ASSERT" "(" "doc->IsInitialDocument()"
") (" "New document should be an initial document" ")"); do {
*((volatile int*)__null) = 6674; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
6674 "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"
, 6674); AnnotateMozCrashReason("MOZ_ASSERT" "(" "doc->IsInitialDocument()"
") (" "New document should be an initial document" ")"); do {
*((volatile int*)__null) = 6674; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
6675 }
6676#endif
6677
6678 return rv;
6679}
6680
6681bool nsDocShell::CanSavePresentation(uint32_t aLoadType,
6682 nsIRequest* aNewRequest,
6683 Document* aNewDocument,
6684 bool aReportBFCacheComboTelemetry) {
6685 if (!mOSHE) {
6686 return false; // no entry to save into
6687 }
6688
6689 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"
, 6690); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mozilla::SessionHistoryInParent()"
") (" "mOSHE cannot be non-null with SHIP" ")"); do { *((volatile
int*)__null) = 6690; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
6690 "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"
, 6690); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mozilla::SessionHistoryInParent()"
") (" "mOSHE cannot be non-null with SHIP" ")"); do { *((volatile
int*)__null) = 6690; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
6691 nsCOMPtr<nsIDocumentViewer> viewer = mOSHE->GetDocumentViewer();
6692 if (viewer) {
6693 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"
, 6693)
;
6694 return false;
6695 }
6696
6697 // Only save presentation for "normal" loads and link loads. Anything else
6698 // probably wants to refetch the page, so caching the old presentation
6699 // would be incorrect.
6700 if (aLoadType != LOAD_NORMAL && aLoadType != LOAD_HISTORY &&
6701 aLoadType != LOAD_LINK && aLoadType != LOAD_STOP_CONTENT &&
6702 aLoadType != LOAD_STOP_CONTENT_AND_REPLACE &&
6703 aLoadType != LOAD_ERROR_PAGE) {
6704 return false;
6705 }
6706
6707 // If the session history entry has the saveLayoutState flag set to false,
6708 // then we should not cache the presentation.
6709 if (!mOSHE->GetSaveLayoutStateFlag()) {
6710 return false;
6711 }
6712
6713 // If the document is not done loading, don't cache it.
6714 if (!mScriptGlobal || mScriptGlobal->IsLoading()) {
6715 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)
6716 ("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)
;
6717 return false;
6718 }
6719
6720 if (mScriptGlobal->WouldReuseInnerWindow(aNewDocument)) {
6721 return false;
6722 }
6723
6724 // Avoid doing the work of saving the presentation state in the case where
6725 // the content viewer cache is disabled.
6726 if (nsSHistory::GetMaxTotalViewers() == 0) {
6727 return false;
6728 }
6729
6730 // Don't cache the content viewer if we're in a subframe.
6731 if (mBrowsingContext->GetParent()) {
6732 return false; // this is a subframe load
6733 }
6734
6735 // If the document does not want its presentation cached, then don't.
6736 RefPtr<Document> doc = mScriptGlobal->GetExtantDoc();
6737
6738 uint32_t bfCacheCombo = 0;
6739 bool canSavePresentation =
6740 doc->CanSavePresentation(aNewRequest, bfCacheCombo, true);
6741 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"
, 6741); AnnotateMozCrashReason("MOZ_ASSERT" "(" "bfCacheCombo == 0"
")"); do { *((volatile int*)__null) = 6741; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
6742 if (canSavePresentation && doc->IsTopLevelContentDocument()) {
6743 auto* browsingContextGroup = mBrowsingContext->Group();
6744 nsTArray<RefPtr<BrowsingContext>>& topLevelContext =
6745 browsingContextGroup->Toplevels();
6746
6747 for (const auto& browsingContext : topLevelContext) {
6748 if (browsingContext != mBrowsingContext) {
6749 if (StaticPrefs::docshell_shistory_bfcache_require_no_opener()) {
6750 canSavePresentation = false;
6751 }
6752 bfCacheCombo |= BFCacheStatus::NOT_ONLY_TOPLEVEL_IN_BCG;
6753 break;
6754 }
6755 }
6756 }
6757
6758 if (aReportBFCacheComboTelemetry) {
6759 ReportBFCacheComboTelemetry(bfCacheCombo);
6760 }
6761 return doc && canSavePresentation;
6762}
6763
6764/* static */
6765void nsDocShell::ReportBFCacheComboTelemetry(uint32_t aCombo) {
6766 // There are 11 possible reasons to make a request fails to use BFCache
6767 // (see BFCacheStatus in dom/base/Document.h), and we'd like to record
6768 // the common combinations for reasons which make requests fail to use
6769 // BFCache. These combinations are generated based on some local browsings,
6770 // we need to adjust them when necessary.
6771 enum BFCacheStatusCombo : uint32_t {
6772 BFCACHE_SUCCESS,
6773 NOT_ONLY_TOPLEVEL = mozilla::dom::BFCacheStatus::NOT_ONLY_TOPLEVEL_IN_BCG,
6774 // If both unload and beforeunload listeners are presented, it'll be
6775 // recorded as unload
6776 UNLOAD = mozilla::dom::BFCacheStatus::UNLOAD_LISTENER,
6777 UNLOAD_REQUEST = mozilla::dom::BFCacheStatus::UNLOAD_LISTENER |
6778 mozilla::dom::BFCacheStatus::REQUEST,
6779 REQUEST = mozilla::dom::BFCacheStatus::REQUEST,
6780 UNLOAD_REQUEST_PEER = mozilla::dom::BFCacheStatus::UNLOAD_LISTENER |
6781 mozilla::dom::BFCacheStatus::REQUEST |
6782 mozilla::dom::BFCacheStatus::ACTIVE_PEER_CONNECTION,
6783 UNLOAD_REQUEST_PEER_MSE =
6784 mozilla::dom::BFCacheStatus::UNLOAD_LISTENER |
6785 mozilla::dom::BFCacheStatus::REQUEST |
6786 mozilla::dom::BFCacheStatus::ACTIVE_PEER_CONNECTION |
6787 mozilla::dom::BFCacheStatus::CONTAINS_MSE_CONTENT,
6788 UNLOAD_REQUEST_MSE = mozilla::dom::BFCacheStatus::UNLOAD_LISTENER |
6789 mozilla::dom::BFCacheStatus::REQUEST |
6790 mozilla::dom::BFCacheStatus::CONTAINS_MSE_CONTENT,
6791 SUSPENDED_UNLOAD_REQUEST_PEER =
6792 mozilla::dom::BFCacheStatus::SUSPENDED |
6793 mozilla::dom::BFCacheStatus::UNLOAD_LISTENER |
6794 mozilla::dom::BFCacheStatus::REQUEST |
6795 mozilla::dom::BFCacheStatus::ACTIVE_PEER_CONNECTION,
6796 REMOTE_SUBFRAMES = mozilla::dom::BFCacheStatus::CONTAINS_REMOTE_SUBFRAMES,
6797 BEFOREUNLOAD = mozilla::dom::BFCacheStatus::BEFOREUNLOAD_LISTENER,
6798 };
6799
6800 // Beforeunload is recorded as a blocker only if it is the only one to block
6801 // bfcache.
6802 if (aCombo != mozilla::dom::BFCacheStatus::BEFOREUNLOAD_LISTENER) {
6803 aCombo &= ~mozilla::dom::BFCacheStatus::BEFOREUNLOAD_LISTENER;
6804 }
6805 switch (aCombo) {
6806 case BFCACHE_SUCCESS:
6807 Telemetry::AccumulateCategorical(
6808 Telemetry::LABELS_BFCACHE_COMBO::BFCache_Success);
6809 break;
6810 case NOT_ONLY_TOPLEVEL:
6811 if (StaticPrefs::docshell_shistory_bfcache_require_no_opener()) {
6812 Telemetry::AccumulateCategorical(
6813 Telemetry::LABELS_BFCACHE_COMBO::Other);
6814 break;
6815 }
6816 Telemetry::AccumulateCategorical(
6817 Telemetry::LABELS_BFCACHE_COMBO::BFCache_Success);
6818 Telemetry::AccumulateCategorical(
6819 Telemetry::LABELS_BFCACHE_COMBO::Success_Not_Toplevel);
6820 break;
6821 case UNLOAD:
6822 Telemetry::AccumulateCategorical(Telemetry::LABELS_BFCACHE_COMBO::Unload);
6823 break;
6824 case BEFOREUNLOAD:
6825 Telemetry::AccumulateCategorical(
6826 Telemetry::LABELS_BFCACHE_COMBO::Beforeunload);
6827 break;
6828 case UNLOAD_REQUEST:
6829 Telemetry::AccumulateCategorical(
6830 Telemetry::LABELS_BFCACHE_COMBO::Unload_Req);
6831 break;
6832 case REQUEST:
6833 Telemetry::AccumulateCategorical(Telemetry::LABELS_BFCACHE_COMBO::Req);
6834 break;
6835 case UNLOAD_REQUEST_PEER:
6836 Telemetry::AccumulateCategorical(
6837 Telemetry::LABELS_BFCACHE_COMBO::Unload_Req_Peer);
6838 break;
6839 case UNLOAD_REQUEST_PEER_MSE:
6840 Telemetry::AccumulateCategorical(
6841 Telemetry::LABELS_BFCACHE_COMBO::Unload_Req_Peer_MSE);
6842 break;
6843 case UNLOAD_REQUEST_MSE:
6844 Telemetry::AccumulateCategorical(
6845 Telemetry::LABELS_BFCACHE_COMBO::Unload_Req_MSE);
6846 break;
6847 case SUSPENDED_UNLOAD_REQUEST_PEER:
6848 Telemetry::AccumulateCategorical(
6849 Telemetry::LABELS_BFCACHE_COMBO::SPD_Unload_Req_Peer);
6850 break;
6851 case REMOTE_SUBFRAMES:
6852 Telemetry::AccumulateCategorical(
6853 Telemetry::LABELS_BFCACHE_COMBO::Remote_Subframes);
6854 break;
6855 default:
6856 Telemetry::AccumulateCategorical(Telemetry::LABELS_BFCACHE_COMBO::Other);
6857 break;
6858 }
6859};
6860
6861void nsDocShell::ReattachEditorToWindow(nsISHEntry* aSHEntry) {
6862 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"
, 6862); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mozilla::SessionHistoryInParent()"
")"); do { *((volatile int*)__null) = 6862; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6863 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"
, 6863); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mIsBeingDestroyed"
")"); do { *((volatile int*)__null) = 6863; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6864
6865 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"
, 6866); MOZ_PretendNoReturn(); } } while (0)
6866 "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"
, 6866); MOZ_PretendNoReturn(); } } while (0)
;
6867 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"
, 6868); MOZ_PretendNoReturn(); } } while (0)
6868 "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"
, 6868); MOZ_PretendNoReturn(); } } while (0)
;
6869
6870 if (mEditorData || !aSHEntry) {
6871 return;
6872 }
6873
6874 mEditorData = WrapUnique(aSHEntry->ForgetEditorData());
6875 if (mEditorData) {
6876#ifdef DEBUG1
6877 nsresult rv =
6878#endif
6879 mEditorData->ReattachToWindow(this);
6880 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"
, 6880); MOZ_PretendNoReturn(); } } while (0)
;
6881 }
6882}
6883
6884void nsDocShell::DetachEditorFromWindow() {
6885 if (!mEditorData || mEditorData->WaitingForLoad()) {
6886 // If there's nothing to detach, or if the editor data is actually set
6887 // up for the _new_ page that's coming in, don't detach.
6888 return;
6889 }
6890
6891 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"
, 6892); MOZ_PretendNoReturn(); } } while (0)
6892 "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"
, 6892); MOZ_PretendNoReturn(); } } while (0)
;
6893
6894 nsresult res = mEditorData->DetachFromWindow();
6895 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"
, 6895); MOZ_PretendNoReturn(); } } while (0)
;
6896
6897 if (NS_SUCCEEDED(res)((bool)(__builtin_expect(!!(!NS_FAILED_impl(res)), 1)))) {
6898 // Make mOSHE hold the owning ref to the editor data.
6899 if (mOSHE) {
6900 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"
, 6902); 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) = 6902; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6901 "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"
, 6902); 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) = 6902; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6902 "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"
, 6902); 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) = 6902; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6903 mOSHE->SetEditorData(mEditorData.release());
6904 } else {
6905 mEditorData = nullptr;
6906 }
6907 }
6908
6909#ifdef DEBUG1
6910 {
6911 bool isEditable;
6912 GetEditable(&isEditable);
6913 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"
, 6914); MOZ_PretendNoReturn(); } } while (0)
6914 "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"
, 6914); MOZ_PretendNoReturn(); } } while (0)
;
6915 }
6916#endif // DEBUG
6917}
6918
6919nsresult nsDocShell::CaptureState() {
6920 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"
, 6920); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mozilla::SessionHistoryInParent()"
")"); do { *((volatile int*)__null) = 6920; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6921
6922 if (!mOSHE || mOSHE == mLSHE) {
6923 // No entry to save into, or we're replacing the existing entry.
6924 return NS_ERROR_FAILURE;
6925 }
6926
6927 if (!mScriptGlobal) {
6928 return NS_ERROR_FAILURE;
6929 }
6930
6931 nsCOMPtr<nsISupports> windowState = mScriptGlobal->SaveWindowState();
6932 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"
, 6932); return NS_ERROR_FAILURE; } } while (false)
;
6933
6934 if (MOZ_UNLIKELY(MOZ_LOG_TEST(gPageCacheLog, LogLevel::Debug))(__builtin_expect(!!((__builtin_expect(!!(mozilla::detail::log_test
(gPageCacheLog, LogLevel::Debug)), 0))), 0))
) {
6935 nsAutoCString spec;
6936 nsCOMPtr<nsIURI> uri = mOSHE->GetURI();
6937 if (uri) {
6938 uri->GetSpec(spec);
6939 }
6940 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)
6941 ("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)
;
6942 }
6943
6944 mOSHE->SetWindowState(windowState);
6945
6946 // Suspend refresh URIs and save off the timer queue
6947 mOSHE->SetRefreshURIList(mSavedRefreshURIList);
6948
6949 // Capture the current content viewer bounds.
6950 if (mDocumentViewer) {
6951 nsIntRect bounds;
6952 mDocumentViewer->GetBounds(bounds);
6953 mOSHE->SetViewerBounds(bounds);
6954 }
6955
6956 // Capture the docshell hierarchy.
6957 mOSHE->ClearChildShells();
6958
6959 uint32_t childCount = mChildList.Length();
6960 for (uint32_t i = 0; i < childCount; ++i) {
6961 nsCOMPtr<nsIDocShellTreeItem> childShell = do_QueryInterface(ChildAt(i));
6962 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"
, 6962); MOZ_PretendNoReturn(); } } while (0)
;
6963
6964 mOSHE->AddChildShell(childShell);
6965 }
6966
6967 return NS_OK;
6968}
6969
6970NS_IMETHODIMPnsresult
6971nsDocShell::RestorePresentationEvent::Run() {
6972 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"
, 6972); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mozilla::SessionHistoryInParent()"
")"); do { *((volatile int*)__null) = 6972; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6973
6974 if (mDocShell && NS_FAILED(mDocShell->RestoreFromHistory())((bool)(__builtin_expect(!!(NS_FAILED_impl(mDocShell->RestoreFromHistory
())), 0)))
) {
6975 NS_WARNING("RestoreFromHistory failed")NS_DebugBreak(NS_DEBUG_WARNING, "RestoreFromHistory failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 6975)
;
6976 }
6977 return NS_OK;
6978}
6979
6980NS_IMETHODIMPnsresult
6981nsDocShell::BeginRestore(nsIDocumentViewer* aDocumentViewer, bool aTop) {
6982 MOZ_ASSERT(!mozilla::SessionHistoryInParent())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mozilla::SessionHistoryInParent())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mozilla::SessionHistoryInParent
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!mozilla::SessionHistoryInParent()", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 6982); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mozilla::SessionHistoryInParent()"
")"); do { *((volatile int*)__null) = 6982; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6983
6984 nsresult rv;
6985 if (!aDocumentViewer) {
6986 rv = EnsureDocumentViewer();
6987 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"
, 6987); return rv; } } while (false)
;
6988
6989 aDocumentViewer = mDocumentViewer;
6990 }
6991
6992 // Dispatch events for restoring the presentation. We try to simulate
6993 // the progress notifications loading the document would cause, so we add
6994 // the document's channel to the loadgroup to initiate stateChange
6995 // notifications.
6996
6997 RefPtr<Document> doc = aDocumentViewer->GetDocument();
6998 if (doc) {
6999 nsIChannel* channel = doc->GetChannel();
7000 if (channel) {
7001 mEODForCurrentDocument = false;
7002 mIsRestoringDocument = true;
7003 mLoadGroup->AddRequest(channel, nullptr);
7004 mIsRestoringDocument = false;
7005 }
7006 }
7007
7008 if (!aTop) {
7009 // This point corresponds to us having gotten OnStartRequest or
7010 // STATE_START, so do the same thing that CreateDocumentViewer does at
7011 // this point to ensure that unload/pagehide events for this document
7012 // will fire when it's unloaded again.
7013 mFiredUnloadEvent = false;
7014
7015 // For non-top frames, there is no notion of making sure that the
7016 // previous document is in the domwindow when STATE_START notifications
7017 // happen. We can just call BeginRestore for all of the child shells
7018 // now.
7019 rv = BeginRestoreChildren();
7020 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"
, 7020); return rv; } } while (false)
;
7021 }
7022
7023 return NS_OK;
7024}
7025
7026nsresult nsDocShell::BeginRestoreChildren() {
7027 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"
, 7027); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mozilla::SessionHistoryInParent()"
")"); do { *((volatile int*)__null) = 7027; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7028
7029 for (auto* childDocLoader : mChildList.ForwardRange()) {
7030 nsCOMPtr<nsIDocShell> child = do_QueryObject(childDocLoader);
7031 if (child) {
7032 nsresult rv = child->BeginRestore(nullptr, false);
7033 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"
, 7033); return rv; } } while (false)
;
7034 }
7035 }
7036 return NS_OK;
7037}
7038
7039NS_IMETHODIMPnsresult
7040nsDocShell::FinishRestore() {
7041 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"
, 7041); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mozilla::SessionHistoryInParent()"
")"); do { *((volatile int*)__null) = 7041; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7042
7043 // First we call finishRestore() on our children. In the simulated load,
7044 // all of the child frames finish loading before the main document.
7045
7046 for (auto* childDocLoader : mChildList.ForwardRange()) {
7047 nsCOMPtr<nsIDocShell> child = do_QueryObject(childDocLoader);
7048 if (child) {
7049 child->FinishRestore();
7050 }
7051 }
7052
7053 if (mOSHE && mOSHE->HasDetachedEditor()) {
7054 ReattachEditorToWindow(mOSHE);
7055 }
7056
7057 RefPtr<Document> doc = GetDocument();
7058 if (doc) {
7059 // Finally, we remove the request from the loadgroup. This will
7060 // cause onStateChange(STATE_STOP) to fire, which will fire the
7061 // pageshow event to the chrome.
7062
7063 nsIChannel* channel = doc->GetChannel();
7064 if (channel) {
7065 mIsRestoringDocument = true;
7066 mLoadGroup->RemoveRequest(channel, nullptr, NS_OK);
7067 mIsRestoringDocument = false;
7068 }
7069 }
7070
7071 return NS_OK;
7072}
7073
7074NS_IMETHODIMPnsresult
7075nsDocShell::GetRestoringDocument(bool* aRestoring) {
7076 *aRestoring = mIsRestoringDocument;
7077 return NS_OK;
7078}
7079
7080nsresult nsDocShell::RestorePresentation(nsISHEntry* aSHEntry,
7081 bool* aRestoring) {
7082 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"
, 7082); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mozilla::SessionHistoryInParent()"
")"); do { *((volatile int*)__null) = 7082; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7083 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"
, 7083); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mIsBeingDestroyed"
")"); do { *((volatile int*)__null) = 7083; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7084
7085 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"
, 7086); MOZ_PretendNoReturn(); } } while (0)
7086 "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"
, 7086); MOZ_PretendNoReturn(); } } while (0)
;
7087
7088 nsCOMPtr<nsIDocumentViewer> viewer = aSHEntry->GetDocumentViewer();
7089
7090 nsAutoCString spec;
7091 if (MOZ_UNLIKELY(MOZ_LOG_TEST(gPageCacheLog, LogLevel::Debug))(__builtin_expect(!!((__builtin_expect(!!(mozilla::detail::log_test
(gPageCacheLog, LogLevel::Debug)), 0))), 0))
) {
7092 nsCOMPtr<nsIURI> uri = aSHEntry->GetURI();
7093 if (uri) {
7094 uri->GetSpec(spec);
7095 }
7096 }
7097
7098 *aRestoring = false;
7099
7100 if (!viewer) {
7101 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)
7102 ("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)
;
7103 return NS_OK;
7104 }
7105
7106 // We need to make sure the content viewer's container is this docshell.
7107 // In subframe navigation, it's possible for the docshell that the
7108 // content viewer was originally loaded into to be replaced with a
7109 // different one. We don't currently support restoring the presentation
7110 // in that case.
7111
7112 nsCOMPtr<nsIDocShell> container;
7113 viewer->GetContainer(getter_AddRefs(container));
7114 if (!::SameCOMIdentity(container, GetAsSupports(this))) {
7115 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)
7116 ("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)
;
7117 aSHEntry->SetDocumentViewer(nullptr);
7118 return NS_ERROR_FAILURE;
7119 }
7120
7121 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"
, 7121); MOZ_PretendNoReturn(); } } while (0)
;
7122
7123 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)
7124 ("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)
;
7125
7126 SetHistoryEntryAndUpdateBC(Some(aSHEntry), Nothing());
7127
7128 // Post an event that will remove the request after we've returned
7129 // to the event loop. This mimics the way it is called by nsIChannel
7130 // implementations.
7131
7132 // Revoke any pending restore (just in case).
7133 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"
, 7134); MOZ_PretendNoReturn(); } } while (0)
7134 "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"
, 7134); MOZ_PretendNoReturn(); } } while (0)
;
7135 mRestorePresentationEvent.Revoke();
7136
7137 RefPtr<RestorePresentationEvent> evt = new RestorePresentationEvent(this);
7138 nsresult rv = Dispatch(do_AddRef(evt));
7139 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
7140 mRestorePresentationEvent = evt.get();
7141 // The rest of the restore processing will happen on our event
7142 // callback.
7143 *aRestoring = true;
7144 }
7145
7146 return rv;
7147}
7148
7149namespace {
7150class MOZ_STACK_CLASS PresentationEventForgetter {
7151 public:
7152 explicit PresentationEventForgetter(
7153 nsRevocableEventPtr<nsDocShell::RestorePresentationEvent>&
7154 aRestorePresentationEvent)
7155 : mRestorePresentationEvent(aRestorePresentationEvent),
7156 mEvent(aRestorePresentationEvent.get()) {}
7157
7158 ~PresentationEventForgetter() { Forget(); }
7159
7160 void Forget() {
7161 if (mRestorePresentationEvent.get() == mEvent) {
7162 mRestorePresentationEvent.Forget();
7163 mEvent = nullptr;
7164 }
7165 }
7166
7167 private:
7168 nsRevocableEventPtr<nsDocShell::RestorePresentationEvent>&
7169 mRestorePresentationEvent;
7170 RefPtr<nsDocShell::RestorePresentationEvent> mEvent;
7171};
7172
7173} // namespace
7174
7175bool nsDocShell::SandboxFlagsImplyCookies(const uint32_t& aSandboxFlags) {
7176 return (aSandboxFlags & (SANDBOXED_ORIGIN | SANDBOXED_SCRIPTS)) == 0;
7177}
7178
7179nsresult nsDocShell::RestoreFromHistory() {
7180 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"
, 7180); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mozilla::SessionHistoryInParent()"
")"); do { *((volatile int*)__null) = 7180; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7181 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"
, 7181); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mRestorePresentationEvent.IsPending()"
")"); do { *((volatile int*)__null) = 7181; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7182 PresentationEventForgetter forgetter(mRestorePresentationEvent);
7183
7184 // This section of code follows the same ordering as CreateDocumentViewer.
7185 if (!mLSHE) {
7186 return NS_ERROR_FAILURE;
7187 }
7188
7189 nsCOMPtr<nsIDocumentViewer> viewer = mLSHE->GetDocumentViewer();
7190 if (!viewer) {
7191 return NS_ERROR_FAILURE;
7192 }
7193
7194 if (mSavingOldViewer) {
7195 // We determined that it was safe to cache the document presentation
7196 // at the time we initiated the new load. We need to check whether
7197 // it's still safe to do so, since there may have been DOM mutations
7198 // or new requests initiated.
7199 RefPtr<Document> doc = viewer->GetDocument();
7200 nsIRequest* request = nullptr;
7201 if (doc) {
7202 request = doc->GetChannel();
7203 }
7204 mSavingOldViewer = CanSavePresentation(
7205 mLoadType, request, doc, /* aReportBFCacheComboTelemetry */ false);
7206 }
7207
7208 // Protect against mLSHE going away via a load triggered from
7209 // pagehide or unload.
7210 nsCOMPtr<nsISHEntry> origLSHE = mLSHE;
7211
7212 // Make sure to blow away our mLoadingURI just in case. No loads
7213 // from inside this pagehide.
7214 mLoadingURI = nullptr;
7215
7216 // Notify the old content viewer that it's being hidden.
7217 FirePageHideNotification(!mSavingOldViewer);
7218 // pagehide notification might destroy this docshell.
7219 if (mIsBeingDestroyed) {
7220 return NS_ERROR_DOCSHELL_DYING;
7221 }
7222
7223 // If mLSHE was changed as a result of the pagehide event, then
7224 // something else was loaded. Don't finish restoring.
7225 if (mLSHE != origLSHE) {
7226 return NS_OK;
7227 }
7228
7229 // Add the request to our load group. We do this before swapping out
7230 // the content viewers so that consumers of STATE_START can access
7231 // the old document. We only deal with the toplevel load at this time --
7232 // to be consistent with normal document loading, subframes cannot start
7233 // loading until after data arrives, which is after STATE_START completes.
7234
7235 RefPtr<RestorePresentationEvent> currentPresentationRestoration =
7236 mRestorePresentationEvent.get();
7237 Stop();
7238 // Make sure we're still restoring the same presentation.
7239 // If we aren't, docshell is in process doing another load already.
7240 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"
, 7241); return NS_ERROR_UNEXPECTED; } } while (false)
7241 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"
, 7241); return NS_ERROR_UNEXPECTED; } } while (false)
;
7242 BeginRestore(viewer, true);
7243 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"
, 7244); return NS_ERROR_UNEXPECTED; } } while (false)
7244 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"
, 7244); return NS_ERROR_UNEXPECTED; } } while (false)
;
7245 forgetter.Forget();
7246
7247 // Set mFiredUnloadEvent = false so that the unload handler for the
7248 // *new* document will fire.
7249 mFiredUnloadEvent = false;
7250
7251 mURIResultedInDocument = true;
7252 RefPtr<ChildSHistory> rootSH = GetRootSessionHistory();
7253 if (rootSH) {
7254 mPreviousEntryIndex = rootSH->Index();
7255 rootSH->LegacySHistory()->UpdateIndex();
7256 mLoadedEntryIndex = rootSH->Index();
7257 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)
7258 ("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)
7259 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)
;
7260 }
7261
7262 // Rather than call Embed(), we will retrieve the viewer from the session
7263 // history entry and swap it in.
7264 // XXX can we refactor this so that we can just call Embed()?
7265 PersistLayoutHistoryState();
7266 nsresult rv;
7267 if (mDocumentViewer) {
7268 if (mSavingOldViewer && NS_FAILED(CaptureState())((bool)(__builtin_expect(!!(NS_FAILED_impl(CaptureState())), 0
)))
) {
7269 if (mOSHE) {
7270 mOSHE->SyncPresentationState();
7271 }
7272 mSavingOldViewer = false;
7273 }
7274 }
7275
7276 mSavedRefreshURIList = nullptr;
7277
7278 // In cases where we use a transient about:blank viewer between loads,
7279 // we never show the transient viewer, so _its_ previous viewer is never
7280 // unhooked from the view hierarchy. Destroy any such previous viewer now,
7281 // before we grab the root view sibling, so that we don't grab a view
7282 // that's about to go away.
7283
7284 if (mDocumentViewer) {
7285 // Make sure to hold a strong ref to previousViewer here while we
7286 // drop the reference to it from mDocumentViewer.
7287 nsCOMPtr<nsIDocumentViewer> previousViewer =
7288 mDocumentViewer->GetPreviousViewer();
7289 if (previousViewer) {
7290 mDocumentViewer->SetPreviousViewer(nullptr);
7291 previousViewer->Destroy();
7292 }
7293 }
7294
7295 // Save off the root view's parent and sibling so that we can insert the
7296 // new content viewer's root view at the same position. Also save the
7297 // bounds of the root view's widget.
7298
7299 nsView* rootViewSibling = nullptr;
7300 nsView* rootViewParent = nullptr;
7301 nsIntRect newBounds(0, 0, 0, 0);
7302
7303 PresShell* oldPresShell = GetPresShell();
7304 if (oldPresShell) {
7305 nsViewManager* vm = oldPresShell->GetViewManager();
7306 if (vm) {
7307 nsView* oldRootView = vm->GetRootView();
7308
7309 if (oldRootView) {
7310 rootViewSibling = oldRootView->GetNextSibling();
7311 rootViewParent = oldRootView->GetParent();
7312
7313 mDocumentViewer->GetBounds(newBounds);
7314 }
7315 }
7316 }
7317
7318 nsCOMPtr<nsIContent> container;
7319 RefPtr<Document> sibling;
7320 if (rootViewParent && rootViewParent->GetParent()) {
7321 nsIFrame* frame = rootViewParent->GetParent()->GetFrame();
7322 container = frame ? frame->GetContent() : nullptr;
7323 }
7324 if (rootViewSibling) {
7325 nsIFrame* frame = rootViewSibling->GetFrame();
7326 sibling = frame ? frame->PresShell()->GetDocument() : nullptr;
7327 }
7328
7329 // Transfer ownership to mDocumentViewer. By ensuring that either the
7330 // docshell or the session history, but not both, have references to the
7331 // content viewer, we prevent the viewer from being torn down after
7332 // Destroy() is called.
7333
7334 if (mDocumentViewer) {
7335 mDocumentViewer->Close(mSavingOldViewer ? mOSHE.get() : nullptr);
7336 viewer->SetPreviousViewer(mDocumentViewer);
7337 }
7338 if (mOSHE && (!mDocumentViewer || !mSavingOldViewer)) {
7339 // We don't plan to save a viewer in mOSHE; tell it to drop
7340 // any other state it's holding.
7341 mOSHE->SyncPresentationState();
7342 }
7343
7344 // Order the mDocumentViewer setup just like Embed does.
7345 mDocumentViewer = nullptr;
7346
7347 // Now that we're about to switch documents, forget all of our children.
7348 // Note that we cached them as needed up in CaptureState above.
7349 DestroyChildren();
7350
7351 mDocumentViewer.swap(viewer);
7352
7353 // Grab all of the related presentation from the SHEntry now.
7354 // Clearing the viewer from the SHEntry will clear all of this state.
7355 nsCOMPtr<nsISupports> windowState = mLSHE->GetWindowState();
7356 mLSHE->SetWindowState(nullptr);
7357
7358 bool sticky = mLSHE->GetSticky();
7359
7360 RefPtr<Document> document = mDocumentViewer->GetDocument();
7361
7362 nsCOMArray<nsIDocShellTreeItem> childShells;
7363 int32_t i = 0;
7364 nsCOMPtr<nsIDocShellTreeItem> child;
7365 while (NS_SUCCEEDED(mLSHE->ChildShellAt(i++, getter_AddRefs(child)))((bool)(__builtin_expect(!!(!NS_FAILED_impl(mLSHE->ChildShellAt
(i++, getter_AddRefs(child)))), 1)))
&&
7366 child) {
7367 childShells.AppendObject(child);
7368 }
7369
7370 // get the previous content viewer size
7371 nsIntRect oldBounds(0, 0, 0, 0);
7372 mLSHE->GetViewerBounds(oldBounds);
7373
7374 // Restore the refresh URI list. The refresh timers will be restarted
7375 // when EndPageLoad() is called.
7376 nsCOMPtr<nsIMutableArray> refreshURIList = mLSHE->GetRefreshURIList();
7377
7378 // Reattach to the window object.
7379 mIsRestoringDocument = true; // for MediaDocument::BecomeInteractive
7380 rv = mDocumentViewer->Open(windowState, mLSHE);
7381 mIsRestoringDocument = false;
7382
7383 // Hack to keep nsDocShellEditorData alive across the
7384 // SetContentViewer(nullptr) call below.
7385 UniquePtr<nsDocShellEditorData> data(mLSHE->ForgetEditorData());
7386
7387 // Now remove it from the cached presentation.
7388 mLSHE->SetDocumentViewer(nullptr);
7389 mEODForCurrentDocument = false;
7390
7391 mLSHE->SetEditorData(data.release());
7392
7393#ifdef DEBUG1
7394 {
7395 nsCOMPtr<nsIMutableArray> refreshURIs = mLSHE->GetRefreshURIList();
7396 nsCOMPtr<nsIDocShellTreeItem> childShell;
7397 mLSHE->ChildShellAt(0, getter_AddRefs(childShell));
7398 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"
, 7399); MOZ_PretendNoReturn(); } } while (0)
7399 "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"
, 7399); MOZ_PretendNoReturn(); } } while (0)
;
7400 }
7401#endif
7402
7403 // Restore the sticky state of the viewer. The viewer has set this state
7404 // on the history entry in Destroy() just before marking itself non-sticky,
7405 // to avoid teardown of the presentation.
7406 mDocumentViewer->SetSticky(sticky);
7407
7408 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"
, 7408); return rv; } } while (false)
;
7409
7410 // mLSHE is now our currently-loaded document.
7411 SetHistoryEntryAndUpdateBC(Nothing(), Some<nsISHEntry*>(mLSHE));
7412
7413 // We aren't going to restore any items from the LayoutHistoryState,
7414 // but we don't want them to stay around in case the page is reloaded.
7415 SetLayoutHistoryState(nullptr);
7416
7417 // This is the end of our Embed() replacement
7418
7419 mSavingOldViewer = false;
7420 mEODForCurrentDocument = false;
7421
7422 if (document) {
7423 RefPtr<nsDocShell> parent = GetInProcessParentDocshell();
7424 if (parent) {
7425 RefPtr<Document> d = parent->GetDocument();
7426 if (d) {
7427 if (d->EventHandlingSuppressed()) {
7428 document->SuppressEventHandling(d->EventHandlingSuppressed());
7429 }
7430 }
7431 }
7432
7433 // Use the uri from the mLSHE we had when we entered this function
7434 // (which need not match the document's URI if anchors are involved),
7435 // since that's the history entry we're loading. Note that if we use
7436 // origLSHE we don't have to worry about whether the entry in question
7437 // is still mLSHE or whether it's now mOSHE.
7438 nsCOMPtr<nsIURI> uri = origLSHE->GetURI();
7439 SetCurrentURI(uri, document->GetChannel(), /* aFireLocationChange */ true,
7440 /* aIsInitialAboutBlank */ false,
7441 /* aLocationFlags */ 0);
7442 }
7443
7444 // This is the end of our CreateDocumentViewer() replacement.
7445 // Now we simulate a load. First, we restore the state of the javascript
7446 // window object.
7447 nsCOMPtr<nsPIDOMWindowOuter> privWin = GetWindow();
7448 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"
, 7448); MOZ_PretendNoReturn(); } } while (0)
;
7449
7450 // Now, dispatch a title change event which would happen as the
7451 // <head> is parsed.
7452 document->NotifyPossibleTitleChange(false);
7453
7454 // Now we simulate appending child docshells for subframes.
7455 for (i = 0; i < childShells.Count(); ++i) {
7456 nsIDocShellTreeItem* childItem = childShells.ObjectAt(i);
7457 nsCOMPtr<nsIDocShell> childShell = do_QueryInterface(childItem);
7458
7459 // Make sure to not clobber the state of the child. Since AddChild
7460 // always clobbers it, save it off first.
7461 bool allowRedirects;
7462 childShell->GetAllowMetaRedirects(&allowRedirects);
7463
7464 bool allowSubframes;
7465 childShell->GetAllowSubframes(&allowSubframes);
7466
7467 bool allowImages;
7468 childShell->GetAllowImages(&allowImages);
7469
7470 bool allowMedia = childShell->GetAllowMedia();
7471
7472 bool allowDNSPrefetch;
7473 childShell->GetAllowDNSPrefetch(&allowDNSPrefetch);
7474
7475 bool allowContentRetargeting = childShell->GetAllowContentRetargeting();
7476 bool allowContentRetargetingOnChildren =
7477 childShell->GetAllowContentRetargetingOnChildren();
7478
7479 // this.AddChild(child) calls child.SetDocLoaderParent(this), meaning that
7480 // the child inherits our state. Among other things, this means that the
7481 // child inherits our mPrivateBrowsingId, which is what we want.
7482 AddChild(childItem);
7483
7484 childShell->SetAllowMetaRedirects(allowRedirects);
7485 childShell->SetAllowSubframes(allowSubframes);
7486 childShell->SetAllowImages(allowImages);
7487 childShell->SetAllowMedia(allowMedia);
7488 childShell->SetAllowDNSPrefetch(allowDNSPrefetch);
7489 childShell->SetAllowContentRetargeting(allowContentRetargeting);
7490 childShell->SetAllowContentRetargetingOnChildren(
7491 allowContentRetargetingOnChildren);
7492
7493 rv = childShell->BeginRestore(nullptr, false);
7494 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"
, 7494); return rv; } } while (false)
;
7495 }
7496
7497 // Make sure to restore the window state after adding the child shells back
7498 // to the tree. This is necessary for Thaw() and Resume() to propagate
7499 // properly.
7500 rv = privWin->RestoreWindowState(windowState);
7501 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"
, 7501); return rv; } } while (false)
;
7502
7503 RefPtr<PresShell> presShell = GetPresShell();
7504
7505 // We may be displayed on a different monitor (or in a different
7506 // HiDPI mode) than when we got into the history list. So we need
7507 // to check if this has happened. See bug 838239.
7508
7509 // Because the prescontext normally handles resolution changes via
7510 // a runnable (see nsPresContext::UIResolutionChanged), its device
7511 // context won't be -immediately- updated as a result of calling
7512 // presShell->BackingScaleFactorChanged().
7513
7514 // But we depend on that device context when adjusting the view size
7515 // via mDocumentViewer->SetBounds(newBounds) below. So we need to
7516 // explicitly tell it to check for changed resolution here.
7517 if (presShell) {
7518 RefPtr<nsPresContext> pc = presShell->GetPresContext();
7519 if (pc->DeviceContext()->CheckDPIChange()) {
7520 presShell->BackingScaleFactorChanged();
7521 }
7522 // Recompute zoom and text-zoom and such.
7523 pc->RecomputeBrowsingContextDependentData();
7524 }
7525
7526 nsViewManager* newVM = presShell ? presShell->GetViewManager() : nullptr;
7527 nsView* newRootView = newVM ? newVM->GetRootView() : nullptr;
7528
7529 // Insert the new root view at the correct location in the view tree.
7530 if (container) {
7531 nsSubDocumentFrame* subDocFrame =
7532 do_QueryFrame(container->GetPrimaryFrame());
7533 rootViewParent = subDocFrame ? subDocFrame->EnsureInnerView() : nullptr;
7534 } else {
7535 rootViewParent = nullptr;
7536 }
7537 if (sibling && sibling->GetPresShell() &&
7538 sibling->GetPresShell()->GetViewManager()) {
7539 rootViewSibling = sibling->GetPresShell()->GetViewManager()->GetRootView();
7540 } else {
7541 rootViewSibling = nullptr;
7542 }
7543 if (rootViewParent && newRootView &&
7544 newRootView->GetParent() != rootViewParent) {
7545 nsViewManager* parentVM = rootViewParent->GetViewManager();
7546 if (parentVM) {
7547 // InsertChild(parent, child, sib, true) inserts the child after
7548 // sib in content order, which is before sib in view order. BUT
7549 // when sib is null it inserts at the end of the the document
7550 // order, i.e., first in view order. But when oldRootSibling is
7551 // null, the old root as at the end of the view list --- last in
7552 // content order --- and we want to call InsertChild(parent, child,
7553 // nullptr, false) in that case.
7554 parentVM->InsertChild(rootViewParent, newRootView, rootViewSibling,
7555 rootViewSibling ? true : false);
7556
7557 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"
, 7558); MOZ_PretendNoReturn(); } } while (0)
7558 "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"
, 7558); MOZ_PretendNoReturn(); } } while (0)
;
7559 }
7560 }
7561
7562 nsCOMPtr<nsPIDOMWindowInner> privWinInner = privWin->GetCurrentInnerWindow();
7563
7564 // If parent is suspended, increase suspension count.
7565 // This can't be done as early as event suppression since this
7566 // depends on docshell tree.
7567 privWinInner->SyncStateFromParentWindow();
7568
7569 // Now that all of the child docshells have been put into place, we can
7570 // restart the timers for the window and all of the child frames.
7571 privWinInner->Resume();
7572
7573 // Now that we have found the inner window of the page restored
7574 // from the history, we have to make sure that
7575 // performance.navigation.type is 2.
7576 Performance* performance = privWinInner->GetPerformance();
7577 if (performance) {
7578 performance->GetDOMTiming()->NotifyRestoreStart();
7579 }
7580
7581 // Restore the refresh URI list. The refresh timers will be restarted
7582 // when EndPageLoad() is called.
7583 mRefreshURIList = refreshURIList;
7584
7585 // Meta-refresh timers have been restarted for this shell, but not
7586 // for our children. Walk the child shells and restart their timers.
7587 for (auto* childDocLoader : mChildList.ForwardRange()) {
7588 nsCOMPtr<nsIDocShell> child = do_QueryObject(childDocLoader);
7589 if (child) {
7590 child->ResumeRefreshURIs();
7591 }
7592 }
7593
7594 // Make sure this presentation is the same size as the previous
7595 // presentation. If this is not the same size we showed it at last time,
7596 // then we need to resize the widget.
7597
7598 // XXXbryner This interacts poorly with Firefox's infobar. If the old
7599 // presentation had the infobar visible, then we will resize the new
7600 // presentation to that smaller size. However, firing the locationchanged
7601 // event will hide the infobar, which will immediately resize the window
7602 // back to the larger size. A future optimization might be to restore
7603 // the presentation at the "wrong" size, then fire the locationchanged
7604 // event and check whether the docshell's new size is the same as the
7605 // cached viewer size (skipping the resize if they are equal).
7606
7607 if (newRootView) {
7608 if (!newBounds.IsEmpty() && !newBounds.IsEqualEdges(oldBounds)) {
7609 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)
7610 ("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)
7611 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)
;
7612 mDocumentViewer->SetBounds(newBounds);
7613 } else if (ScrollContainerFrame* sf =
7614 presShell->GetRootScrollContainerFrame()) {
7615 sf->PostScrolledAreaEventForCurrentArea();
7616 }
7617 }
7618
7619 // The FinishRestore call below can kill these, null them out so we don't
7620 // have invalid pointer lying around.
7621 newRootView = rootViewSibling = rootViewParent = nullptr;
7622 newVM = nullptr;
7623
7624 // If the IsUnderHiddenEmbedderElement() state has been changed, we need to
7625 // update it.
7626 if (oldPresShell && presShell &&
7627 presShell->IsUnderHiddenEmbedderElement() !=
7628 oldPresShell->IsUnderHiddenEmbedderElement()) {
7629 presShell->SetIsUnderHiddenEmbedderElement(
7630 oldPresShell->IsUnderHiddenEmbedderElement());
7631 }
7632
7633 // Simulate the completion of the load.
7634 nsDocShell::FinishRestore();
7635
7636 // Restart plugins, and paint the content.
7637 if (presShell) {
7638 presShell->Thaw();
7639 }
7640
7641 return privWin->FireDelayedDOMEvents(true);
7642}
7643
7644nsresult nsDocShell::CreateDocumentViewer(const nsACString& aContentType,
7645 nsIRequest* aRequest,
7646 nsIStreamListener** aContentHandler) {
7647 *aContentHandler = nullptr;
7648
7649 if (!mTreeOwner || mIsBeingDestroyed) {
7650 // If we don't have a tree owner, then we're in the process of being
7651 // destroyed. Rather than continue trying to load something, just give up.
7652 return NS_ERROR_DOCSHELL_DYING;
7653 }
7654
7655 if (!mBrowsingContext->AncestorsAreCurrent() ||
7656 mBrowsingContext->IsInBFCache()) {
7657 mBrowsingContext->RemoveRootFromBFCacheSync();
7658 return NS_ERROR_NOT_AVAILABLE;
7659 }
7660
7661 // Can we check the content type of the current content viewer
7662 // and reuse it without destroying it and re-creating it?
7663
7664 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"
, 7664); MOZ_PretendNoReturn(); } } while (0)
;
7665
7666 // Instantiate the content viewer object
7667 nsCOMPtr<nsIDocumentViewer> viewer;
7668 nsresult rv = NewDocumentViewerObj(aContentType, aRequest, mLoadGroup,
7669 aContentHandler, getter_AddRefs(viewer));
7670
7671 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
7672 return rv;
7673 }
7674
7675 // Notify the current document that it is about to be unloaded!!
7676 //
7677 // It is important to fire the unload() notification *before* any state
7678 // is changed within the DocShell - otherwise, javascript will get the
7679 // wrong information :-(
7680 //
7681
7682 if (mSavingOldViewer) {
7683 // We determined that it was safe to cache the document presentation
7684 // at the time we initiated the new load. We need to check whether
7685 // it's still safe to do so, since there may have been DOM mutations
7686 // or new requests initiated.
7687 RefPtr<Document> doc = viewer->GetDocument();
7688 mSavingOldViewer = CanSavePresentation(
7689 mLoadType, aRequest, doc, /* aReportBFCacheComboTelemetry */ false);
7690 }
7691
7692 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"
, 7692); MOZ_PretendNoReturn(); } } while (0)
;
7693
7694 nsCOMPtr<nsIChannel> aOpenedChannel = do_QueryInterface(aRequest);
7695 if (aOpenedChannel) {
7696 aOpenedChannel->GetURI(getter_AddRefs(mLoadingURI));
7697 }
7698
7699 // Grab the current URI, we need to pass it to Embed, and OnNewURI will reset
7700 // it before we do call Embed.
7701 nsCOMPtr<nsIURI> previousURI = mCurrentURI;
7702
7703 FirePageHideNotification(!mSavingOldViewer);
7704 if (mIsBeingDestroyed) {
7705 // Force to stop the newly created orphaned viewer.
7706 viewer->Stop();
7707 return NS_ERROR_DOCSHELL_DYING;
7708 }
7709 mLoadingURI = nullptr;
7710
7711 // Set mFiredUnloadEvent = false so that the unload handler for the
7712 // *new* document will fire.
7713 mFiredUnloadEvent = false;
7714
7715 // we've created a new document so go ahead and call
7716 // OnNewURI(), but don't fire OnLocationChange()
7717 // notifications before we've called Embed(). See bug 284993.
7718 mURIResultedInDocument = true;
7719 bool errorOnLocationChangeNeeded = false;
7720 nsCOMPtr<nsIChannel> failedChannel = mFailedChannel;
7721 nsCOMPtr<nsIURI> failedURI;
7722
7723 if (mLoadType == LOAD_ERROR_PAGE) {
7724 // We need to set the SH entry and our current URI here and not
7725 // at the moment we load the page. We want the same behavior
7726 // of Stop() as for a normal page load. See bug 514232 for details.
7727
7728 // Revert mLoadType to load type to state the page load failed,
7729 // following function calls need it.
7730 mLoadType = mFailedLoadType;
7731
7732 Document* doc = viewer->GetDocument();
7733 if (doc) {
7734 doc->SetFailedChannel(failedChannel);
7735 }
7736
7737 nsCOMPtr<nsIPrincipal> triggeringPrincipal;
7738 if (failedChannel) {
7739 // Make sure we have a URI to set currentURI.
7740 NS_GetFinalChannelURI(failedChannel, getter_AddRefs(failedURI));
7741 } else {
7742 // if there is no failed channel we have to explicitly provide
7743 // a triggeringPrincipal for the history entry.
7744 triggeringPrincipal = nsContentUtils::GetSystemPrincipal();
7745 }
7746
7747 if (!failedURI) {
7748 failedURI = mFailedURI;
7749 }
7750 if (!failedURI) {
7751 // We need a URI object to store a session history entry, so make up a URI
7752 NS_NewURI(getter_AddRefs(failedURI), "about:blank");
7753 }
7754
7755 // When we don't have failedURI, something wrong will happen. See
7756 // bug 291876.
7757 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"
, 7757); AnnotateMozCrashReason("MOZ_ASSERT" "(" "failedURI" ") ("
"We don't have a URI for history APIs." ")"); do { *((volatile
int*)__null) = 7757; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
7758
7759 mFailedChannel = nullptr;
7760 mFailedURI = nullptr;
7761
7762 // Create an shistory entry for the old load.
7763 if (failedURI) {
7764 errorOnLocationChangeNeeded =
7765 OnNewURI(failedURI, failedChannel, triggeringPrincipal, nullptr,
7766 nullptr, nullptr, false, false);
7767 }
7768
7769 // Be sure to have a correct mLSHE, it may have been cleared by
7770 // EndPageLoad. See bug 302115.
7771 ChildSHistory* shistory = GetSessionHistory();
7772 if (!mozilla::SessionHistoryInParent() && shistory && !mLSHE) {
7773 int32_t idx = shistory->LegacySHistory()->GetRequestedIndex();
7774 if (idx == -1) {
7775 idx = shistory->Index();
7776 }
7777 shistory->LegacySHistory()->GetEntryAtIndex(idx, getter_AddRefs(mLSHE));
7778 }
7779
7780 mLoadType = LOAD_ERROR_PAGE;
7781 }
7782
7783 nsCOMPtr<nsIURI> finalURI;
7784 // If this a redirect, use the final url (uri)
7785 // else use the original url
7786 //
7787 // Note that this should match what documents do (see Document::Reset).
7788 NS_GetFinalChannelURI(aOpenedChannel, getter_AddRefs(finalURI));
7789
7790 bool onLocationChangeNeeded = false;
7791 if (finalURI) {
7792 // Pass false for aCloneSHChildren, since we're loading a new page here.
7793 onLocationChangeNeeded = OnNewURI(finalURI, aOpenedChannel, nullptr,
7794 nullptr, nullptr, nullptr, true, false);
7795 }
7796
7797 // let's try resetting the load group if we need to...
7798 nsCOMPtr<nsILoadGroup> currentLoadGroup;
7799 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"
, 7801); return NS_ERROR_FAILURE; } } while (false)
7800 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"
, 7801); return NS_ERROR_FAILURE; } } while (false)
7801 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"
, 7801); return NS_ERROR_FAILURE; } } while (false)
;
7802
7803 if (currentLoadGroup != mLoadGroup) {
7804 nsLoadFlags loadFlags = 0;
7805
7806 // Cancel any URIs that are currently loading...
7807 // XXX: Need to do this eventually Stop();
7808 //
7809 // Retarget the document to this loadgroup...
7810 //
7811 /* First attach the channel to the right loadgroup
7812 * and then remove from the old loadgroup. This
7813 * puts the notifications in the right order and
7814 * we don't null-out mLSHE in OnStateChange() for
7815 * all redirected urls
7816 */
7817 aOpenedChannel->SetLoadGroup(mLoadGroup);
7818
7819 // Mark the channel as being a document URI...
7820 aOpenedChannel->GetLoadFlags(&loadFlags);
7821 loadFlags |= nsIChannel::LOAD_DOCUMENT_URI;
7822 nsCOMPtr<nsILoadInfo> loadInfo = aOpenedChannel->LoadInfo();
7823 if (SandboxFlagsImplyCookies(loadInfo->GetSandboxFlags())) {
7824 loadFlags |= nsIRequest::LOAD_DOCUMENT_NEEDS_COOKIE;
7825 }
7826
7827 aOpenedChannel->SetLoadFlags(loadFlags);
7828
7829 mLoadGroup->AddRequest(aRequest, nullptr);
7830 if (currentLoadGroup) {
7831 currentLoadGroup->RemoveRequest(aRequest, nullptr, NS_BINDING_RETARGETED);
7832 }
7833
7834 // Update the notification callbacks, so that progress and
7835 // status information are sent to the right docshell...
7836 aOpenedChannel->SetNotificationCallbacks(this);
7837 }
7838
7839 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"
, 7842); return NS_ERROR_FAILURE; } } while (false)
7840 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"
, 7842); return NS_ERROR_FAILURE; } } while (false)
7841 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"
, 7842); return NS_ERROR_FAILURE; } } while (false)
7842 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"
, 7842); return NS_ERROR_FAILURE; } } while (false)
;
7843
7844 if (!mBrowsingContext->GetHasLoadedNonInitialDocument()) {
7845 MOZ_ALWAYS_SUCCEEDS(mBrowsingContext->SetHasLoadedNonInitialDocument(true))do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(mBrowsingContext->SetHasLoadedNonInitialDocument(true))),
1)))), 1))) { } else { do { static_assert( mozilla::detail::
AssertionConditionType<decltype(false)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("false" " (" "NS_SUCCEEDED(mBrowsingContext->SetHasLoadedNonInitialDocument(true))"
")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 7845); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "false"
") (" "NS_SUCCEEDED(mBrowsingContext->SetHasLoadedNonInitialDocument(true))"
")"); do { *((volatile int*)__null) = 7845; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
7846 }
7847
7848 mSavedRefreshURIList = nullptr;
7849 mSavingOldViewer = false;
7850 mEODForCurrentDocument = false;
7851
7852 // if this document is part of a multipart document,
7853 // the ID can be used to distinguish it from the other parts.
7854 nsCOMPtr<nsIMultiPartChannel> multiPartChannel(do_QueryInterface(aRequest));
7855 if (multiPartChannel) {
7856 if (PresShell* presShell = GetPresShell()) {
7857 if (Document* doc = presShell->GetDocument()) {
7858 uint32_t partID;
7859 multiPartChannel->GetPartID(&partID);
7860 doc->SetPartID(partID);
7861 }
7862 }
7863 }
7864
7865 if (errorOnLocationChangeNeeded) {
7866 FireOnLocationChange(this, failedChannel, failedURI,
7867 LOCATION_CHANGE_ERROR_PAGE);
7868 } else if (onLocationChangeNeeded) {
7869 uint32_t locationFlags =
7870 (mLoadType & LOAD_CMD_RELOAD) ? uint32_t(LOCATION_CHANGE_RELOAD) : 0;
7871 FireOnLocationChange(this, aRequest, mCurrentURI, locationFlags);
7872 }
7873
7874 return NS_OK;
7875}
7876
7877nsresult nsDocShell::NewDocumentViewerObj(const nsACString& aContentType,
7878 nsIRequest* aRequest,
7879 nsILoadGroup* aLoadGroup,
7880 nsIStreamListener** aContentHandler,
7881 nsIDocumentViewer** aViewer) {
7882 nsCOMPtr<nsIChannel> aOpenedChannel = do_QueryInterface(aRequest);
7883
7884 nsCOMPtr<nsIDocumentLoaderFactory> docLoaderFactory =
7885 nsContentUtils::FindInternalDocumentViewer(aContentType);
7886 if (!docLoaderFactory) {
7887 return NS_ERROR_FAILURE;
7888 }
7889
7890 // Now create an instance of the content viewer nsLayoutDLF makes the
7891 // determination if it should be a "view-source" instead of "view"
7892 nsresult rv = docLoaderFactory->CreateInstance(
7893 "view", aOpenedChannel, aLoadGroup, aContentType, this, nullptr,
7894 aContentHandler, aViewer);
7895 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"
, 7895); return rv; } } while (false)
;
7896
7897 (*aViewer)->SetContainer(this);
7898 return NS_OK;
7899}
7900
7901nsresult nsDocShell::SetupNewViewer(nsIDocumentViewer* aNewViewer,
7902 WindowGlobalChild* aWindowActor) {
7903 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"
, 7903); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mIsBeingDestroyed"
")"); do { *((volatile int*)__null) = 7903; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7904
7905 //
7906 // Copy content viewer state from previous or parent content viewer.
7907 //
7908 // The following logic is mirrored in nsHTMLDocument::StartDocumentLoad!
7909 //
7910 // Do NOT to maintain a reference to the old content viewer outside
7911 // of this "copying" block, or it will not be destroyed until the end of
7912 // this routine and all <SCRIPT>s and event handlers fail! (bug 20315)
7913 //
7914 // In this block of code, if we get an error result, we return it
7915 // but if we get a null pointer, that's perfectly legal for parent
7916 // and parentContentViewer.
7917 //
7918
7919 int32_t x = 0;
7920 int32_t y = 0;
7921 int32_t cx = 0;
7922 int32_t cy = 0;
7923
7924 // This will get the size from the current content viewer or from the
7925 // Init settings
7926 DoGetPositionAndSize(&x, &y, &cx, &cy);
7927
7928 nsCOMPtr<nsIDocShellTreeItem> parentAsItem;
7929 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"
, 7930); return NS_ERROR_FAILURE; } } while (false)
7930 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"
, 7930); return NS_ERROR_FAILURE; } } while (false)
;
7931 nsCOMPtr<nsIDocShell> parent(do_QueryInterface(parentAsItem));
7932
7933 const Encoding* reloadEncoding = nullptr;
7934 int32_t reloadEncodingSource = kCharsetUninitialized;
7935 // |newMUDV| also serves as a flag to set the data from the above vars
7936 nsCOMPtr<nsIDocumentViewer> newViewer;
7937
7938 if (mDocumentViewer || parent) {
7939 nsCOMPtr<nsIDocumentViewer> oldViewer;
7940 if (mDocumentViewer) {
7941 // Get any interesting state from old content viewer
7942 // XXX: it would be far better to just reuse the document viewer ,
7943 // since we know we're just displaying the same document as before
7944 oldViewer = mDocumentViewer;
7945
7946 // Tell the old content viewer to hibernate in session history when
7947 // it is destroyed.
7948
7949 if (mSavingOldViewer && NS_FAILED(CaptureState())((bool)(__builtin_expect(!!(NS_FAILED_impl(CaptureState())), 0
)))
) {
7950 if (mOSHE) {
7951 mOSHE->SyncPresentationState();
7952 }
7953 mSavingOldViewer = false;
7954 }
7955 } else {
7956 // No old content viewer, so get state from parent's content viewer
7957 parent->GetDocViewer(getter_AddRefs(oldViewer));
7958 }
7959
7960 if (oldViewer) {
7961 newViewer = aNewViewer;
7962 if (newViewer) {
7963 reloadEncoding =
7964 oldViewer->GetReloadEncodingAndSource(&reloadEncodingSource);
7965 }
7966 }
7967 }
7968
7969 nscolor bgcolor = NS_RGBA(0, 0, 0, 0)((nscolor)(((0) << 24) | ((0) << 16) | ((0) <<
8) | (0)))
;
7970 bool isUnderHiddenEmbedderElement = false;
7971 // Ensure that the content viewer is destroyed *after* the GC - bug 71515
7972 nsCOMPtr<nsIDocumentViewer> viewer = mDocumentViewer;
7973 if (viewer) {
7974 // Stop any activity that may be happening in the old document before
7975 // releasing it...
7976 viewer->Stop();
7977
7978 // Try to extract the canvas background color from the old
7979 // presentation shell, so we can use it for the next document.
7980 if (PresShell* presShell = viewer->GetPresShell()) {
7981 bgcolor = presShell->GetCanvasBackground();
7982 isUnderHiddenEmbedderElement = presShell->IsUnderHiddenEmbedderElement();
7983 }
7984
7985 viewer->Close(mSavingOldViewer ? mOSHE.get() : nullptr);
7986 aNewViewer->SetPreviousViewer(viewer);
7987 }
7988 if (mOSHE && (!mDocumentViewer || !mSavingOldViewer)) {
7989 // We don't plan to save a viewer in mOSHE; tell it to drop
7990 // any other state it's holding.
7991 mOSHE->SyncPresentationState();
7992 }
7993
7994 mDocumentViewer = nullptr;
7995
7996 // Now that we're about to switch documents, forget all of our children.
7997 // Note that we cached them as needed up in CaptureState above.
7998 DestroyChildren();
7999
8000 mDocumentViewer = aNewViewer;
8001
8002 nsCOMPtr<nsIWidget> widget;
8003 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"
, 8003); return NS_ERROR_FAILURE; } } while (false)
;
8004
8005 nsIntRect bounds(x, y, cx, cy);
8006
8007 mDocumentViewer->SetNavigationTiming(mTiming);
8008
8009 if (NS_FAILED(mDocumentViewer->Init(widget, bounds, aWindowActor))((bool)(__builtin_expect(!!(NS_FAILED_impl(mDocumentViewer->
Init(widget, bounds, aWindowActor))), 0)))
) {
8010 nsCOMPtr<nsIDocumentViewer> viewer = mDocumentViewer;
8011 viewer->Close(nullptr);
8012 viewer->Destroy();
8013 mDocumentViewer = nullptr;
8014 SetCurrentURIInternal(nullptr);
8015 NS_WARNING("ContentViewer Initialization failed")NS_DebugBreak(NS_DEBUG_WARNING, "ContentViewer Initialization failed"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 8015)
;
8016 return NS_ERROR_FAILURE;
8017 }
8018
8019 // If we have old state to copy, set the old state onto the new content
8020 // viewer
8021 if (newViewer) {
8022 newViewer->SetReloadEncodingAndSource(reloadEncoding, reloadEncodingSource);
8023 }
8024
8025 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"
, 8025); return NS_ERROR_FAILURE; } } while (false)
;
8026
8027 // Stuff the bgcolor from the old pres shell into the new
8028 // pres shell. This improves page load continuity.
8029 if (RefPtr<PresShell> presShell = mDocumentViewer->GetPresShell()) {
8030 presShell->SetCanvasBackground(bgcolor);
8031 presShell->ActivenessMaybeChanged();
8032 if (isUnderHiddenEmbedderElement) {
8033 presShell->SetIsUnderHiddenEmbedderElement(isUnderHiddenEmbedderElement);
8034 }
8035 }
8036
8037 // XXX: It looks like the LayoutState gets restored again in Embed()
8038 // right after the call to SetupNewViewer(...)
8039
8040 // We don't show the mDocumentViewer yet, since we want to draw the old page
8041 // until we have enough of the new page to show. Just return with the new
8042 // viewer still set to hidden.
8043
8044 return NS_OK;
8045}
8046
8047void nsDocShell::SetDocCurrentStateObj(nsISHEntry* aShEntry,
8048 SessionHistoryInfo* aInfo) {
8049 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"
, 8049); return; } } while (false)
;
8050
8051 RefPtr<Document> document = GetDocument();
8052 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"
, 8052); return; } } while (false)
;
8053
8054 nsCOMPtr<nsIStructuredCloneContainer> scContainer;
8055 if (mozilla::SessionHistoryInParent()) {
8056 // If aInfo is null, just set the document's state object to null.
8057 if (aInfo) {
8058 scContainer = aInfo->GetStateData();
8059 }
8060 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)
8061 ("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)
;
8062 } else {
8063 if (aShEntry) {
8064 scContainer = aShEntry->GetStateData();
8065
8066 // If aShEntry is null, just set the document's state object to null.
8067 }
8068 }
8069
8070 // It's OK for scContainer too be null here; that just means there's no
8071 // state data associated with this history entry.
8072 document->SetStateObject(scContainer);
8073}
8074
8075nsresult nsDocShell::CheckLoadingPermissions() {
8076 // This method checks whether the caller may load content into
8077 // this docshell. Even though we've done our best to hide windows
8078 // from code that doesn't have the right to access them, it's
8079 // still possible for an evil site to open a window and access
8080 // frames in the new window through window.frames[] (which is
8081 // allAccess for historic reasons), so we still need to do this
8082 // check on load.
8083 nsresult rv = NS_OK;
8084
8085 if (!IsSubframe()) {
8086 // We're not a frame. Permit all loads.
8087 return rv;
8088 }
8089
8090 // Note - The check for a current JSContext here isn't necessarily sensical.
8091 // It's just designed to preserve the old semantics during a mass-conversion
8092 // patch.
8093 if (!nsContentUtils::GetCurrentJSContext()) {
8094 return NS_OK;
8095 }
8096
8097 // Check if the caller is from the same origin as this docshell,
8098 // or any of its ancestors.
8099 for (RefPtr<BrowsingContext> bc = mBrowsingContext; bc;
8100 bc = bc->GetParent()) {
8101 // If the BrowsingContext is not in process, then it
8102 // is true by construction that its principal will not
8103 // subsume the current docshell principal.
8104 if (!bc->IsInProcess()) {
8105 continue;
8106 }
8107
8108 nsCOMPtr<nsIScriptGlobalObject> sgo =
8109 bc->GetDocShell()->GetScriptGlobalObject();
8110 nsCOMPtr<nsIScriptObjectPrincipal> sop(do_QueryInterface(sgo));
8111
8112 nsIPrincipal* p;
8113 if (!sop || !(p = sop->GetPrincipal())) {
8114 return NS_ERROR_UNEXPECTED;
8115 }
8116
8117 if (nsContentUtils::SubjectPrincipal()->Subsumes(p)) {
8118 // Same origin, permit load
8119 return NS_OK;
8120 }
8121 }
8122
8123 return NS_ERROR_DOM_PROP_ACCESS_DENIED;
8124}
8125
8126//*****************************************************************************
8127// nsDocShell: Site Loading
8128//*****************************************************************************
8129
8130void nsDocShell::CopyFavicon(nsIURI* aOldURI, nsIURI* aNewURI,
8131 bool aInPrivateBrowsing) {
8132 if (XRE_IsContentProcess()) {
8133 dom::ContentChild* contentChild = dom::ContentChild::GetSingleton();
8134 if (contentChild) {
8135 contentChild->SendCopyFavicon(aOldURI, aNewURI, aInPrivateBrowsing);
8136 }
8137 return;
8138 }
8139
8140#ifdef MOZ_PLACES1
8141 nsCOMPtr<nsIFaviconService> favSvc =
8142 do_GetService("@mozilla.org/browser/favicon-service;1");
8143 if (favSvc) {
8144 favSvc->CopyFavicons(aOldURI, aNewURI,
8145 aInPrivateBrowsing
8146 ? nsIFaviconService::FAVICON_LOAD_PRIVATE
8147 : nsIFaviconService::FAVICON_LOAD_NON_PRIVATE,
8148 nullptr);
8149 }
8150#endif
8151}
8152
8153class InternalLoadEvent : public Runnable {
8154 public:
8155 InternalLoadEvent(nsDocShell* aDocShell, nsDocShellLoadState* aLoadState)
8156 : mozilla::Runnable("InternalLoadEvent"),
8157 mDocShell(aDocShell),
8158 mLoadState(aLoadState) {
8159 // For events, both target and filename should be the version of "null" they
8160 // expect. By the time the event is fired, both window targeting and file
8161 // downloading have been handled, so we should never have an internal load
8162 // event that retargets or had a download.
8163 mLoadState->SetTarget(u""_ns);
8164 mLoadState->SetFileName(VoidString());
8165 }
8166
8167 NS_IMETHODvirtual nsresult
8168 Run() override {
8169#ifndef ANDROID
8170 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"
, 8171); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mLoadState->TriggeringPrincipal()"
") (" "InternalLoadEvent: Should always have a principal here"
")"); do { *((volatile int*)__null) = 8171; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
8171 "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"
, 8171); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mLoadState->TriggeringPrincipal()"
") (" "InternalLoadEvent: Should always have a principal here"
")"); do { *((volatile int*)__null) = 8171; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8172#endif
8173 return mDocShell->InternalLoad(mLoadState);
8174 }
8175
8176 private:
8177 RefPtr<nsDocShell> mDocShell;
8178 RefPtr<nsDocShellLoadState> mLoadState;
8179};
8180
8181/**
8182 * Returns true if we started an asynchronous load (i.e., from the network), but
8183 * the document we're loading there hasn't yet become this docshell's active
8184 * document.
8185 *
8186 * When JustStartedNetworkLoad is true, you should be careful about modifying
8187 * mLoadType and mLSHE. These are both set when the asynchronous load first
8188 * starts, and the load expects that, when it eventually runs InternalLoad,
8189 * mLoadType and mLSHE will have their original values.
8190 */
8191bool nsDocShell::JustStartedNetworkLoad() {
8192 return mDocumentRequest && mDocumentRequest != GetCurrentDocChannel();
8193}
8194
8195// The contentType will be INTERNAL_(I)FRAME if this docshell is for a
8196// non-toplevel browsing context in spec terms. (frame, iframe, <object>,
8197// <embed>, etc)
8198//
8199// This return value will be used when we call NS_CheckContentLoadPolicy, and
8200// later when we call DoURILoad.
8201nsContentPolicyType nsDocShell::DetermineContentType() {
8202 if (!IsSubframe()) {
8203 return nsIContentPolicy::TYPE_DOCUMENT;
8204 }
8205
8206 const auto& maybeEmbedderElementType =
8207 GetBrowsingContext()->GetEmbedderElementType();
8208 if (!maybeEmbedderElementType) {
8209 // If the EmbedderElementType hasn't been set yet, just assume we're
8210 // an iframe since that's more common.
8211 return nsIContentPolicy::TYPE_INTERNAL_IFRAME;
8212 }
8213
8214 return maybeEmbedderElementType->EqualsLiteral("iframe")
8215 ? nsIContentPolicy::TYPE_INTERNAL_IFRAME
8216 : nsIContentPolicy::TYPE_INTERNAL_FRAME;
8217}
8218
8219bool nsDocShell::NoopenerForceEnabled() {
8220 // If current's top-level browsing context's active document's
8221 // cross-origin-opener-policy is "same-origin" or "same-origin + COEP" then
8222 // if currentDoc's origin is not same origin with currentDoc's top-level
8223 // origin, noopener is force enabled, and name is cleared to "_blank".
8224 auto topPolicy = mBrowsingContext->Top()->GetOpenerPolicy();
8225 return (topPolicy == nsILoadInfo::OPENER_POLICY_SAME_ORIGIN ||
8226 topPolicy ==
8227 nsILoadInfo::
8228 OPENER_POLICY_SAME_ORIGIN_EMBEDDER_POLICY_REQUIRE_CORP) &&
8229 !mBrowsingContext->SameOriginWithTop();
8230}
8231
8232nsresult nsDocShell::PerformRetargeting(nsDocShellLoadState* aLoadState) {
8233 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"
, 8233); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState"
") (" "need a load state!" ")"); do { *((volatile int*)__null
) = 8233; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
;
8234 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"
, 8234); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aLoadState->Target().IsEmpty()"
") (" "should have a target here!" ")"); do { *((volatile int
*)__null) = 8234; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
8235 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"
, 8236); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->TargetBrowsingContext().IsNull()"
") (" "should not have picked target yet" ")"); do { *((volatile
int*)__null) = 8236; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
8236 "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"
, 8236); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->TargetBrowsingContext().IsNull()"
") (" "should not have picked target yet" ")"); do { *((volatile
int*)__null) = 8236; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
8237
8238 nsresult rv = NS_OK;
8239 RefPtr<BrowsingContext> targetContext;
8240
8241 // Only _self, _parent, and _top are supported in noopener case. But we
8242 // have to be careful to not apply that to the noreferrer case. See bug
8243 // 1358469.
8244 bool allowNamedTarget =
8245 !aLoadState->HasInternalLoadFlags(INTERNAL_LOAD_FLAGS_NO_OPENER) ||
8246 aLoadState->HasInternalLoadFlags(INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER);
8247 if (allowNamedTarget ||
8248 aLoadState->Target().LowerCaseEqualsLiteral("_self") ||
8249 aLoadState->Target().LowerCaseEqualsLiteral("_parent") ||
8250 aLoadState->Target().LowerCaseEqualsLiteral("_top")) {
8251 Document* document = GetDocument();
8252 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"
, 8252); return NS_ERROR_FAILURE; } } while (false)
;
8253 WindowGlobalChild* wgc = document->GetWindowGlobalChild();
8254 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"
, 8254); return NS_ERROR_FAILURE; } } while (false)
;
8255 targetContext = wgc->FindBrowsingContextWithName(
8256 aLoadState->Target(), /* aUseEntryGlobalForAccessCheck */ false);
8257 }
8258
8259 if (!targetContext) {
8260 // If the targetContext doesn't exist, then this is a new docShell and we
8261 // should consider this a TYPE_DOCUMENT load
8262 //
8263 // For example, when target="_blank"
8264
8265 // If there's no targetContext, that means we are about to create a new
8266 // window. Perform a content policy check before creating the window. Please
8267 // note for all other docshell loads content policy checks are performed
8268 // within the contentSecurityManager when the channel is about to be
8269 // openend.
8270 nsISupports* requestingContext = nullptr;
8271 if (XRE_IsContentProcess()) {
8272 // In e10s the child process doesn't have access to the element that
8273 // contains the browsing context (because that element is in the chrome
8274 // process). So we just pass mScriptGlobal.
8275 requestingContext = ToSupports(mScriptGlobal);
8276 } else {
8277 // This is for loading non-e10s tabs and toplevel windows of various
8278 // sorts.
8279 // For the toplevel window cases, requestingElement will be null.
8280 nsCOMPtr<Element> requestingElement =
8281 mScriptGlobal->GetFrameElementInternal();
8282 requestingContext = requestingElement;
8283 }
8284
8285 // Ideally we should use the same loadinfo as within DoURILoad which
8286 // should match this one when both are applicable.
8287 nsCOMPtr<nsILoadInfo> secCheckLoadInfo =
8288 new LoadInfo(mScriptGlobal, aLoadState->URI(),
8289 aLoadState->TriggeringPrincipal(), requestingContext,
8290 nsILoadInfo::SEC_ONLY_FOR_EXPLICIT_CONTENTSEC_CHECK, 0);
8291
8292 // Since Content Policy checks are performed within docShell as well as
8293 // the ContentSecurityManager we need a reliable way to let certain
8294 // nsIContentPolicy consumers ignore duplicate calls.
8295 secCheckLoadInfo->SetSkipContentPolicyCheckForWebRequest(true);
8296
8297 int16_t shouldLoad = nsIContentPolicy::ACCEPT;
8298 rv = NS_CheckContentLoadPolicy(aLoadState->URI(), secCheckLoadInfo,
8299 &shouldLoad);
8300
8301 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) || NS_CP_REJECTED(shouldLoad)((shouldLoad) != nsIContentPolicy::ACCEPT)) {
8302 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
8303 if (shouldLoad == nsIContentPolicy::REJECT_TYPE) {
8304 return NS_ERROR_CONTENT_BLOCKED_SHOW_ALT;
8305 }
8306 if (shouldLoad == nsIContentPolicy::REJECT_POLICY) {
8307 return NS_ERROR_BLOCKED_BY_POLICY;
8308 }
8309 }
8310
8311 return NS_ERROR_CONTENT_BLOCKED;
8312 }
8313 }
8314
8315 //
8316 // Resolve the window target before going any further...
8317 // If the load has been targeted to another DocShell, then transfer the
8318 // load to it...
8319 //
8320
8321 // We've already done our owner-inheriting. Mask out that bit, so we
8322 // don't try inheriting an owner from the target window if we came up
8323 // with a null owner above.
8324 aLoadState->UnsetInternalLoadFlag(INTERNAL_LOAD_FLAGS_INHERIT_PRINCIPAL);
8325
8326 if (!targetContext) {
8327 // If the docshell's document is sandboxed, only open a new window
8328 // if the document's SANDBOXED_AUXILLARY_NAVIGATION flag is not set.
8329 // (i.e. if allow-popups is specified)
8330 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"
, 8330); return NS_ERROR_FAILURE; } } while (false)
;
8331 Document* doc = mDocumentViewer->GetDocument();
8332
8333 const bool isDocumentAuxSandboxed =
8334 doc && (doc->GetSandboxFlags() & SANDBOXED_AUXILIARY_NAVIGATION);
8335
8336 if (isDocumentAuxSandboxed) {
8337 return NS_ERROR_DOM_INVALID_ACCESS_ERR;
8338 }
8339
8340 nsCOMPtr<nsPIDOMWindowOuter> win = GetWindow();
8341 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"
, 8341); return NS_ERROR_NOT_AVAILABLE; } } while (false)
;
8342
8343 RefPtr<BrowsingContext> newBC;
8344 nsAutoCString spec;
8345 aLoadState->URI()->GetSpec(spec);
8346
8347 // If we are a noopener load, we just hand the whole thing over to our
8348 // window.
8349 if (aLoadState->HasInternalLoadFlags(INTERNAL_LOAD_FLAGS_NO_OPENER) ||
8350 NoopenerForceEnabled()) {
8351 // Various asserts that we know to hold because NO_OPENER loads can only
8352 // happen for links.
8353 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"
, 8353); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aLoadState->LoadReplace()"
")"); do { *((volatile int*)__null) = 8353; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8354 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"
, 8355); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->PrincipalToInherit() == aLoadState->TriggeringPrincipal()"
")"); do { *((volatile int*)__null) = 8355; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
8355 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"
, 8355); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->PrincipalToInherit() == aLoadState->TriggeringPrincipal()"
")"); do { *((volatile int*)__null) = 8355; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8356 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"
, 8360); 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) = 8360; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
8357 ~(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"
, 8360); 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) = 8360; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
8358 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"
, 8360); 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) = 8360; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
8359 "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"
, 8360); 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) = 8360; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
8360 "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"
, 8360); 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) = 8360; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8361 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"
, 8362); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->IsFormSubmission()"
")"); do { *((volatile int*)__null) = 8362; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
8362 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"
, 8362); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->IsFormSubmission()"
")"); do { *((volatile int*)__null) = 8362; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
8363 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"
, 8363); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aLoadState->HeadersStream()"
")"); do { *((volatile int*)__null) = 8363; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8364 // If OnLinkClickSync was invoked inside the onload handler, the load
8365 // type would be set to LOAD_NORMAL_REPLACE; otherwise it should be
8366 // LOAD_LINK.
8367 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"
, 8368); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->LoadType() == LOAD_LINK || aLoadState->LoadType() == LOAD_NORMAL_REPLACE"
")"); do { *((volatile int*)__null) = 8368; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
8368 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"
, 8368); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->LoadType() == LOAD_LINK || aLoadState->LoadType() == LOAD_NORMAL_REPLACE"
")"); do { *((volatile int*)__null) = 8368; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8369 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"
, 8369); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aLoadState->LoadIsFromSessionHistory()"
")"); do { *((volatile int*)__null) = 8369; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8370 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"
, 8370); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->FirstParty()"
")"); do { *((volatile int*)__null) = 8370; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
; // Windowwatcher will assume this.
8371
8372 RefPtr<nsDocShellLoadState> loadState =
8373 new nsDocShellLoadState(aLoadState->URI());
8374
8375 // Set up our loadinfo so it will do the load as much like we would have
8376 // as possible.
8377 loadState->SetReferrerInfo(aLoadState->GetReferrerInfo());
8378 loadState->SetOriginalURI(aLoadState->OriginalURI());
8379
8380 Maybe<nsCOMPtr<nsIURI>> resultPrincipalURI;
8381 aLoadState->GetMaybeResultPrincipalURI(resultPrincipalURI);
8382
8383 loadState->SetMaybeResultPrincipalURI(resultPrincipalURI);
8384 loadState->SetKeepResultPrincipalURIIfSet(
8385 aLoadState->KeepResultPrincipalURIIfSet());
8386 // LoadReplace will always be false due to asserts above, skip setting
8387 // it.
8388 loadState->SetTriggeringPrincipal(aLoadState->TriggeringPrincipal());
8389 loadState->SetTriggeringSandboxFlags(
8390 aLoadState->TriggeringSandboxFlags());
8391 loadState->SetTriggeringWindowId(aLoadState->TriggeringWindowId());
8392 loadState->SetTriggeringStorageAccess(
8393 aLoadState->TriggeringStorageAccess());
8394 loadState->SetCsp(aLoadState->Csp());
8395 loadState->SetInheritPrincipal(aLoadState->HasInternalLoadFlags(
8396 INTERNAL_LOAD_FLAGS_INHERIT_PRINCIPAL));
8397 // Explicit principal because we do not want any guesses as to what the
8398 // principal to inherit is: it should be aTriggeringPrincipal.
8399 loadState->SetPrincipalIsExplicit(true);
8400 loadState->SetLoadType(aLoadState->LoadType());
8401 loadState->SetForceAllowDataURI(aLoadState->HasInternalLoadFlags(
8402 INTERNAL_LOAD_FLAGS_FORCE_ALLOW_DATA_URI));
8403
8404 loadState->SetHasValidUserGestureActivation(
8405 aLoadState->HasValidUserGestureActivation());
8406
8407 loadState->SetTextDirectiveUserActivation(
8408 aLoadState->GetTextDirectiveUserActivation());
8409
8410 // Propagate POST data to the new load.
8411 loadState->SetPostDataStream(aLoadState->PostDataStream());
8412 loadState->SetIsFormSubmission(aLoadState->IsFormSubmission());
8413
8414 rv = win->Open(NS_ConvertUTF8toUTF16(spec),
8415 aLoadState->Target(), // window name
8416 u""_ns, // Features
8417 loadState,
8418 true, // aForceNoOpener
8419 getter_AddRefs(newBC));
8420 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"
, 8420); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!newBC" ")"
); do { *((volatile int*)__null) = 8420; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8421 return rv;
8422 }
8423
8424 rv = win->OpenNoNavigate(NS_ConvertUTF8toUTF16(spec),
8425 aLoadState->Target(), // window name
8426 u""_ns, // Features
8427 getter_AddRefs(newBC));
8428
8429 // In some cases the Open call doesn't actually result in a new
8430 // window being opened. We can detect these cases by examining the
8431 // document in |newBC|, if any.
8432 nsCOMPtr<nsPIDOMWindowOuter> piNewWin =
8433 newBC ? newBC->GetDOMWindow() : nullptr;
8434 if (piNewWin) {
8435 RefPtr<Document> newDoc = piNewWin->GetExtantDoc();
8436 if (!newDoc || newDoc->IsInitialDocument()) {
8437 aLoadState->SetInternalLoadFlag(INTERNAL_LOAD_FLAGS_FIRST_LOAD);
8438 }
8439 }
8440
8441 if (newBC) {
8442 targetContext = newBC;
8443 }
8444 }
8445 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"
, 8445); return rv; } } while (false)
;
8446 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"
, 8446); return rv; } } while (false)
;
8447
8448 // If our target BrowsingContext is still pending initialization, ignore the
8449 // navigation request targeting it.
8450 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"
, 8450)
) {
8451 return NS_OK;
8452 }
8453
8454 aLoadState->SetTargetBrowsingContext(targetContext);
8455 if (aLoadState->IsFormSubmission()) {
8456 aLoadState->SetLoadType(
8457 GetLoadTypeForFormSubmission(targetContext, aLoadState));
8458 }
8459
8460 //
8461 // Transfer the load to the target BrowsingContext... Clear the window target
8462 // name to the empty string to prevent recursive retargeting!
8463 //
8464 // No window target
8465 aLoadState->SetTarget(u""_ns);
8466 // No forced download
8467 aLoadState->SetFileName(VoidString());
8468 return targetContext->InternalLoad(aLoadState);
8469}
8470
8471static nsAutoCString RefMaybeNull(nsIURI* aURI) {
8472 nsAutoCString result;
8473 if (NS_FAILED(aURI->GetRef(result))((bool)(__builtin_expect(!!(NS_FAILED_impl(aURI->GetRef(result
))), 0)))
) {
8474 result.SetIsVoid(true);
8475 }
8476 return result;
8477}
8478
8479uint32_t nsDocShell::GetSameDocumentNavigationFlags(nsIURI* aNewURI) {
8480 uint32_t flags = LOCATION_CHANGE_SAME_DOCUMENT;
8481
8482 bool equal = false;
8483 if (mCurrentURI &&
8484 NS_SUCCEEDED(mCurrentURI->EqualsExceptRef(aNewURI, &equal))((bool)(__builtin_expect(!!(!NS_FAILED_impl(mCurrentURI->EqualsExceptRef
(aNewURI, &equal))), 1)))
&& equal &&
8485 RefMaybeNull(mCurrentURI) != RefMaybeNull(aNewURI)) {
8486 flags |= LOCATION_CHANGE_HASHCHANGE;
8487 }
8488
8489 return flags;
8490}
8491
8492bool nsDocShell::IsSameDocumentNavigation(nsDocShellLoadState* aLoadState,
8493 SameDocumentNavigationState& aState) {
8494 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"
, 8494); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState"
")"); do { *((volatile int*)__null) = 8494; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8495 if (!(aLoadState->LoadType() == LOAD_NORMAL ||
8496 aLoadState->LoadType() == LOAD_STOP_CONTENT ||
8497 LOAD_TYPE_HAS_FLAGS(aLoadState->LoadType(),((aLoadState->LoadType()) & ((LOAD_FLAGS_REPLACE_HISTORY
) << 16))
8498 LOAD_FLAGS_REPLACE_HISTORY)((aLoadState->LoadType()) & ((LOAD_FLAGS_REPLACE_HISTORY
) << 16))
||
8499 aLoadState->LoadType() == LOAD_HISTORY ||
8500 aLoadState->LoadType() == LOAD_LINK)) {
8501 return false;
8502 }
8503
8504 nsCOMPtr<nsIURI> currentURI = mCurrentURI;
8505
8506 nsresult rvURINew = aLoadState->URI()->GetRef(aState.mNewHash);
8507 if (NS_SUCCEEDED(rvURINew)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rvURINew)), 1)))) {
8508 rvURINew = aLoadState->URI()->GetHasRef(&aState.mNewURIHasRef);
8509 }
8510
8511 // A Fragment Directive must be removed from the new hash in order to allow
8512 // fallback element id scroll. Additionally, the extracted parsed text
8513 // directives need to be stored for further use.
8514 nsTArray<TextDirective> textDirectives;
8515 if (FragmentDirective::ParseAndRemoveFragmentDirectiveFromFragmentString(
8516 aState.mNewHash, &textDirectives, aLoadState->URI())) {
8517 if (Document* doc = GetDocument()) {
8518 doc->FragmentDirective()->SetTextDirectives(std::move(textDirectives));
8519 }
8520 }
8521
8522 if (currentURI && NS_SUCCEEDED(rvURINew)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rvURINew)), 1)))) {
8523 nsresult rvURIOld = currentURI->GetRef(aState.mCurrentHash);
8524 if (NS_SUCCEEDED(rvURIOld)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rvURIOld)), 1)))) {
8525 rvURIOld = currentURI->GetHasRef(&aState.mCurrentURIHasRef);
8526 }
8527 if (NS_SUCCEEDED(rvURIOld)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rvURIOld)), 1)))) {
8528 if (NS_FAILED(currentURI->EqualsExceptRef(aLoadState->URI(),((bool)(__builtin_expect(!!(NS_FAILED_impl(currentURI->EqualsExceptRef
(aLoadState->URI(), &aState.mSameExceptHashes))), 0)))
8529 &aState.mSameExceptHashes))((bool)(__builtin_expect(!!(NS_FAILED_impl(currentURI->EqualsExceptRef
(aLoadState->URI(), &aState.mSameExceptHashes))), 0)))
) {
8530 aState.mSameExceptHashes = false;
8531 }
8532 }
8533 }
8534
8535 if (!aState.mSameExceptHashes && currentURI && NS_SUCCEEDED(rvURINew)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rvURINew)), 1)))) {
8536 // Maybe aLoadState->URI() came from the exposable form of currentURI?
8537 nsCOMPtr<nsIURI> currentExposableURI =
8538 nsIOService::CreateExposableURI(currentURI);
8539 nsresult rvURIOld = currentExposableURI->GetRef(aState.mCurrentHash);
8540 if (NS_SUCCEEDED(rvURIOld)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rvURIOld)), 1)))) {
8541 rvURIOld = currentExposableURI->GetHasRef(&aState.mCurrentURIHasRef);
8542 }
8543 if (NS_SUCCEEDED(rvURIOld)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rvURIOld)), 1)))) {
8544 if (NS_FAILED(currentExposableURI->EqualsExceptRef(((bool)(__builtin_expect(!!(NS_FAILED_impl(currentExposableURI
->EqualsExceptRef( aLoadState->URI(), &aState.mSameExceptHashes
))), 0)))
8545 aLoadState->URI(), &aState.mSameExceptHashes))((bool)(__builtin_expect(!!(NS_FAILED_impl(currentExposableURI
->EqualsExceptRef( aLoadState->URI(), &aState.mSameExceptHashes
))), 0)))
) {
8546 aState.mSameExceptHashes = false;
8547 }
8548 // HTTPS-Only Mode upgrades schemes from http to https in Necko, hence we
8549 // have to perform a special check here to avoid an actual navigation. If
8550 // HTTPS-Only Mode is enabled and the two URIs are same-origin (modulo the
8551 // fact that the new URI is currently http), then set mSameExceptHashes to
8552 // true and only perform a fragment navigation.
8553 if (!aState.mSameExceptHashes) {
8554 if (nsCOMPtr<nsIChannel> docChannel = GetCurrentDocChannel()) {
8555 nsCOMPtr<nsILoadInfo> docLoadInfo = docChannel->LoadInfo();
8556 if (!docLoadInfo->GetLoadErrorPage() &&
8557 nsHTTPSOnlyUtils::ShouldUpgradeConnection(docLoadInfo) &&
8558 nsHTTPSOnlyUtils::IsHttpDowngrade(currentExposableURI,
8559 aLoadState->URI())) {
8560 uint32_t status = docLoadInfo->GetHttpsOnlyStatus();
8561 if (status & (nsILoadInfo::HTTPS_ONLY_UPGRADED_LISTENER_REGISTERED |
8562 nsILoadInfo::HTTPS_ONLY_UPGRADED_HTTPS_FIRST)) {
8563 // At this point the requested URI is for sure a fragment
8564 // navigation via HTTP and HTTPS-Only mode or HTTPS-First is
8565 // enabled. Also it is not interfering the upgrade order of
8566 // https://searchfox.org/mozilla-central/source/netwerk/base/nsNetUtil.cpp#2948-2953.
8567 // Since we are on an HTTPS site the fragment
8568 // navigation should also be an HTTPS.
8569 // For that reason we should upgrade the URI to HTTPS.
8570 aState.mSecureUpgradeURI = true;
8571 aState.mSameExceptHashes = true;
8572 }
8573 }
8574 }
8575 }
8576 }
8577 }
8578
8579 if (mozilla::SessionHistoryInParent()) {
8580 if (mActiveEntry && aLoadState->LoadIsFromSessionHistory()) {
8581 aState.mHistoryNavBetweenSameDoc = mActiveEntry->SharesDocumentWith(
8582 aLoadState->GetLoadingSessionHistoryInfo()->mInfo);
8583 }
8584 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)
8585 ("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)
8586 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)
;
8587 } else {
8588 if (mOSHE && aLoadState->LoadIsFromSessionHistory()) {
8589 // We're doing a history load.
8590
8591 mOSHE->SharesDocumentWith(aLoadState->SHEntry(),
8592 &aState.mHistoryNavBetweenSameDoc);
8593 }
8594 }
8595
8596 // A same document navigation happens when we navigate between two SHEntries
8597 // for the same document. We do a same document navigation under two
8598 // circumstances. Either
8599 //
8600 // a) we're navigating between two different SHEntries which share a
8601 // document, or
8602 //
8603 // b) we're navigating to a new shentry whose URI differs from the
8604 // current URI only in its hash, the new hash is non-empty, and
8605 // we're not doing a POST.
8606 //
8607 // The restriction that the SHEntries in (a) must be different ensures
8608 // that history.go(0) and the like trigger full refreshes, rather than
8609 // same document navigations.
8610 if (!mozilla::SessionHistoryInParent()) {
8611 bool doSameDocumentNavigation =
8612 (aState.mHistoryNavBetweenSameDoc && mOSHE != aLoadState->SHEntry()) ||
8613 (!aLoadState->SHEntry() && !aLoadState->PostDataStream() &&
8614 aState.mSameExceptHashes && aState.mNewURIHasRef);
8615 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)
8616 ("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)
8617 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)
;
8618 return doSameDocumentNavigation;
8619 }
8620
8621 if (aState.mHistoryNavBetweenSameDoc &&
8622 !aLoadState->GetLoadingSessionHistoryInfo()->mLoadingCurrentEntry) {
8623 return true;
8624 }
8625
8626 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)
8627 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)
8628 ("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)
8629 "!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)
8630 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)
8631 !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)
8632 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)
8633 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)
;
8634 return !aLoadState->LoadIsFromSessionHistory() &&
8635 !aLoadState->PostDataStream() && aState.mSameExceptHashes &&
8636 aState.mNewURIHasRef;
8637}
8638
8639nsresult nsDocShell::HandleSameDocumentNavigation(
8640 nsDocShellLoadState* aLoadState, SameDocumentNavigationState& aState,
8641 bool& aSameDocument) {
8642 aSameDocument = true;
8643#ifdef DEBUG1
8644 SameDocumentNavigationState state;
8645 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"
, 8645); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsSameDocumentNavigation(aLoadState, state)"
")"); do { *((volatile int*)__null) = 8645; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8646#endif
8647
8648 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)
8649 ("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)
8650 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)
8651 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)
;
8652
8653 RefPtr<Document> doc = GetDocument();
8654 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"
, 8654); return NS_ERROR_FAILURE; } } while (false)
;
8655 doc->DoNotifyPossibleTitleChange();
8656
8657 nsCOMPtr<nsIURI> currentURI = mCurrentURI;
8658
8659 // We need to upgrade the new URI from http: to https:
8660 nsCOMPtr<nsIURI> newURI = aLoadState->URI();
8661 if (aState.mSecureUpgradeURI) {
8662 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)
;
8663 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)
8664 ("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)
;
8665 }
8666
8667 if (StaticPrefs::dom_security_setdocumenturi()) {
8668 // check if aLoadState->URI(), principalURI, mCurrentURI are same origin
8669 // skip handling otherwise
8670 nsCOMPtr<nsIPrincipal> origPrincipal = doc->NodePrincipal();
8671 nsCOMPtr<nsIURI> principalURI = origPrincipal->GetURI();
8672 if (origPrincipal->GetIsNullPrincipal()) {
8673 nsCOMPtr<nsIPrincipal> precursor = origPrincipal->GetPrecursorPrincipal();
8674 if (precursor) {
8675 principalURI = precursor->GetURI();
8676 }
8677 }
8678
8679 if (nsScriptSecurityManager::IsHttpOrHttpsAndCrossOrigin(principalURI,
8680 newURI) ||
8681 nsScriptSecurityManager::IsHttpOrHttpsAndCrossOrigin(principalURI,
8682 mCurrentURI) ||
8683 nsScriptSecurityManager::IsHttpOrHttpsAndCrossOrigin(mCurrentURI,
8684 newURI)) {
8685 aSameDocument = false;
8686 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)
8687 ("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)
8688 "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)
8689 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)
;
8690 return NS_OK;
8691 }
8692 }
8693
8694#ifdef DEBUG1
8695 if (aState.mSameExceptHashes) {
8696 bool sameExceptHashes = false;
8697 currentURI->EqualsExceptRef(newURI, &sameExceptHashes);
8698 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"
, 8698); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sameExceptHashes"
")"); do { *((volatile int*)__null) = 8698; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8699 }
8700#endif
8701 const nsCOMPtr<nsILoadInfo> loadInfo =
8702 doc->GetChannel() ? doc->GetChannel()->LoadInfo() : nullptr;
8703 if (loadInfo) {
8704 loadInfo->SetIsSameDocumentNavigation(true);
8705 }
8706 // Save the position of the scrollers.
8707 nsPoint scrollPos = GetCurScrollPos();
8708
8709 // Reset mLoadType to its original value once we exit this block, because this
8710 // same document navigation might have started after a normal, network load,
8711 // and we don't want to clobber its load type. See bug 737307.
8712 AutoRestore<uint32_t> loadTypeResetter(mLoadType);
8713
8714 // If a non-same-document-navigation (i.e., a network load) is pending, make
8715 // this a replacement load, so that we don't add a SHEntry here and the
8716 // network load goes into the SHEntry it expects to.
8717 if (JustStartedNetworkLoad() && (aLoadState->LoadType() & LOAD_CMD_NORMAL)) {
8718 mLoadType = LOAD_NORMAL_REPLACE;
8719 } else {
8720 mLoadType = aLoadState->LoadType();
8721 }
8722
8723 mURIResultedInDocument = true;
8724
8725 nsCOMPtr<nsISHEntry> oldLSHE = mLSHE;
8726
8727 // we need to assign aLoadState->SHEntry() to mLSHE right here, so that on
8728 // History loads, SetCurrentURI() called from OnNewURI() will send proper
8729 // onLocationChange() notifications to the browser to update back/forward
8730 // buttons.
8731 SetHistoryEntryAndUpdateBC(Some<nsISHEntry*>(aLoadState->SHEntry()),
8732 Nothing());
8733 UniquePtr<mozilla::dom::LoadingSessionHistoryInfo> oldLoadingEntry;
8734 mLoadingEntry.swap(oldLoadingEntry);
8735 if (aLoadState->GetLoadingSessionHistoryInfo()) {
8736 mLoadingEntry = MakeUnique<LoadingSessionHistoryInfo>(
8737 *aLoadState->GetLoadingSessionHistoryInfo());
8738 mNeedToReportActiveAfterLoadingBecomesActive = false;
8739 }
8740
8741 // Set the doc's URI according to the new history entry's URI.
8742 doc->SetDocumentURI(newURI);
8743
8744 /* This is a anchor traversal within the same page.
8745 * call OnNewURI() so that, this traversal will be
8746 * recorded in session and global history.
8747 */
8748 nsCOMPtr<nsIPrincipal> newURITriggeringPrincipal, newURIPrincipalToInherit,
8749 newURIPartitionedPrincipalToInherit;
8750 nsCOMPtr<nsIContentSecurityPolicy> newCsp;
8751 if (mozilla::SessionHistoryInParent() ? !!mActiveEntry : !!mOSHE) {
8752 if (mozilla::SessionHistoryInParent()) {
8753 newURITriggeringPrincipal = mActiveEntry->GetTriggeringPrincipal();
8754 newURIPrincipalToInherit = mActiveEntry->GetPrincipalToInherit();
8755 newURIPartitionedPrincipalToInherit =
8756 mActiveEntry->GetPartitionedPrincipalToInherit();
8757 newCsp = mActiveEntry->GetCsp();
8758 } else {
8759 newURITriggeringPrincipal = mOSHE->GetTriggeringPrincipal();
8760 newURIPrincipalToInherit = mOSHE->GetPrincipalToInherit();
8761 newURIPartitionedPrincipalToInherit =
8762 mOSHE->GetPartitionedPrincipalToInherit();
8763 newCsp = mOSHE->GetCsp();
8764 }
8765 } else {
8766 newURITriggeringPrincipal = aLoadState->TriggeringPrincipal();
8767 newURIPrincipalToInherit = doc->NodePrincipal();
8768 newURIPartitionedPrincipalToInherit = doc->PartitionedPrincipal();
8769 newCsp = doc->GetCsp();
8770 }
8771
8772 uint32_t locationChangeFlags = GetSameDocumentNavigationFlags(newURI);
8773
8774 // Pass true for aCloneSHChildren, since we're not
8775 // changing documents here, so all of our subframes are
8776 // still relevant to the new session history entry.
8777 //
8778 // It also makes OnNewURI(...) set LOCATION_CHANGE_SAME_DOCUMENT
8779 // flag on firing onLocationChange(...).
8780 // Anyway, aCloneSHChildren param is simply reflecting
8781 // doSameDocumentNavigation in this scope.
8782 //
8783 // Note: we'll actually fire onLocationChange later, in order to preserve
8784 // ordering of HistoryCommit() in the parent vs onLocationChange (bug
8785 // 1668126)
8786 bool locationChangeNeeded = OnNewURI(
8787 newURI, nullptr, newURITriggeringPrincipal, newURIPrincipalToInherit,
8788 newURIPartitionedPrincipalToInherit, newCsp, true, true);
8789
8790 nsCOMPtr<nsIInputStream> postData;
8791 nsCOMPtr<nsIReferrerInfo> referrerInfo;
8792 uint32_t cacheKey = 0;
8793
8794 bool scrollRestorationIsManual = false;
8795 if (!mozilla::SessionHistoryInParent()) {
8796 if (mOSHE) {
8797 /* save current position of scroller(s) (bug 59774) */
8798 mOSHE->SetScrollPosition(scrollPos.x, scrollPos.y);
8799 scrollRestorationIsManual = mOSHE->GetScrollRestorationIsManual();
8800 // Get the postdata, page ident and referrer info from the current page,
8801 // if the new load is being done via normal means. Note that "normal
8802 // means" can be checked for just by checking for LOAD_CMD_NORMAL, given
8803 // the loadType and allowScroll check above -- it filters out some
8804 // LOAD_CMD_NORMAL cases that we wouldn't want here.
8805 if (aLoadState->LoadType() & LOAD_CMD_NORMAL) {
8806 postData = mOSHE->GetPostData();
8807 cacheKey = mOSHE->GetCacheKey();
8808 referrerInfo = mOSHE->GetReferrerInfo();
8809 }
8810
8811 // Link our new SHEntry to the old SHEntry's back/forward
8812 // cache data, since the two SHEntries correspond to the
8813 // same document.
8814 if (mLSHE) {
8815 if (!aLoadState->LoadIsFromSessionHistory()) {
8816 // If we're not doing a history load, scroll restoration
8817 // should be inherited from the previous session history entry.
8818 SetScrollRestorationIsManualOnHistoryEntry(mLSHE,
8819 scrollRestorationIsManual);
8820 }
8821 mLSHE->AdoptBFCacheEntry(mOSHE);
8822 }
8823 }
8824 } else {
8825 if (mActiveEntry) {
8826 mActiveEntry->SetScrollPosition(scrollPos.x, scrollPos.y);
8827 if (mBrowsingContext) {
8828 CollectWireframe();
8829 if (XRE_IsParentProcess()) {
8830 SessionHistoryEntry* entry =
8831 mBrowsingContext->Canonical()->GetActiveSessionHistoryEntry();
8832 if (entry) {
8833 entry->SetScrollPosition(scrollPos.x, scrollPos.y);
8834 }
8835 } else {
8836 mozilla::Unused << ContentChild::GetSingleton()
8837 ->SendSessionHistoryEntryScrollPosition(
8838 mBrowsingContext, scrollPos.x,
8839 scrollPos.y);
8840 }
8841 }
8842 }
8843 if (mLoadingEntry) {
8844 if (!mLoadingEntry->mLoadIsFromSessionHistory) {
8845 // If we're not doing a history load, scroll restoration
8846 // should be inherited from the previous session history entry.
8847 // XXX This needs most probably tweaks once fragment navigation is
8848 // fixed to work with session-history-in-parent.
8849 SetScrollRestorationIsManualOnHistoryEntry(nullptr,
8850 scrollRestorationIsManual);
8851 }
8852 }
8853 }
8854
8855 // If we're doing a history load, use its scroll restoration state.
8856 if (aLoadState->LoadIsFromSessionHistory()) {
8857 if (mozilla::SessionHistoryInParent()) {
8858 scrollRestorationIsManual = aLoadState->GetLoadingSessionHistoryInfo()
8859 ->mInfo.GetScrollRestorationIsManual();
8860 } else {
8861 scrollRestorationIsManual =
8862 aLoadState->SHEntry()->GetScrollRestorationIsManual();
8863 }
8864 }
8865
8866 /* Assign mLSHE to mOSHE. This will either be a new entry created
8867 * by OnNewURI() for normal loads or aLoadState->SHEntry() for history
8868 * loads.
8869 */
8870 if (!mozilla::SessionHistoryInParent()) {
8871 if (mLSHE) {
8872 SetHistoryEntryAndUpdateBC(Nothing(), Some<nsISHEntry*>(mLSHE));
8873 // Save the postData obtained from the previous page
8874 // in to the session history entry created for the
8875 // anchor page, so that any history load of the anchor
8876 // page will restore the appropriate postData.
8877 if (postData) {
8878 mOSHE->SetPostData(postData);
8879 }
8880
8881 // Make sure we won't just repost without hitting the
8882 // cache first
8883 if (cacheKey != 0) {
8884 mOSHE->SetCacheKey(cacheKey);
8885 }
8886
8887 // As the document has not changed, the referrer info hasn't changed too,
8888 // so we can just copy it over.
8889 if (referrerInfo) {
8890 mOSHE->SetReferrerInfo(referrerInfo);
8891 }
8892 }
8893
8894 /* Set the title for the SH entry for this target url so that
8895 * SH menus in go/back/forward buttons won't be empty for this.
8896 * Note, this happens on mOSHE (and mActiveEntry in the future) because of
8897 * the code above.
8898 * Note, when session history lives in the parent process, this does not
8899 * update the title there.
8900 */
8901 SetTitleOnHistoryEntry(false);
8902 } else {
8903 if (aLoadState->LoadIsFromSessionHistory()) {
8904 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)
8905 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)
8906 ("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)
8907 "%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)
8908 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)
;
8909
8910 nsCOMPtr<nsILayoutHistoryState> currentLayoutHistoryState;
8911 if (mActiveEntry) {
8912 currentLayoutHistoryState = mActiveEntry->GetLayoutHistoryState();
8913 }
8914
8915 UniquePtr<SessionHistoryInfo> previousActiveEntry(mActiveEntry.release());
8916 mActiveEntry = MakeUnique<SessionHistoryInfo>(mLoadingEntry->mInfo);
8917 if (currentLayoutHistoryState) {
8918 // Restore the existing nsILayoutHistoryState object, since it is
8919 // possibly being used by the layout. When doing a new load, the
8920 // shared state is copied from the existing active entry, so this
8921 // special case is needed only with the history loads.
8922 mActiveEntry->SetLayoutHistoryState(currentLayoutHistoryState);
8923 }
8924
8925 if (cacheKey != 0) {
8926 mActiveEntry->SetCacheKey(cacheKey);
8927 }
8928 // We're passing in mCurrentURI, which could be null. SessionHistoryCommit
8929 // does require a non-null uri if this is for a refresh load of the same
8930 // URI, but in that case mCurrentURI won't be null here.
8931 mBrowsingContext->SessionHistoryCommit(
8932 *mLoadingEntry, mLoadType, mCurrentURI, previousActiveEntry.get(),
8933 true, true,
8934 /* No expiration update on the same document loads*/
8935 false, cacheKey);
8936 // FIXME Need to set postdata.
8937
8938 // Set the title for the SH entry for this target url so that
8939 // SH menus in go/back/forward buttons won't be empty for this.
8940 // Note, when session history lives in the parent process, this does not
8941 // update the title there.
8942 SetTitleOnHistoryEntry(false);
8943 } else {
8944 Maybe<bool> scrollRestorationIsManual;
8945 if (mActiveEntry) {
8946 scrollRestorationIsManual.emplace(
8947 mActiveEntry->GetScrollRestorationIsManual());
8948
8949 // Get the postdata, page ident and referrer info from the current page,
8950 // if the new load is being done via normal means. Note that "normal
8951 // means" can be checked for just by checking for LOAD_CMD_NORMAL, given
8952 // the loadType and allowScroll check above -- it filters out some
8953 // LOAD_CMD_NORMAL cases that we wouldn't want here.
8954 if (aLoadState->LoadType() & LOAD_CMD_NORMAL) {
8955 postData = mActiveEntry->GetPostData();
8956 cacheKey = mActiveEntry->GetCacheKey();
8957 referrerInfo = mActiveEntry->GetReferrerInfo();
8958 }
8959 }
8960
8961 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)
8962 ("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)
8963 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)
;
8964 if (mActiveEntry) {
8965 mActiveEntry = MakeUnique<SessionHistoryInfo>(*mActiveEntry, newURI);
8966 } else {
8967 mActiveEntry = MakeUnique<SessionHistoryInfo>(
8968 newURI, newURITriggeringPrincipal, newURIPrincipalToInherit,
8969 newURIPartitionedPrincipalToInherit, newCsp, mContentTypeHint);
8970 }
8971
8972 // Save the postData obtained from the previous page in to the session
8973 // history entry created for the anchor page, so that any history load of
8974 // the anchor page will restore the appropriate postData.
8975 if (postData) {
8976 mActiveEntry->SetPostData(postData);
8977 }
8978
8979 // Make sure we won't just repost without hitting the
8980 // cache first
8981 if (cacheKey != 0) {
8982 mActiveEntry->SetCacheKey(cacheKey);
8983 }
8984
8985 // As the document has not changed, the referrer info hasn't changed too,
8986 // so we can just copy it over.
8987 if (referrerInfo) {
8988 mActiveEntry->SetReferrerInfo(referrerInfo);
8989 }
8990
8991 // Set the title for the SH entry for this target url so that
8992 // SH menus in go/back/forward buttons won't be empty for this.
8993 mActiveEntry->SetTitle(mTitle);
8994
8995 if (scrollRestorationIsManual.isSome()) {
8996 mActiveEntry->SetScrollRestorationIsManual(
8997 scrollRestorationIsManual.value());
8998 }
8999
9000 if (LOAD_TYPE_HAS_FLAGS(mLoadType, LOAD_FLAGS_REPLACE_HISTORY)((mLoadType) & ((LOAD_FLAGS_REPLACE_HISTORY) << 16)
)
) {
9001 mBrowsingContext->ReplaceActiveSessionHistoryEntry(mActiveEntry.get());
9002 } else {
9003 mBrowsingContext->IncrementHistoryEntryCountForBrowsingContext();
9004 // FIXME We should probably just compute mChildOffset in the parent
9005 // instead of passing it over IPC here.
9006 mBrowsingContext->SetActiveSessionHistoryEntry(
9007 Some(scrollPos), mActiveEntry.get(), mLoadType, cacheKey);
9008 // FIXME Do we need to update mPreviousEntryIndex and mLoadedEntryIndex?
9009 }
9010 }
9011 }
9012
9013 if (locationChangeNeeded) {
9014 FireOnLocationChange(this, nullptr, newURI, locationChangeFlags);
9015 }
9016
9017 /* Restore the original LSHE if we were loading something
9018 * while same document navigation was initiated.
9019 */
9020 SetHistoryEntryAndUpdateBC(Some<nsISHEntry*>(oldLSHE), Nothing());
9021 mLoadingEntry.swap(oldLoadingEntry);
9022
9023 /* Set the title for the Global History entry for this anchor url.
9024 */
9025 UpdateGlobalHistoryTitle(newURI);
9026
9027 SetDocCurrentStateObj(mOSHE, mActiveEntry.get());
9028
9029 // Inform the favicon service that the favicon for oldURI also
9030 // applies to newURI.
9031 CopyFavicon(currentURI, newURI, UsePrivateBrowsing());
9032
9033 RefPtr<nsGlobalWindowOuter> scriptGlobal = mScriptGlobal;
9034 nsCOMPtr<nsPIDOMWindowInner> win =
9035 scriptGlobal ? scriptGlobal->GetCurrentInnerWindow() : nullptr;
9036
9037 // ScrollToAnchor doesn't necessarily cause us to scroll the window;
9038 // the function decides whether a scroll is appropriate based on the
9039 // arguments it receives. But even if we don't end up scrolling,
9040 // ScrollToAnchor performs other important tasks, such as informing
9041 // the presShell that we have a new hash. See bug 680257.
9042 nsresult rv = ScrollToAnchor(aState.mCurrentURIHasRef, aState.mNewURIHasRef,
9043 aState.mNewHash, aLoadState->LoadType());
9044 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"
, 9044); return rv; } } while (false)
;
9045
9046 /* restore previous position of scroller(s), if we're moving
9047 * back in history (bug 59774)
9048 */
9049 nscoord bx = 0;
9050 nscoord by = 0;
9051 bool needsScrollPosUpdate = false;
9052 if ((mozilla::SessionHistoryInParent() ? !!mActiveEntry : !!mOSHE) &&
9053 (aLoadState->LoadType() == LOAD_HISTORY ||
9054 aLoadState->LoadType() == LOAD_RELOAD_NORMAL) &&
9055 !scrollRestorationIsManual) {
9056 needsScrollPosUpdate = true;
9057 if (mozilla::SessionHistoryInParent()) {
9058 mActiveEntry->GetScrollPosition(&bx, &by);
9059 } else {
9060 mOSHE->GetScrollPosition(&bx, &by);
9061 }
9062 }
9063
9064 // Dispatch the popstate and hashchange events, as appropriate.
9065 //
9066 // The event dispatch below can cause us to re-enter script and
9067 // destroy the docshell, nulling out mScriptGlobal. Hold a stack
9068 // reference to avoid null derefs. See bug 914521.
9069 if (win) {
9070 // Fire a hashchange event URIs differ, and only in their hashes.
9071 bool doHashchange = aState.mSameExceptHashes &&
9072 (aState.mCurrentURIHasRef != aState.mNewURIHasRef ||
9073 !aState.mCurrentHash.Equals(aState.mNewHash));
9074
9075 if (aState.mHistoryNavBetweenSameDoc || doHashchange) {
9076 win->DispatchSyncPopState();
9077 }
9078
9079 if (needsScrollPosUpdate && win->HasActiveDocument()) {
9080 SetCurScrollPosEx(bx, by);
9081 }
9082
9083 if (doHashchange) {
9084 // Note that currentURI hasn't changed because it's on the
9085 // stack, so we can just use it directly as the old URI.
9086 win->DispatchAsyncHashchange(currentURI, newURI);
9087 }
9088 }
9089
9090 return NS_OK;
9091}
9092
9093static bool NavigationShouldTakeFocus(nsDocShell* aDocShell,
9094 nsDocShellLoadState* aLoadState) {
9095 if (!aLoadState->AllowFocusMove()) {
9096 return false;
9097 }
9098 if (!aLoadState->HasValidUserGestureActivation()) {
9099 return false;
9100 }
9101 const auto& sourceBC = aLoadState->SourceBrowsingContext();
9102 if (!sourceBC || !sourceBC->IsActive()) {
9103 // If the navigation didn't come from a foreground tab, then we don't steal
9104 // focus.
9105 return false;
9106 }
9107 auto* bc = aDocShell->GetBrowsingContext();
9108 if (sourceBC.get() == bc) {
9109 // If it comes from the same tab / frame, don't steal focus either.
9110 return false;
9111 }
9112 auto* fm = nsFocusManager::GetFocusManager();
9113 if (fm && bc->IsActive() && fm->IsInActiveWindow(bc)) {
9114 // If we're already on the foreground tab of the foreground window, then we
9115 // don't need to do this. This helps to e.g. not steal focus from the
9116 // browser chrome unnecessarily.
9117 return false;
9118 }
9119 if (auto* doc = aDocShell->GetExtantDocument()) {
9120 if (doc->IsInitialDocument()) {
9121 // If we're the initial load for the browsing context, the browser
9122 // chrome determines what to focus. This is important because the
9123 // browser chrome may want to e.g focus the url-bar
9124 return false;
9125 }
9126 }
9127 // Take loadDivertedInBackground into account so the behavior would be the
9128 // same as how the tab first opened.
9129 return !Preferences::GetBool("browser.tabs.loadDivertedInBackground", false);
9130}
9131
9132uint32_t nsDocShell::GetLoadTypeForFormSubmission(
9133 BrowsingContext* aTargetBC, nsDocShellLoadState* aLoadState) {
9134 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"
, 9134); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->IsFormSubmission()"
")"); do { *((volatile int*)__null) = 9134; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9135
9136 // https://html.spec.whatwg.org/#form-submission-algorithm
9137 // 22. Let historyHandling be "push".
9138 // 23. If form document equals targetNavigable's active document, and
9139 // form document has not yet completely loaded, then set
9140 // historyHandling to "replace".
9141 return GetBrowsingContext() == aTargetBC && !mEODForCurrentDocument
9142 ? LOAD_NORMAL_REPLACE
9143 : LOAD_LINK;
9144}
9145
9146nsresult nsDocShell::InternalLoad(nsDocShellLoadState* aLoadState,
9147 Maybe<uint32_t> aCacheKey) {
9148 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"
, 9148); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState"
") (" "need a load state!" ")"); do { *((volatile int*)__null
) = 9148; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
;
9149 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"
, 9150); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->TriggeringPrincipal()"
") (" "need a valid TriggeringPrincipal" ")"); do { *((volatile
int*)__null) = 9150; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
9150 "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"
, 9150); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->TriggeringPrincipal()"
") (" "need a valid TriggeringPrincipal" ")"); do { *((volatile
int*)__null) = 9150; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
9151
9152 if (!aLoadState->TriggeringPrincipal()) {
9153 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"
, 9153); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"InternalLoad needs a valid triggeringPrincipal" ")"); do { *
((volatile int*)__null) = 9153; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
;
9154 return NS_ERROR_FAILURE;
9155 }
9156 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"
, 9156)
) {
9157 return NS_ERROR_NOT_AVAILABLE;
9158 }
9159
9160 const bool shouldTakeFocus = NavigationShouldTakeFocus(this, aLoadState);
9161
9162 mOriginalUriString.Truncate();
9163
9164 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)
9165 ("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)
9166 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)
;
9167
9168 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"
, 9168); return NS_ERROR_INVALID_ARG; } } while (false)
;
9169
9170 // Cancel loads coming from Docshells that are being destroyed.
9171 if (mIsBeingDestroyed) {
9172 return NS_ERROR_NOT_AVAILABLE;
9173 }
9174
9175 nsresult rv = EnsureScriptEnvironment();
9176 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
9177 return rv;
9178 }
9179
9180 // If we have a target to move to, do that now.
9181 if (!aLoadState->Target().IsEmpty()) {
9182 return PerformRetargeting(aLoadState);
9183 }
9184
9185 // This is the non-retargeting load path, we've already set the right loadtype
9186 // for form submissions in nsDocShell::OnLinkClickSync.
9187 if (aLoadState->TargetBrowsingContext().IsNull()) {
9188 aLoadState->SetTargetBrowsingContext(GetBrowsingContext());
9189 }
9190
9191 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"
, 9193); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "aLoadState->TargetBrowsingContext() == GetBrowsingContext()"
") (" "Load must be targeting this BrowsingContext" ")"); do
{ *((volatile int*)__null) = 9193; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
9192 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"
, 9193); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "aLoadState->TargetBrowsingContext() == GetBrowsingContext()"
") (" "Load must be targeting this BrowsingContext" ")"); do
{ *((volatile int*)__null) = 9193; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
9193 "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"
, 9193); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "aLoadState->TargetBrowsingContext() == GetBrowsingContext()"
") (" "Load must be targeting this BrowsingContext" ")"); do
{ *((volatile int*)__null) = 9193; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
9194
9195 MOZ_TRY(CheckDisallowedJavascriptLoad(aLoadState))do { auto mozTryTempResult_ = ::mozilla::ToResult(CheckDisallowedJavascriptLoad
(aLoadState)); if ((__builtin_expect(!!(mozTryTempResult_.isErr
()), 0))) { return mozTryTempResult_.propagateErr(); } } while
(0)
;
9196
9197 // If we don't have a target, we're loading into ourselves, and our load
9198 // delegate may want to intercept that load.
9199 SameDocumentNavigationState sameDocumentNavigationState;
9200 bool sameDocument =
9201 IsSameDocumentNavigation(aLoadState, sameDocumentNavigationState) &&
9202 !aLoadState->GetPendingRedirectedChannel();
9203
9204 // Note: We do this check both here and in BrowsingContext::
9205 // LoadURI/InternalLoad, since document-specific sandbox flags are only
9206 // available in the process triggering the load, and we don't want the target
9207 // process to have to trust the triggering process to do the appropriate
9208 // checks for the BrowsingContext's sandbox flags.
9209 MOZ_TRY(mBrowsingContext->CheckSandboxFlags(aLoadState))do { auto mozTryTempResult_ = ::mozilla::ToResult(mBrowsingContext
->CheckSandboxFlags(aLoadState)); if ((__builtin_expect(!!
(mozTryTempResult_.isErr()), 0))) { return mozTryTempResult_.
propagateErr(); } } while (0)
;
9210
9211 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"
, 9211); return NS_ERROR_UNEXPECTED; } } while (false)
;
9212
9213 rv = CheckLoadingPermissions();
9214 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
9215 return rv;
9216 }
9217
9218 if (mFiredUnloadEvent) {
9219 if (IsOKToLoadURI(aLoadState->URI())) {
9220 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"
, 9221); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->Target().IsEmpty()"
") (" "Shouldn't have a window target here!" ")"); do { *((volatile
int*)__null) = 9221; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
9221 "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"
, 9221); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->Target().IsEmpty()"
") (" "Shouldn't have a window target here!" ")"); do { *((volatile
int*)__null) = 9221; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
9222
9223 // If this is a replace load, make whatever load triggered
9224 // the unload event also a replace load, so we don't
9225 // create extra history entries.
9226 if (LOAD_TYPE_HAS_FLAGS(aLoadState->LoadType(),((aLoadState->LoadType()) & ((LOAD_FLAGS_REPLACE_HISTORY
) << 16))
9227 LOAD_FLAGS_REPLACE_HISTORY)((aLoadState->LoadType()) & ((LOAD_FLAGS_REPLACE_HISTORY
) << 16))
) {
9228 mLoadType = LOAD_NORMAL_REPLACE;
9229 }
9230
9231 // Do this asynchronously
9232 nsCOMPtr<nsIRunnable> ev = new InternalLoadEvent(this, aLoadState);
9233 return Dispatch(ev.forget());
9234 }
9235
9236 // Just ignore this load attempt
9237 return NS_OK;
9238 }
9239
9240 // If we are loading a URI that should inherit a security context (basically
9241 // javascript: at this point), and the caller has said that principal
9242 // inheritance is allowed, there are a few possible cases:
9243 //
9244 // 1) We are provided with the principal to inherit. In that case, we just use
9245 // it.
9246 //
9247 // 2) The load is coming from some other application. In this case we don't
9248 // want to inherit from whatever document we have loaded now, since the
9249 // load is unrelated to it.
9250 //
9251 // 3) It's a load from our application, but does not provide an explicit
9252 // principal to inherit. In that case, we want to inherit the principal of
9253 // our current document, or of our parent document (if any) if we don't
9254 // have a current document.
9255 {
9256 bool inherits;
9257
9258 if (!aLoadState->HasLoadFlags(LOAD_FLAGS_FROM_EXTERNAL) &&
9259 !aLoadState->PrincipalToInherit() &&
9260 (aLoadState->HasInternalLoadFlags(
9261 INTERNAL_LOAD_FLAGS_INHERIT_PRINCIPAL)) &&
9262 NS_SUCCEEDED(nsContentUtils::URIInheritsSecurityContext(((bool)(__builtin_expect(!!(!NS_FAILED_impl(nsContentUtils::URIInheritsSecurityContext
( aLoadState->URI(), &inherits))), 1)))
9263 aLoadState->URI(), &inherits))((bool)(__builtin_expect(!!(!NS_FAILED_impl(nsContentUtils::URIInheritsSecurityContext
( aLoadState->URI(), &inherits))), 1)))
&&
9264 inherits) {
9265 aLoadState->SetPrincipalToInherit(GetInheritedPrincipal(true));
9266 }
9267 // If principalToInherit is still null (e.g. if some of the conditions of
9268 // were not satisfied), then no inheritance of any sort will happen: the
9269 // load will just get a principal based on the URI being loaded.
9270 }
9271
9272 // If this docshell is owned by a frameloader, make sure to cancel
9273 // possible frameloader initialization before loading a new page.
9274 nsCOMPtr<nsIDocShellTreeItem> parent = GetInProcessParentDocshell();
9275 if (parent) {
9276 RefPtr<Document> doc = parent->GetDocument();
9277 if (doc) {
9278 doc->TryCancelFrameLoaderInitialization(this);
9279 }
9280 }
9281
9282 // Before going any further vet loads initiated by external programs.
9283 if (aLoadState->HasLoadFlags(LOAD_FLAGS_FROM_EXTERNAL)) {
9284 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"
, 9284); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "aLoadState->LoadType() == LOAD_NORMAL"
")"); do { *((volatile int*)__null) = 9284; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9285
9286 // Disallow external chrome: loads targetted at content windows
9287 if (SchemeIsChrome(aLoadState->URI())) {
9288 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"
, 9288)
;
9289 return NS_ERROR_FAILURE;
9290 }
9291
9292 // clear the decks to prevent context bleed-through (bug 298255)
9293 rv = CreateAboutBlankDocumentViewer(nullptr, nullptr, nullptr, nullptr,
9294 /* aIsInitialDocument */ false);
9295 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
9296 return NS_ERROR_FAILURE;
9297 }
9298 }
9299
9300 mAllowKeywordFixup = aLoadState->HasInternalLoadFlags(
9301 INTERNAL_LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP);
9302 mURIResultedInDocument = false; // reset the clock...
9303
9304 // See if this is actually a load between two history entries for the same
9305 // document. If the process fails, or if we successfully navigate within the
9306 // same document, return.
9307 if (sameDocument) {
9308 nsresult rv = HandleSameDocumentNavigation(
9309 aLoadState, sameDocumentNavigationState, sameDocument);
9310 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"
, 9310); return rv; } } while (false)
;
9311 if (shouldTakeFocus) {
9312 mBrowsingContext->Focus(CallerType::System, IgnoreErrors());
9313 }
9314 if (sameDocument) {
9315 return rv;
9316 }
9317 }
9318
9319 // mDocumentViewer->PermitUnload can destroy |this| docShell, which
9320 // causes the next call of CanSavePresentation to crash.
9321 // Hold onto |this| until we return, to prevent a crash from happening.
9322 // (bug#331040)
9323 nsCOMPtr<nsIDocShell> kungFuDeathGrip(this);
9324
9325 // Don't init timing for javascript:, since it generally doesn't
9326 // actually start a load or anything. If it does, we'll init
9327 // timing then, from OnStateChange.
9328
9329 // XXXbz mTiming should know what channel it's for, so we don't
9330 // need this hackery.
9331 bool toBeReset = false;
9332 bool isJavaScript = SchemeIsJavascript(aLoadState->URI());
9333
9334 if (!isJavaScript) {
9335 toBeReset = MaybeInitTiming();
9336 }
9337 bool isNotDownload = aLoadState->FileName().IsVoid();
9338 if (mTiming && isNotDownload) {
9339 mTiming->NotifyBeforeUnload();
9340 }
9341 // Check if the page doesn't want to be unloaded. The javascript:
9342 // protocol handler deals with this for javascript: URLs.
9343 if (!isJavaScript && isNotDownload &&
9344 !aLoadState->NotifiedBeforeUnloadListeners() && mDocumentViewer) {
9345 bool okToUnload;
9346
9347 // Check if request is exempted from HTTPSOnlyMode and if https-first is
9348 // enabled, if so it means:
9349 // * https-first failed to upgrade request to https
9350 // * we already asked for permission to unload and the user accepted
9351 // otherwise we wouldn't be here.
9352 bool isPrivateWin = GetOriginAttributes().IsPrivateBrowsing();
9353 bool isHistoryOrReload = false;
9354 uint32_t loadType = aLoadState->LoadType();
9355
9356 // Check if request is a reload.
9357 if (loadType == LOAD_RELOAD_NORMAL ||
9358 loadType == LOAD_RELOAD_BYPASS_CACHE ||
9359 loadType == LOAD_RELOAD_BYPASS_PROXY ||
9360 loadType == LOAD_RELOAD_BYPASS_PROXY_AND_CACHE ||
9361 loadType == LOAD_HISTORY) {
9362 isHistoryOrReload = true;
9363 }
9364
9365 // If it isn't a reload, the request already failed to be upgraded and
9366 // https-first is enabled then don't ask the user again for permission to
9367 // unload and just unload.
9368 if (!isHistoryOrReload && aLoadState->IsExemptFromHTTPSFirstMode() &&
9369 nsHTTPSOnlyUtils::IsHttpsFirstModeEnabled(isPrivateWin)) {
9370 rv = mDocumentViewer->PermitUnload(
9371 nsIDocumentViewer::PermitUnloadAction::eDontPromptAndUnload,
9372 &okToUnload);
9373 } else {
9374 rv = mDocumentViewer->PermitUnload(&okToUnload);
9375 }
9376
9377 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && !okToUnload) {
9378 // The user chose not to unload the page, interrupt the
9379 // load.
9380 MaybeResetInitTiming(toBeReset);
9381 return NS_OK;
9382 }
9383 }
9384
9385 if (mTiming && isNotDownload) {
9386 mTiming->NotifyUnloadAccepted(mCurrentURI);
9387 }
9388
9389 // In e10s, in the parent process, we refuse to load anything other than
9390 // "safe" resources that we ship or trust enough to give "special" URLs.
9391 // Similar check will be performed by the ParentProcessDocumentChannel if in
9392 // use.
9393 if (XRE_IsE10sParentProcess() &&
9394 !DocumentChannel::CanUseDocumentChannel(aLoadState->URI()) &&
9395 !CanLoadInParentProcess(aLoadState->URI())) {
9396 return NS_ERROR_FAILURE;
9397 }
9398
9399 // Whenever a top-level browsing context is navigated, the user agent MUST
9400 // lock the orientation of the document to the document's default
9401 // orientation. We don't explicitly check for a top-level browsing context
9402 // here because orientation is only set on top-level browsing contexts.
9403 if (mBrowsingContext->GetOrientationLock() != hal::ScreenOrientation::None) {
9404 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"
, 9404); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mBrowsingContext->IsTop()"
")"); do { *((volatile int*)__null) = 9404; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9405 MOZ_ALWAYS_SUCCEEDS(do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(mBrowsingContext->SetOrientationLock(hal::ScreenOrientation
::None))), 1)))), 1))) { } else { do { static_assert( mozilla
::detail::AssertionConditionType<decltype(false)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(false))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("false" " (" "NS_SUCCEEDED(mBrowsingContext->SetOrientationLock(hal::ScreenOrientation::None))"
")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 9406); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "false"
") (" "NS_SUCCEEDED(mBrowsingContext->SetOrientationLock(hal::ScreenOrientation::None))"
")"); do { *((volatile int*)__null) = 9406; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
9406 mBrowsingContext->SetOrientationLock(hal::ScreenOrientation::None))do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(mBrowsingContext->SetOrientationLock(hal::ScreenOrientation
::None))), 1)))), 1))) { } else { do { static_assert( mozilla
::detail::AssertionConditionType<decltype(false)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(false))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("false" " (" "NS_SUCCEEDED(mBrowsingContext->SetOrientationLock(hal::ScreenOrientation::None))"
")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 9406); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "false"
") (" "NS_SUCCEEDED(mBrowsingContext->SetOrientationLock(hal::ScreenOrientation::None))"
")"); do { *((volatile int*)__null) = 9406; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
9407 if (mBrowsingContext->IsActive()) {
9408 ScreenOrientation::UpdateActiveOrientationLock(
9409 hal::ScreenOrientation::None);
9410 }
9411 }
9412
9413 // Check for saving the presentation here, before calling Stop().
9414 // This is necessary so that we can catch any pending requests.
9415 // Since the new request has not been created yet, we pass null for the
9416 // new request parameter.
9417 // Also pass nullptr for the document, since it doesn't affect the return
9418 // value for our purposes here.
9419 bool savePresentation =
9420 CanSavePresentation(aLoadState->LoadType(), nullptr, nullptr,
9421 /* aReportBFCacheComboTelemetry */ true);
9422
9423 // nsDocShell::CanSavePresentation is for non-SHIP version only. Do a
9424 // separate check for SHIP so that we know if there are ongoing requests
9425 // before calling Stop() below.
9426 if (mozilla::SessionHistoryInParent()) {
9427 Document* document = GetDocument();
9428 uint32_t flags = 0;
9429 if (document && !document->CanSavePresentation(nullptr, flags, true)) {
9430 // This forces some flags into the WindowGlobalParent's mBFCacheStatus,
9431 // which we'll then use in CanonicalBrowsingContext::AllowedInBFCache,
9432 // and in particular we'll store BFCacheStatus::REQUEST if needed.
9433 // Also, we want to report all the flags to the parent process here (and
9434 // not just BFCacheStatus::NOT_ALLOWED), so that it can update the
9435 // telemetry data correctly.
9436 document->DisallowBFCaching(flags);
9437 }
9438 }
9439
9440 // Don't stop current network activity for javascript: URL's since
9441 // they might not result in any data, and thus nothing should be
9442 // stopped in those cases. In the case where they do result in
9443 // data, the javascript: URL channel takes care of stopping
9444 // current network activity.
9445 if (!isJavaScript && isNotDownload) {
9446 // Stop any current network activity.
9447 // Also stop content if this is a zombie doc. otherwise
9448 // the onload will be delayed by other loads initiated in the
9449 // background by the first document that
9450 // didn't fully load before the next load was initiated.
9451 // If not a zombie, don't stop content until data
9452 // starts arriving from the new URI...
9453
9454 if ((mDocumentViewer && mDocumentViewer->GetPreviousViewer()) ||
9455 LOAD_TYPE_HAS_FLAGS(aLoadState->LoadType(), LOAD_FLAGS_STOP_CONTENT)((aLoadState->LoadType()) & ((LOAD_FLAGS_STOP_CONTENT)
<< 16))
) {
9456 rv = Stop(nsIWebNavigation::STOP_ALL);
9457 } else {
9458 rv = Stop(nsIWebNavigation::STOP_NETWORK);
9459 }
9460
9461 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
9462 return rv;
9463 }
9464 }
9465
9466 mLoadType = aLoadState->LoadType();
9467
9468 // aLoadState->SHEntry() should be assigned to mLSHE, only after Stop() has
9469 // been called. But when loading an error page, do not clear the
9470 // mLSHE for the real page.
9471 if (mLoadType != LOAD_ERROR_PAGE) {
9472 SetHistoryEntryAndUpdateBC(Some<nsISHEntry*>(aLoadState->SHEntry()),
9473 Nothing());
9474 if (aLoadState->LoadIsFromSessionHistory() &&
9475 !mozilla::SessionHistoryInParent()) {
9476 // We're making history navigation or a reload. Make sure our history ID
9477 // points to the same ID as SHEntry's docshell ID.
9478 nsID historyID = {};
9479 aLoadState->SHEntry()->GetDocshellID(historyID);
9480
9481 Unused << mBrowsingContext->SetHistoryID(historyID);
9482 }
9483 }
9484
9485 mSavingOldViewer = savePresentation;
9486
9487 // If we have a saved content viewer in history, restore and show it now.
9488 if (aLoadState->LoadIsFromSessionHistory() &&
9489 (mLoadType & LOAD_CMD_HISTORY)) {
9490 // https://html.spec.whatwg.org/#history-traversal:
9491 // To traverse the history
9492 // "If entry has a different Document object than the current entry, then
9493 // run the following substeps: Remove any tasks queued by the history
9494 // traversal task source..."
9495 // Same document object case was handled already above with
9496 // HandleSameDocumentNavigation call.
9497 RefPtr<ChildSHistory> shistory = GetRootSessionHistory();
9498 if (shistory) {
9499 shistory->RemovePendingHistoryNavigations();
9500 }
9501 if (!mozilla::SessionHistoryInParent()) {
9502 // It's possible that the previous viewer of mDocumentViewer is the
9503 // viewer that will end up in aLoadState->SHEntry() when it gets closed.
9504 // If that's the case, we need to go ahead and force it into its shentry
9505 // so we can restore it.
9506 if (mDocumentViewer) {
9507 nsCOMPtr<nsIDocumentViewer> prevViewer =
9508 mDocumentViewer->GetPreviousViewer();
9509 if (prevViewer) {
9510#ifdef DEBUG1
9511 nsCOMPtr<nsIDocumentViewer> prevPrevViewer =
9512 prevViewer->GetPreviousViewer();
9513 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"
, 9513); MOZ_PretendNoReturn(); } } while (0)
;
9514#endif
9515 nsCOMPtr<nsISHEntry> viewerEntry;
9516 prevViewer->GetHistoryEntry(getter_AddRefs(viewerEntry));
9517 if (viewerEntry == aLoadState->SHEntry()) {
9518 // Make sure this viewer ends up in the right place
9519 mDocumentViewer->SetPreviousViewer(nullptr);
9520 prevViewer->Destroy();
9521 }
9522 }
9523 }
9524 nsCOMPtr<nsISHEntry> oldEntry = mOSHE;
9525 bool restoring;
9526 rv = RestorePresentation(aLoadState->SHEntry(), &restoring);
9527 if (restoring) {
9528 Telemetry::Accumulate(Telemetry::BFCACHE_PAGE_RESTORED, true);
9529 return rv;
9530 }
9531 Telemetry::Accumulate(Telemetry::BFCACHE_PAGE_RESTORED, false);
9532
9533 // We failed to restore the presentation, so clean up.
9534 // Both the old and new history entries could potentially be in
9535 // an inconsistent state.
9536 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
9537 if (oldEntry) {
9538 oldEntry->SyncPresentationState();
9539 }
9540
9541 aLoadState->SHEntry()->SyncPresentationState();
9542 }
9543 }
9544 }
9545
9546 bool isTopLevelDoc = mBrowsingContext->IsTopContent();
9547
9548 OriginAttributes attrs = GetOriginAttributes();
9549 attrs.SetFirstPartyDomain(isTopLevelDoc, aLoadState->URI());
9550
9551 PredictorLearn(aLoadState->URI(), nullptr,
9552 nsINetworkPredictor::LEARN_LOAD_TOPLEVEL, attrs);
9553 PredictorPredict(aLoadState->URI(), nullptr,
9554 nsINetworkPredictor::PREDICT_LOAD, attrs, nullptr);
9555
9556 nsCOMPtr<nsIRequest> req;
9557 rv = DoURILoad(aLoadState, aCacheKey, getter_AddRefs(req));
9558
9559 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
9560 if (shouldTakeFocus) {
9561 mBrowsingContext->Focus(CallerType::System, IgnoreErrors());
9562 }
9563 }
9564
9565 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
9566 nsCOMPtr<nsIChannel> chan(do_QueryInterface(req));
9567 UnblockEmbedderLoadEventForFailure();
9568 nsCOMPtr<nsIURI> uri = aLoadState->URI();
9569 if (DisplayLoadError(rv, uri, nullptr, chan) &&
9570 // FIXME: At this point code was using internal load flags, but checking
9571 // non-internal load flags?
9572 aLoadState->HasLoadFlags(LOAD_FLAGS_ERROR_LOAD_CHANGES_RV)) {
9573 return NS_ERROR_LOAD_SHOWED_ERRORPAGE;
9574 }
9575
9576 // We won't report any error if this is an unknown protocol error. The
9577 // reason behind this is that it will allow enumeration of external
9578 // protocols if we report an error for each unknown protocol.
9579 if (NS_ERROR_UNKNOWN_PROTOCOL == rv) {
9580 return NS_OK;
9581 }
9582 }
9583
9584 return rv;
9585}
9586
9587/* static */
9588bool nsDocShell::CanLoadInParentProcess(nsIURI* aURI) {
9589 nsCOMPtr<nsIURI> uri = aURI;
9590 // In e10s, in the parent process, we refuse to load anything other than
9591 // "safe" resources that we ship or trust enough to give "special" URLs.
9592 bool canLoadInParent = false;
9593 if (NS_SUCCEEDED(NS_URIChainHasFlags(((bool)(__builtin_expect(!!(!NS_FAILED_impl(NS_URIChainHasFlags
( uri, nsIProtocolHandler::URI_IS_UI_RESOURCE, &canLoadInParent
))), 1)))
9594 uri, nsIProtocolHandler::URI_IS_UI_RESOURCE, &canLoadInParent))((bool)(__builtin_expect(!!(!NS_FAILED_impl(NS_URIChainHasFlags
( uri, nsIProtocolHandler::URI_IS_UI_RESOURCE, &canLoadInParent
))), 1)))
&&
9595 canLoadInParent) {
9596 // We allow UI resources.
9597 return true;
9598 }
9599 // For about: and extension-based URIs, which don't get
9600 // URI_IS_UI_RESOURCE, first remove layers of view-source:, if present.
9601 while (uri && uri->SchemeIs("view-source")) {
9602 nsCOMPtr<nsINestedURI> nested = do_QueryInterface(uri);
9603 if (nested) {
9604 nested->GetInnerURI(getter_AddRefs(uri));
9605 } else {
9606 break;
9607 }
9608 }
9609 // Allow about: URIs, and allow moz-extension ones if we're running
9610 // extension content in the parent process.
9611 if (!uri || uri->SchemeIs("about") ||
9612 (!StaticPrefs::extensions_webextensions_remote() &&
9613 uri->SchemeIs("moz-extension"))) {
9614 return true;
9615 }
9616#ifdef MOZ_THUNDERBIRD
9617 if (uri->SchemeIs("imap") || uri->SchemeIs("mailbox") ||
9618 uri->SchemeIs("news") || uri->SchemeIs("nntp") ||
9619 uri->SchemeIs("snews") || uri->SchemeIs("x-moz-ews")) {
9620 return true;
9621 }
9622#endif
9623 nsAutoCString scheme;
9624 uri->GetScheme(scheme);
9625 // Allow ext+foo URIs (extension-registered custom protocols). See
9626 // https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/protocol_handlers
9627 if (StringBeginsWith(scheme, "ext+"_ns) &&
9628 !StaticPrefs::extensions_webextensions_remote()) {
9629 return true;
9630 }
9631 // Final exception for some legacy automated tests:
9632 if (xpc::IsInAutomation() &&
9633 StaticPrefs::security_allow_unsafe_parent_loads()) {
9634 return true;
9635 }
9636 return false;
9637}
9638
9639nsIPrincipal* nsDocShell::GetInheritedPrincipal(
9640 bool aConsiderCurrentDocument, bool aConsiderPartitionedPrincipal) {
9641 RefPtr<Document> document;
9642 bool inheritedFromCurrent = false;
9643
9644 if (aConsiderCurrentDocument && mDocumentViewer) {
9645 document = mDocumentViewer->GetDocument();
9646 inheritedFromCurrent = true;
9647 }
9648
9649 if (!document) {
9650 nsCOMPtr<nsIDocShellTreeItem> parentItem;
9651 GetInProcessSameTypeParent(getter_AddRefs(parentItem));
9652 if (parentItem) {
9653 document = parentItem->GetDocument();
9654 }
9655 }
9656
9657 if (!document) {
9658 if (!aConsiderCurrentDocument) {
9659 return nullptr;
9660 }
9661
9662 // Make sure we end up with _something_ as the principal no matter
9663 // what.If this fails, we'll just get a null docViewer and bail.
9664 EnsureDocumentViewer();
9665 if (!mDocumentViewer) {
9666 return nullptr;
9667 }
9668 document = mDocumentViewer->GetDocument();
9669 }
9670
9671 //-- Get the document's principal
9672 if (document) {
9673 nsIPrincipal* docPrincipal = aConsiderPartitionedPrincipal
9674 ? document->PartitionedPrincipal()
9675 : document->NodePrincipal();
9676
9677 // Don't allow loads in typeContent docShells to inherit the system
9678 // principal from existing documents.
9679 if (inheritedFromCurrent && mItemType == typeContent &&
9680 docPrincipal->IsSystemPrincipal()) {
9681 return nullptr;
9682 }
9683
9684 return docPrincipal;
9685 }
9686
9687 return nullptr;
9688}
9689
9690/* static */ nsresult nsDocShell::CreateRealChannelForDocument(
9691 nsIChannel** aChannel, nsIURI* aURI, nsILoadInfo* aLoadInfo,
9692 nsIInterfaceRequestor* aCallbacks, nsLoadFlags aLoadFlags,
9693 const nsAString& aSrcdoc, nsIURI* aBaseURI) {
9694 nsCOMPtr<nsIChannel> channel;
9695 if (aSrcdoc.IsVoid()) {
9696 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)
9697 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)
9698 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)
9699 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)
;
9700
9701 if (aBaseURI) {
9702 nsCOMPtr<nsIViewSourceChannel> vsc = do_QueryInterface(channel);
9703 if (vsc) {
9704 MOZ_ALWAYS_SUCCEEDS(vsc->SetBaseURI(aBaseURI))do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(vsc->SetBaseURI(aBaseURI))), 1)))), 1))) { } else { do { static_assert
( mozilla::detail::AssertionConditionType<decltype(false)>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(false))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("false" " (" "NS_SUCCEEDED(vsc->SetBaseURI(aBaseURI))" ")"
, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 9704); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "false"
") (" "NS_SUCCEEDED(vsc->SetBaseURI(aBaseURI))" ")"); do {
*((volatile int*)__null) = 9704; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false); } } while (false
)
;
9705 }
9706 }
9707 } else if (SchemeIsViewSource(aURI)) {
9708 // Instantiate view source handler protocol, if it doesn't exist already.
9709 nsCOMPtr<nsIIOService> io(do_GetIOService());
9710 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"
, 9710); AnnotateMozCrashReason("MOZ_ASSERT" "(" "io" ")"); do
{ *((volatile int*)__null) = 9710; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
9711 nsCOMPtr<nsIProtocolHandler> handler;
9712 nsresult rv =
9713 io->GetProtocolHandler("view-source", getter_AddRefs(handler));
9714 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
9715 return rv;
9716 }
9717
9718 nsViewSourceHandler* vsh = nsViewSourceHandler::GetInstance();
9719 if (!vsh) {
9720 return NS_ERROR_FAILURE;
9721 }
9722
9723 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)
9724 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)
;
9725 } else {
9726 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)
9727 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)
9728 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)
;
9729 nsCOMPtr<nsIInputStreamChannel> isc = do_QueryInterface(channel);
9730 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"
, 9730); AnnotateMozCrashReason("MOZ_ASSERT" "(" "isc" ")"); do
{ *((volatile int*)__null) = 9730; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
9731 isc->SetBaseURI(aBaseURI);
9732 }
9733
9734 if (aLoadFlags != nsIRequest::LOAD_NORMAL) {
9735 nsresult rv = channel->SetLoadFlags(aLoadFlags);
9736 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"
, 9736); return rv; } } while (false)
;
9737 }
9738
9739 channel.forget(aChannel);
9740 return NS_OK;
9741}
9742
9743/* static */ bool nsDocShell::CreateAndConfigureRealChannelForLoadState(
9744 BrowsingContext* aBrowsingContext, nsDocShellLoadState* aLoadState,
9745 LoadInfo* aLoadInfo, nsIInterfaceRequestor* aCallbacks,
9746 nsDocShell* aDocShell, const OriginAttributes& aOriginAttributes,
9747 nsLoadFlags aLoadFlags, uint32_t aCacheKey, nsresult& aRv,
9748 nsIChannel** aChannel) {
9749 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"
, 9749); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadInfo" ")"
); do { *((volatile int*)__null) = 9749; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9750
9751 nsString srcdoc = VoidString();
9752 bool isSrcdoc =
9753 aLoadState->HasInternalLoadFlags(INTERNAL_LOAD_FLAGS_IS_SRCDOC);
9754 if (isSrcdoc) {
9755 srcdoc = aLoadState->SrcdocData();
9756 }
9757
9758 aLoadInfo->SetTriggeringRemoteType(
9759 aLoadState->GetEffectiveTriggeringRemoteType());
9760
9761 if (aLoadState->PrincipalToInherit()) {
9762 aLoadInfo->SetPrincipalToInherit(aLoadState->PrincipalToInherit());
9763 }
9764 aLoadInfo->SetLoadTriggeredFromExternal(
9765 aLoadState->HasLoadFlags(LOAD_FLAGS_FROM_EXTERNAL));
9766 aLoadInfo->SetForceAllowDataURI(aLoadState->HasInternalLoadFlags(
9767 INTERNAL_LOAD_FLAGS_FORCE_ALLOW_DATA_URI));
9768 aLoadInfo->SetOriginalFrameSrcLoad(
9769 aLoadState->HasInternalLoadFlags(INTERNAL_LOAD_FLAGS_ORIGINAL_FRAME_SRC));
9770
9771 bool inheritAttrs = false;
9772 if (aLoadState->PrincipalToInherit()) {
9773 inheritAttrs = nsContentUtils::ChannelShouldInheritPrincipal(
9774 aLoadState->PrincipalToInherit(), aLoadState->URI(),
9775 true, // aInheritForAboutBlank
9776 isSrcdoc);
9777 }
9778
9779 // Strip the target query parameters before creating the channel.
9780 aLoadState->MaybeStripTrackerQueryStrings(aBrowsingContext);
9781
9782 OriginAttributes attrs;
9783
9784 // Inherit origin attributes from PrincipalToInherit if inheritAttrs is
9785 // true. Otherwise we just use the origin attributes from docshell.
9786 if (inheritAttrs) {
9787 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"
, 9788); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->PrincipalToInherit()"
") (" "We should have PrincipalToInherit here." ")"); do { *
((volatile int*)__null) = 9788; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
9788 "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"
, 9788); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->PrincipalToInherit()"
") (" "We should have PrincipalToInherit here." ")"); do { *
((volatile int*)__null) = 9788; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
;
9789 attrs = aLoadState->PrincipalToInherit()->OriginAttributesRef();
9790 // If firstPartyIsolation is not enabled, then PrincipalToInherit should
9791 // have the same origin attributes with docshell.
9792 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"
, 9793); AnnotateMozCrashReason("MOZ_ASSERT" "(" "attrs == aOriginAttributes"
")"); do { *((volatile int*)__null) = 9793; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
9793 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"
, 9793); AnnotateMozCrashReason("MOZ_ASSERT" "(" "attrs == aOriginAttributes"
")"); do { *((volatile int*)__null) = 9793; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
9794 } else {
9795 attrs = aOriginAttributes;
9796 attrs.SetFirstPartyDomain(IsTopLevelDoc(aBrowsingContext, aLoadInfo),
9797 aLoadState->URI());
9798 }
9799
9800 aRv = aLoadInfo->SetOriginAttributes(attrs);
9801 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"
, 9801)
) {
9802 return false;
9803 }
9804
9805 if (aLoadState->GetIsFromProcessingFrameAttributes()) {
9806 aLoadInfo->SetIsFromProcessingFrameAttributes();
9807 }
9808
9809 // Propagate the IsFormSubmission flag to the loadInfo.
9810 if (aLoadState->IsFormSubmission()) {
9811 aLoadInfo->SetIsFormSubmission(true);
9812 }
9813
9814 aLoadInfo->SetUnstrippedURI(aLoadState->GetUnstrippedURI());
9815
9816 nsCOMPtr<nsIChannel> channel;
9817 aRv = CreateRealChannelForDocument(getter_AddRefs(channel), aLoadState->URI(),
9818 aLoadInfo, aCallbacks, aLoadFlags, srcdoc,
9819 aLoadState->BaseURI());
9820 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"
, 9820); return false; } } while (false)
;
9821
9822 if (!channel) {
9823 return false;
9824 }
9825
9826 // If the HTTPS-Only mode is enabled, every insecure request gets upgraded to
9827 // HTTPS by default. This behavior can be disabled through the loadinfo flag
9828 // HTTPS_ONLY_EXEMPT.
9829 nsHTTPSOnlyUtils::TestSitePermissionAndPotentiallyAddExemption(channel);
9830
9831 // hack
9832 nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(channel));
9833 nsCOMPtr<nsIHttpChannelInternal> httpChannelInternal(
9834 do_QueryInterface(channel));
9835 nsCOMPtr<nsIURI> referrer;
9836 nsIReferrerInfo* referrerInfo = aLoadState->GetReferrerInfo();
9837 if (referrerInfo) {
9838 referrerInfo->GetOriginalReferrer(getter_AddRefs(referrer));
9839 }
9840 if (httpChannelInternal) {
9841 if (aLoadState->HasInternalLoadFlags(
9842 INTERNAL_LOAD_FLAGS_FORCE_ALLOW_COOKIES)) {
9843 aRv = httpChannelInternal->SetThirdPartyFlags(
9844 nsIHttpChannelInternal::THIRD_PARTY_FORCE_ALLOW);
9845 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"
, 9845); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(aRv)), 1)))"
")"); do { *((volatile int*)__null) = 9845; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9846 }
9847 if (aLoadState->FirstParty()) {
9848 aRv = httpChannelInternal->SetDocumentURI(aLoadState->URI());
9849 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"
, 9849); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(aRv)), 1)))"
")"); do { *((volatile int*)__null) = 9849; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9850 } else {
9851 aRv = httpChannelInternal->SetDocumentURI(referrer);
9852 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"
, 9852); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(aRv)), 1)))"
")"); do { *((volatile int*)__null) = 9852; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9853 }
9854 aRv = httpChannelInternal->SetRedirectMode(
9855 nsIHttpChannelInternal::REDIRECT_MODE_MANUAL);
9856 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"
, 9856); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(aRv)), 1)))"
")"); do { *((volatile int*)__null) = 9856; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9857 }
9858
9859 if (httpChannel) {
9860 if (aLoadState->HeadersStream()) {
9861 aRv = AddHeadersToChannel(aLoadState->HeadersStream(), httpChannel);
9862 }
9863 // Set the referrer explicitly
9864 // Referrer is currenly only set for link clicks here.
9865 if (referrerInfo) {
9866 aRv = httpChannel->SetReferrerInfo(referrerInfo);
9867 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"
, 9867); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(aRv)), 1)))"
")"); do { *((volatile int*)__null) = 9867; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9868 }
9869
9870 // Mark the http channel as UrgentStart for top level document loading in
9871 // active tab.
9872 if (IsUrgentStart(aBrowsingContext, aLoadInfo, aLoadState->LoadType())) {
9873 nsCOMPtr<nsIClassOfService> cos(do_QueryInterface(channel));
9874 if (cos) {
9875 cos->AddClassFlags(nsIClassOfService::UrgentStart);
9876 if (StaticPrefs::dom_document_priority_incremental()) {
9877 cos->SetIncremental(true);
9878 }
9879 }
9880 }
9881 }
9882
9883 channel->SetOriginalURI(aLoadState->OriginalURI() ? aLoadState->OriginalURI()
9884 : aLoadState->URI());
9885
9886 const nsACString& typeHint = aLoadState->TypeHint();
9887 if (!typeHint.IsVoid()) {
9888 channel->SetContentType(typeHint);
9889 }
9890
9891 const nsAString& fileName = aLoadState->FileName();
9892 if (!fileName.IsVoid()) {
9893 aRv = channel->SetContentDisposition(nsIChannel::DISPOSITION_ATTACHMENT);
9894 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"
, 9894); return false; } } while (false)
;
9895 if (!fileName.IsEmpty()) {
9896 aRv = channel->SetContentDispositionFilename(fileName);
9897 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"
, 9897); return false; } } while (false)
;
9898 }
9899 }
9900
9901 if (nsCOMPtr<nsIWritablePropertyBag2> props = do_QueryInterface(channel)) {
9902 nsCOMPtr<nsIURI> referrer;
9903 nsIReferrerInfo* referrerInfo = aLoadState->GetReferrerInfo();
9904 if (referrerInfo) {
9905 referrerInfo->GetOriginalReferrer(getter_AddRefs(referrer));
9906 }
9907 // save true referrer for those who need it (e.g. xpinstall whitelisting)
9908 // Currently only http and ftp channels support this.
9909 props->SetPropertyAsInterface(u"docshell.internalReferrer"_ns, referrer);
9910
9911 if (aLoadState->HasInternalLoadFlags(INTERNAL_LOAD_FLAGS_FIRST_LOAD)) {
9912 props->SetPropertyAsBool(u"docshell.newWindowTarget"_ns, true);
9913 }
9914 }
9915
9916 nsCOMPtr<nsICacheInfoChannel> cacheChannel(do_QueryInterface(channel));
9917 auto loadType = aLoadState->LoadType();
9918
9919 if (loadType == LOAD_RELOAD_NORMAL &&
9920 StaticPrefs::
9921 browser_soft_reload_only_force_validate_top_level_document()) {
9922 nsCOMPtr<nsICacheInfoChannel> cachingChannel = do_QueryInterface(channel);
9923 if (cachingChannel) {
9924 cachingChannel->SetForceValidateCacheContent(true);
9925 }
9926 }
9927
9928 // figure out if we need to set the post data stream on the channel...
9929 if (aLoadState->PostDataStream()) {
9930 if (nsCOMPtr<nsIFormPOSTActionChannel> postChannel =
9931 do_QueryInterface(channel)) {
9932 // XXX it's a bit of a hack to rewind the postdata stream here but
9933 // it has to be done in case the post data is being reused multiple
9934 // times.
9935 nsCOMPtr<nsISeekableStream> postDataSeekable =
9936 do_QueryInterface(aLoadState->PostDataStream());
9937 if (postDataSeekable) {
9938 aRv = postDataSeekable->Seek(nsISeekableStream::NS_SEEK_SET, 0);
9939 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"
, 9939); return false; } } while (false)
;
9940 }
9941
9942 // we really need to have a content type associated with this stream!!
9943 postChannel->SetUploadStream(aLoadState->PostDataStream(), ""_ns, -1);
9944
9945 // Ownership of the stream has transferred to the channel, clear our
9946 // reference.
9947 aLoadState->SetPostDataStream(nullptr);
9948 }
9949
9950 /* If there is a valid postdata *and* it is a History Load,
9951 * set up the cache key on the channel, to retrieve the
9952 * data *only* from the cache. If it is a normal reload, the
9953 * cache is free to go to the server for updated postdata.
9954 */
9955 if (cacheChannel && aCacheKey != 0) {
9956 if (loadType == LOAD_HISTORY || loadType == LOAD_RELOAD_CHARSET_CHANGE) {
9957 cacheChannel->SetCacheKey(aCacheKey);
9958 uint32_t loadFlags;
9959 if (NS_SUCCEEDED(channel->GetLoadFlags(&loadFlags))((bool)(__builtin_expect(!!(!NS_FAILED_impl(channel->GetLoadFlags
(&loadFlags))), 1)))
) {
9960 channel->SetLoadFlags(loadFlags |
9961 nsICachingChannel::LOAD_ONLY_FROM_CACHE);
9962 }
9963 } else if (loadType == LOAD_RELOAD_NORMAL) {
9964 cacheChannel->SetCacheKey(aCacheKey);
9965 }
9966 }
9967 } else {
9968 /* If there is no postdata, set the cache key on the channel, and
9969 * do not set the LOAD_ONLY_FROM_CACHE flag, so that the channel
9970 * will be free to get it from net if it is not found in cache.
9971 * New cache may use it creatively on CGI pages with GET
9972 * method and even on those that say "no-cache"
9973 */
9974 if (loadType == LOAD_HISTORY || loadType == LOAD_RELOAD_NORMAL ||
9975 loadType == LOAD_RELOAD_CHARSET_CHANGE ||
9976 loadType == LOAD_RELOAD_CHARSET_CHANGE_BYPASS_CACHE ||
9977 loadType == LOAD_RELOAD_CHARSET_CHANGE_BYPASS_PROXY_AND_CACHE) {
9978 if (cacheChannel && aCacheKey != 0) {
9979 cacheChannel->SetCacheKey(aCacheKey);
9980 }
9981 }
9982 }
9983
9984 if (nsCOMPtr<nsIScriptChannel> scriptChannel = do_QueryInterface(channel)) {
9985 // Allow execution against our context if the principals match
9986 scriptChannel->SetExecutionPolicy(nsIScriptChannel::EXECUTE_NORMAL);
9987 }
9988
9989 if (nsCOMPtr<nsITimedChannel> timedChannel = do_QueryInterface(channel)) {
9990 timedChannel->SetTimingEnabled(true);
9991
9992 nsString initiatorType;
9993 switch (aLoadInfo->InternalContentPolicyType()) {
9994 case nsIContentPolicy::TYPE_INTERNAL_EMBED:
9995 initiatorType = u"embed"_ns;
9996 break;
9997 case nsIContentPolicy::TYPE_INTERNAL_OBJECT:
9998 initiatorType = u"object"_ns;
9999 break;
10000 default: {
10001 const auto& embedderElementType =
10002 aBrowsingContext->GetEmbedderElementType();
10003 if (embedderElementType) {
10004 initiatorType = *embedderElementType;
10005 }
10006 break;
10007 }
10008 }
10009
10010 if (!initiatorType.IsEmpty()) {
10011 timedChannel->SetInitiatorType(initiatorType);
10012 }
10013 }
10014
10015 nsCOMPtr<nsIURI> rpURI;
10016 aLoadInfo->GetResultPrincipalURI(getter_AddRefs(rpURI));
10017 Maybe<nsCOMPtr<nsIURI>> originalResultPrincipalURI;
10018 aLoadState->GetMaybeResultPrincipalURI(originalResultPrincipalURI);
10019 if (originalResultPrincipalURI &&
10020 (!aLoadState->KeepResultPrincipalURIIfSet() || !rpURI)) {
10021 // Unconditionally override, we want the replay to be equal to what has
10022 // been captured.
10023 aLoadInfo->SetResultPrincipalURI(originalResultPrincipalURI.ref());
10024 }
10025
10026 if (aLoadState->OriginalURI() && aLoadState->LoadReplace()) {
10027 // The LOAD_REPLACE flag and its handling here will be removed as part
10028 // of bug 1319110. For now preserve its restoration here to not break
10029 // any code expecting it being set specially on redirected channels.
10030 // If the flag has originally been set to change result of
10031 // NS_GetFinalChannelURI it won't have any effect and also won't cause
10032 // any harm.
10033 uint32_t loadFlags;
10034 aRv = channel->GetLoadFlags(&loadFlags);
10035 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"
, 10035); return false; } } while (false)
;
10036 channel->SetLoadFlags(loadFlags | nsIChannel::LOAD_REPLACE);
10037 }
10038
10039 nsCOMPtr<nsIContentSecurityPolicy> csp = aLoadState->Csp();
10040 if (csp) {
10041 // Navigational requests that are same origin need to be upgraded in case
10042 // upgrade-insecure-requests is present. Please note that for document
10043 // navigations that bit is re-computed in case we encounter a server
10044 // side redirect so the navigation is not same-origin anymore.
10045 bool upgradeInsecureRequests = false;
10046 csp->GetUpgradeInsecureRequests(&upgradeInsecureRequests);
10047 if (upgradeInsecureRequests) {
10048 // only upgrade if the navigation is same origin
10049 nsCOMPtr<nsIPrincipal> resultPrincipal;
10050 aRv = nsContentUtils::GetSecurityManager()->GetChannelResultPrincipal(
10051 channel, getter_AddRefs(resultPrincipal));
10052 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"
, 10052); return false; } } while (false)
;
10053 if (nsContentSecurityUtils::IsConsideredSameOriginForUIR(
10054 aLoadState->TriggeringPrincipal(), resultPrincipal)) {
10055 aLoadInfo->SetUpgradeInsecureRequests(true);
10056 }
10057 }
10058
10059 // For document loads we store the CSP that potentially needs to
10060 // be inherited by the new document, e.g. in case we are loading
10061 // an opaque origin like a data: URI. The actual inheritance
10062 // check happens within Document::InitCSP().
10063 // Please create an actual copy of the CSP (do not share the same
10064 // reference) otherwise a Meta CSP of an opaque origin will
10065 // incorrectly be propagated to the embedding document.
10066 RefPtr<nsCSPContext> cspToInherit = new nsCSPContext();
10067 cspToInherit->InitFromOther(static_cast<nsCSPContext*>(csp.get()));
10068 aLoadInfo->SetCSPToInherit(cspToInherit);
10069 }
10070
10071 channel.forget(aChannel);
10072 return true;
10073}
10074
10075bool nsDocShell::IsAboutBlankLoadOntoInitialAboutBlank(
10076 nsIURI* aURI, bool aInheritPrincipal, nsIPrincipal* aPrincipalToInherit) {
10077 return NS_IsAboutBlankAllowQueryAndFragment(aURI) && aInheritPrincipal &&
10078 (aPrincipalToInherit == GetInheritedPrincipal(false)) &&
10079 (!mDocumentViewer || !mDocumentViewer->GetDocument() ||
10080 mDocumentViewer->GetDocument()->IsInitialDocument());
10081}
10082
10083nsresult nsDocShell::DoURILoad(nsDocShellLoadState* aLoadState,
10084 Maybe<uint32_t> aCacheKey,
10085 nsIRequest** aRequest) {
10086 // Double-check that we're still around to load this URI.
10087 if (mIsBeingDestroyed) {
10088 // Return NS_OK despite not doing anything to avoid throwing exceptions
10089 // from nsLocation::SetHref if the unload handler of the existing page
10090 // tears us down.
10091 return NS_OK;
10092 }
10093
10094 nsCOMPtr<nsIURILoader> uriLoader = components::URILoader::Service();
10095 if (NS_WARN_IF(!uriLoader)NS_warn_if_impl(!uriLoader, "!uriLoader", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 10095)
) {
10096 return NS_ERROR_UNEXPECTED;
10097 }
10098
10099 // Persist and sync layout history state before we load a new uri, as this
10100 // might be our last chance to do so, in the content process.
10101 PersistLayoutHistoryState();
10102 SynchronizeLayoutHistoryState();
10103
10104 nsresult rv;
10105 nsContentPolicyType contentPolicyType = DetermineContentType();
10106
10107 if (IsSubframe()) {
10108 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"
, 10110); 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) = 10110; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
10109 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"
, 10110); 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) = 10110; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
10110 "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"
, 10110); 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) = 10110; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10111
10112 if (StaticPrefs::dom_block_external_protocol_in_iframes()) {
10113 // Only allow URLs able to return data in iframes.
10114 if (nsContentUtils::IsExternalProtocol(aLoadState->URI())) {
10115 // The context to check user-interaction with for the purposes of
10116 // popup-blocking.
10117 //
10118 // We generally want to check the context that initiated the navigation.
10119 WindowContext* sourceWindowContext = [&] {
10120 const MaybeDiscardedBrowsingContext& sourceBC =
10121 aLoadState->SourceBrowsingContext();
10122 if (!sourceBC.IsNullOrDiscarded()) {
10123 if (WindowContext* wc = sourceBC.get()->GetCurrentWindowContext()) {
10124 return wc;
10125 }
10126 }
10127 return mBrowsingContext->GetParentWindowContext();
10128 }();
10129
10130 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"
, 10130); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sourceWindowContext"
")"); do { *((volatile int*)__null) = 10130; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10131 // FIXME: We can't check user-interaction against an OOP window. This is
10132 // the next best thing we can really do. The load state keeps whether
10133 // the navigation had a user interaction in process
10134 // (aLoadState->HasValidUserGestureActivation()), but we can't really
10135 // consume it, which we want to prevent popup-spamming from the same
10136 // click event.
10137 WindowContext* context =
10138 sourceWindowContext->IsInProcess()
10139 ? sourceWindowContext
10140 : mBrowsingContext->GetCurrentWindowContext();
10141 const bool popupBlocked = [&] {
10142 const bool active = mBrowsingContext->IsActive();
10143
10144 // For same-origin-with-top windows, we grant a single free popup
10145 // without user activation, see bug 1680721.
10146 //
10147 // We consume the flag now even if there's no user activation.
10148 const bool hasFreePass = [&] {
10149 if (!active ||
10150 !(context->IsInProcess() && context->SameOriginWithTop())) {
10151 return false;
10152 }
10153 nsGlobalWindowInner* win =
10154 context->TopWindowContext()->GetInnerWindow();
10155 return win && win->TryOpenExternalProtocolIframe();
10156 }();
10157
10158 if (context->IsInProcess() &&
10159 context->ConsumeTransientUserGestureActivation()) {
10160 // If the user has interacted with the page, consume it.
10161 return false;
10162 }
10163
10164 // TODO(emilio): Can we remove this check? It seems like what prompted
10165 // this code (bug 1514547) should be covered by transient user
10166 // activation, see bug 1514547.
10167 if (active &&
10168 PopupBlocker::ConsumeTimerTokenForExternalProtocolIframe()) {
10169 return false;
10170 }
10171
10172 if (sourceWindowContext->CanShowPopup()) {
10173 return false;
10174 }
10175
10176 if (hasFreePass) {
10177 return false;
10178 }
10179
10180 return true;
10181 }();
10182
10183 // No error must be returned when iframes are blocked.
10184 if (popupBlocked) {
10185 nsAutoString message;
10186 nsresult rv = nsContentUtils::GetLocalizedString(
10187 nsContentUtils::eDOM_PROPERTIES,
10188 "ExternalProtocolFrameBlockedNoUserActivation", message);
10189 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
10190 nsContentUtils::ReportToConsoleByWindowID(
10191 message, nsIScriptError::warningFlag, "DOM"_ns,
10192 context->InnerWindowId());
10193 }
10194 return NS_OK;
10195 }
10196 }
10197 }
10198
10199 // Only allow view-source scheme in top-level docshells. view-source is
10200 // the only scheme to which this applies at the moment due to potential
10201 // timing attacks to read data from cross-origin iframes. If this widens
10202 // we should add a protocol flag for whether the scheme is allowed in
10203 // frames and use something like nsNetUtil::NS_URIChainHasFlags.
10204 nsCOMPtr<nsIURI> tempURI = aLoadState->URI();
10205 nsCOMPtr<nsINestedURI> nestedURI = do_QueryInterface(tempURI);
10206 while (nestedURI) {
10207 // view-source should always be an nsINestedURI, loop and check the
10208 // scheme on this and all inner URIs that are also nested URIs.
10209 if (SchemeIsViewSource(tempURI)) {
10210 return NS_ERROR_UNKNOWN_PROTOCOL;
10211 }
10212 nestedURI->GetInnerURI(getter_AddRefs(tempURI));
10213 nestedURI = do_QueryInterface(tempURI);
10214 }
10215 } else {
10216 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"
, 10217); AnnotateMozCrashReason("MOZ_ASSERT" "(" "contentPolicyType == nsIContentPolicy::TYPE_DOCUMENT"
") (" "DoURILoad thinks this is a document and InternalLoad does not"
")"); do { *((volatile int*)__null) = 10217; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
10217 "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"
, 10217); AnnotateMozCrashReason("MOZ_ASSERT" "(" "contentPolicyType == nsIContentPolicy::TYPE_DOCUMENT"
") (" "DoURILoad thinks this is a document and InternalLoad does not"
")"); do { *((volatile int*)__null) = 10217; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10218 }
10219
10220 // We want to inherit aLoadState->PrincipalToInherit() when:
10221 // 1. ChannelShouldInheritPrincipal returns true.
10222 // 2. aLoadState->URI() is not data: URI, or data: URI is not
10223 // configured as unique opaque origin.
10224 bool inheritPrincipal = false;
10225
10226 if (aLoadState->PrincipalToInherit()) {
10227 bool isSrcdoc =
10228 aLoadState->HasInternalLoadFlags(INTERNAL_LOAD_FLAGS_IS_SRCDOC);
10229 bool inheritAttrs = nsContentUtils::ChannelShouldInheritPrincipal(
10230 aLoadState->PrincipalToInherit(), aLoadState->URI(),
10231 true, // aInheritForAboutBlank
10232 isSrcdoc);
10233
10234 inheritPrincipal = inheritAttrs && !SchemeIsData(aLoadState->URI());
10235 }
10236
10237 // See https://bugzilla.mozilla.org/show_bug.cgi?id=1736570
10238 const bool isAboutBlankLoadOntoInitialAboutBlank =
10239 IsAboutBlankLoadOntoInitialAboutBlank(aLoadState->URI(), inheritPrincipal,
10240 aLoadState->PrincipalToInherit());
10241
10242 // FIXME We still have a ton of codepaths that don't pass through
10243 // DocumentLoadListener, so probably need to create session history info
10244 // in more places.
10245 if (aLoadState->GetLoadingSessionHistoryInfo()) {
10246 SetLoadingSessionHistoryInfo(*aLoadState->GetLoadingSessionHistoryInfo());
10247 } else if (isAboutBlankLoadOntoInitialAboutBlank &&
10248 mozilla::SessionHistoryInParent()) {
10249 // Materialize LoadingSessionHistoryInfo here, because DocumentChannel
10250 // loads have it, and later history behavior depends on it existing.
10251 UniquePtr<SessionHistoryInfo> entry = MakeUnique<SessionHistoryInfo>(
10252 aLoadState->URI(), aLoadState->TriggeringPrincipal(),
10253 aLoadState->PrincipalToInherit(),
10254 aLoadState->PartitionedPrincipalToInherit(), aLoadState->Csp(),
10255 mContentTypeHint);
10256 mozilla::dom::LoadingSessionHistoryInfo info(*entry);
10257 SetLoadingSessionHistoryInfo(info, true);
10258 }
10259
10260 // open a channel for the url
10261
10262 // If we have a pending channel, use the channel we've already created here.
10263 // We don't need to set up load flags for our channel, as it has already been
10264 // created.
10265
10266 if (nsCOMPtr<nsIChannel> channel =
10267 aLoadState->GetPendingRedirectedChannel()) {
10268 // If we have a request outparameter, shove our channel into it.
10269 if (aRequest) {
10270 nsCOMPtr<nsIRequest> outRequest = channel;
10271 outRequest.forget(aRequest);
10272 }
10273
10274 return OpenRedirectedChannel(aLoadState);
10275 }
10276
10277 // There are two cases we care about:
10278 // * Top-level load: In this case, loadingNode is null, but loadingWindow
10279 // is our mScriptGlobal. We pass null for loadingPrincipal in this case.
10280 // * Subframe load: loadingWindow is null, but loadingNode is the frame
10281 // element for the load. loadingPrincipal is the NodePrincipal of the
10282 // frame element.
10283 nsCOMPtr<nsINode> loadingNode;
10284 nsCOMPtr<nsPIDOMWindowOuter> loadingWindow;
10285 nsCOMPtr<nsIPrincipal> loadingPrincipal;
10286 nsCOMPtr<nsISupports> topLevelLoadingContext;
10287
10288 if (contentPolicyType == nsIContentPolicy::TYPE_DOCUMENT) {
10289 loadingNode = nullptr;
10290 loadingPrincipal = nullptr;
10291 loadingWindow = mScriptGlobal;
10292 if (XRE_IsContentProcess()) {
10293 // In e10s the child process doesn't have access to the element that
10294 // contains the browsing context (because that element is in the chrome
10295 // process).
10296 nsCOMPtr<nsIBrowserChild> browserChild = GetBrowserChild();
10297 topLevelLoadingContext = ToSupports(browserChild);
10298 } else {
10299 // This is for loading non-e10s tabs and toplevel windows of various
10300 // sorts.
10301 // For the toplevel window cases, requestingElement will be null.
10302 nsCOMPtr<Element> requestingElement =
10303 loadingWindow->GetFrameElementInternal();
10304 topLevelLoadingContext = requestingElement;
10305 }
10306 } else {
10307 loadingWindow = nullptr;
10308 loadingNode = mScriptGlobal->GetFrameElementInternal();
10309 if (loadingNode) {
10310 // If we have a loading node, then use that as our loadingPrincipal.
10311 loadingPrincipal = loadingNode->NodePrincipal();
10312#ifdef DEBUG1
10313 // Get the docshell type for requestingElement.
10314 RefPtr<Document> requestingDoc = loadingNode->OwnerDoc();
10315 nsCOMPtr<nsIDocShell> elementDocShell = requestingDoc->GetDocShell();
10316 // requestingElement docshell type = current docshell type.
10317 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"
, 10319); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mItemType == elementDocShell->ItemType()"
") (" "subframes should have the same docshell type as their parent"
")"); do { *((volatile int*)__null) = 10319; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
10318 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"
, 10319); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mItemType == elementDocShell->ItemType()"
") (" "subframes should have the same docshell type as their parent"
")"); do { *((volatile int*)__null) = 10319; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
10319 "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"
, 10319); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mItemType == elementDocShell->ItemType()"
") (" "subframes should have the same docshell type as their parent"
")"); do { *((volatile int*)__null) = 10319; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10320#endif
10321 } else {
10322 if (mIsBeingDestroyed) {
10323 // If this isn't a top-level load and mScriptGlobal's frame element is
10324 // null, then the element got removed from the DOM while we were trying
10325 // to load this resource. This docshell is scheduled for destruction
10326 // already, so bail out here.
10327 return NS_OK;
10328 }
10329 // If we are not being destroyed and we do not have access to the loading
10330 // node, then we are a remote subframe. Set the loading principal
10331 // to be a null principal and then set it correctly in the parent.
10332 loadingPrincipal = NullPrincipal::Create(GetOriginAttributes(), nullptr);
10333 }
10334 }
10335
10336 if (!aLoadState->TriggeringPrincipal()) {
10337 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"
, 10337); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"DoURILoad needs a valid triggeringPrincipal" ")"); do { *((
volatile int*)__null) = 10337; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
;
10338 return NS_ERROR_FAILURE;
10339 }
10340
10341 uint32_t sandboxFlags = mBrowsingContext->GetSandboxFlags();
10342 nsSecurityFlags securityFlags =
10343 nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_SEC_CONTEXT_IS_NULL;
10344
10345 if (mLoadType == LOAD_ERROR_PAGE) {
10346 securityFlags |= nsILoadInfo::SEC_LOAD_ERROR_PAGE;
10347 }
10348
10349 if (inheritPrincipal) {
10350 securityFlags |= nsILoadInfo::SEC_FORCE_INHERIT_PRINCIPAL;
10351 }
10352
10353 // Must never have a parent for TYPE_DOCUMENT loads
10354 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"
, 10355); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mBrowsingContext->GetParent()"
")"); do { *((volatile int*)__null) = 10355; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false); } } while
(false)
10355 !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"
, 10355); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mBrowsingContext->GetParent()"
")"); do { *((volatile int*)__null) = 10355; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false); } } while
(false)
;
10356 // Subdocuments must have a parent
10357 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"
, 10358); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mBrowsingContext->GetParent()"
")"); do { *((volatile int*)__null) = 10358; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false); } } while
(false)
10358 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"
, 10358); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mBrowsingContext->GetParent()"
")"); do { *((volatile int*)__null) = 10358; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false); } } while
(false)
;
10359 mBrowsingContext->SetTriggeringAndInheritPrincipals(
10360 aLoadState->TriggeringPrincipal(), aLoadState->PrincipalToInherit(),
10361 aLoadState->GetLoadIdentifier());
10362 RefPtr<LoadInfo> loadInfo =
10363 (contentPolicyType == nsIContentPolicy::TYPE_DOCUMENT)
10364 ? new LoadInfo(loadingWindow, aLoadState->URI(),
10365 aLoadState->TriggeringPrincipal(),
10366 topLevelLoadingContext, securityFlags, sandboxFlags)
10367 : new LoadInfo(loadingPrincipal, aLoadState->TriggeringPrincipal(),
10368 loadingNode, securityFlags, contentPolicyType,
10369 Maybe<mozilla::dom::ClientInfo>(),
10370 Maybe<mozilla::dom::ServiceWorkerDescriptor>(),
10371 sandboxFlags);
10372 RefPtr<WindowContext> context = mBrowsingContext->GetCurrentWindowContext();
10373
10374 if (isAboutBlankLoadOntoInitialAboutBlank) {
10375 // Match the DocumentChannel case where the default for third-partiness
10376 // differs from the default in LoadInfo construction here.
10377 // toolkit/components/antitracking/test/browser/browser_aboutblank.js
10378 // fails without this.
10379 BrowsingContext* top = mBrowsingContext->Top();
10380 if (top == mBrowsingContext) {
10381 // If we're at the top, this must be a window.open()ed
10382 // window, and we can't be third-party relative to ourselves.
10383 loadInfo->SetIsThirdPartyContextToTopWindow(false);
10384 } else {
10385 if (Document* topDoc = top->GetDocument()) {
10386 bool thirdParty = false;
10387 mozilla::Unused << topDoc->GetPrincipal()->IsThirdPartyPrincipal(
10388 aLoadState->PrincipalToInherit(), &thirdParty);
10389 loadInfo->SetIsThirdPartyContextToTopWindow(thirdParty);
10390 } else {
10391 // If top is in a different process, we have to be third-party relative
10392 // to it.
10393 loadInfo->SetIsThirdPartyContextToTopWindow(true);
10394 }
10395 }
10396 }
10397
10398 if (mLoadType != LOAD_ERROR_PAGE && context && context->IsInProcess()) {
10399 if (context->HasValidTransientUserGestureActivation()) {
10400 aLoadState->SetHasValidUserGestureActivation(true);
10401 aLoadState->SetTextDirectiveUserActivation(true);
10402 }
10403 if (!aLoadState->TriggeringWindowId()) {
10404 aLoadState->SetTriggeringWindowId(context->Id());
10405 }
10406 if (!aLoadState->TriggeringStorageAccess()) {
10407 Document* contextDoc = context->GetExtantDoc();
10408 if (contextDoc) {
10409 aLoadState->SetTriggeringStorageAccess(
10410 contextDoc->UsingStorageAccess());
10411 }
10412 }
10413 }
10414
10415 // in case this docshell load was triggered by a valid transient user gesture,
10416 // or also the load originates from external, then we pass that information on
10417 // to the loadinfo, which allows e.g. setting Sec-Fetch-User request headers.
10418 if (aLoadState->HasValidUserGestureActivation() ||
10419 aLoadState->HasLoadFlags(LOAD_FLAGS_FROM_EXTERNAL)) {
10420 loadInfo->SetHasValidUserGestureActivation(true);
10421 aLoadState->SetTextDirectiveUserActivation(true);
10422 }
10423
10424 loadInfo->SetTextDirectiveUserActivation(
10425 aLoadState->GetTextDirectiveUserActivation());
10426
10427 loadInfo->SetTriggeringWindowId(aLoadState->TriggeringWindowId());
10428 loadInfo->SetTriggeringStorageAccess(aLoadState->TriggeringStorageAccess());
10429 loadInfo->SetTriggeringSandboxFlags(aLoadState->TriggeringSandboxFlags());
10430 loadInfo->SetIsMetaRefresh(aLoadState->IsMetaRefresh());
10431
10432 uint32_t cacheKey = 0;
10433 if (aCacheKey) {
10434 cacheKey = *aCacheKey;
10435 } else if (mozilla::SessionHistoryInParent()) {
10436 if (mLoadingEntry) {
10437 cacheKey = mLoadingEntry->mInfo.GetCacheKey();
10438 } else if (mActiveEntry) { // for reload cases
10439 cacheKey = mActiveEntry->GetCacheKey();
10440 }
10441 } else {
10442 if (mLSHE) {
10443 cacheKey = mLSHE->GetCacheKey();
10444 } else if (mOSHE) { // for reload cases
10445 cacheKey = mOSHE->GetCacheKey();
10446 }
10447 }
10448
10449 bool uriModified;
10450 if (mLSHE || mLoadingEntry) {
10451 if (mLoadingEntry) {
10452 uriModified = mLoadingEntry->mInfo.GetURIWasModified();
10453 } else {
10454 uriModified = mLSHE->GetURIWasModified();
10455 }
10456 } else {
10457 uriModified = false;
10458 }
10459
10460 bool isEmbeddingBlockedError = false;
10461 if (mFailedChannel) {
10462 nsresult status;
10463 mFailedChannel->GetStatus(&status);
10464 isEmbeddingBlockedError = status == NS_ERROR_XFO_VIOLATION ||
10465 status == NS_ERROR_CSP_FRAME_ANCESTOR_VIOLATION;
10466 }
10467
10468 nsLoadFlags loadFlags = aLoadState->CalculateChannelLoadFlags(
10469 mBrowsingContext, Some(uriModified), Some(isEmbeddingBlockedError));
10470
10471 nsCOMPtr<nsIChannel> channel;
10472 if (DocumentChannel::CanUseDocumentChannel(aLoadState->URI()) &&
10473 !isAboutBlankLoadOntoInitialAboutBlank) {
10474 channel = DocumentChannel::CreateForDocument(
10475 aLoadState, loadInfo, loadFlags, this, cacheKey, uriModified,
10476 isEmbeddingBlockedError);
10477 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"
, 10477); AnnotateMozCrashReason("MOZ_ASSERT" "(" "channel" ")"
); do { *((volatile int*)__null) = 10477; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
10478
10479 // Disable keyword fixup when using DocumentChannel, since
10480 // DocumentLoadListener will handle this for us (in the parent process).
10481 mAllowKeywordFixup = false;
10482 } else if (!CreateAndConfigureRealChannelForLoadState(
10483 mBrowsingContext, aLoadState, loadInfo, this, this,
10484 GetOriginAttributes(), loadFlags, cacheKey, rv,
10485 getter_AddRefs(channel))) {
10486 return rv;
10487 }
10488
10489 // Make sure to give the caller a channel if we managed to create one
10490 // This is important for correct error page/session history interaction
10491 if (aRequest) {
10492 NS_ADDREF(*aRequest = channel)(*aRequest = channel)->AddRef();
10493 }
10494
10495 const nsACString& typeHint = aLoadState->TypeHint();
10496 if (!typeHint.IsVoid()) {
10497 mContentTypeHint = typeHint;
10498 } else {
10499 mContentTypeHint.Truncate();
10500 }
10501
10502 // Load attributes depend on load type...
10503 if (mLoadType == LOAD_RELOAD_CHARSET_CHANGE) {
10504 // Use SetAllowStaleCacheContent (not LOAD_FROM_CACHE flag) since we
10505 // only want to force cache load for this channel, not the whole
10506 // loadGroup.
10507 nsCOMPtr<nsICacheInfoChannel> cachingChannel = do_QueryInterface(channel);
10508 if (cachingChannel) {
10509 cachingChannel->SetAllowStaleCacheContent(true);
10510 }
10511 }
10512
10513 uint32_t openFlags =
10514 nsDocShell::ComputeURILoaderFlags(mBrowsingContext, mLoadType);
10515 return OpenInitializedChannel(channel, uriLoader, openFlags);
10516}
10517
10518static nsresult AppendSegmentToString(nsIInputStream* aIn, void* aClosure,
10519 const char* aFromRawSegment,
10520 uint32_t aToOffset, uint32_t aCount,
10521 uint32_t* aWriteCount) {
10522 // aFromSegment now contains aCount bytes of data.
10523
10524 nsAutoCString* buf = static_cast<nsAutoCString*>(aClosure);
10525 buf->Append(aFromRawSegment, aCount);
10526
10527 // Indicate that we have consumed all of aFromSegment
10528 *aWriteCount = aCount;
10529 return NS_OK;
10530}
10531
10532/* static */ nsresult nsDocShell::AddHeadersToChannel(
10533 nsIInputStream* aHeadersData, nsIChannel* aGenericChannel) {
10534 nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(aGenericChannel);
10535 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"
, 10535); return NS_ERROR_UNEXPECTED; } } while (false)
;
10536
10537 uint32_t numRead;
10538 nsAutoCString headersString;
10539 nsresult rv = aHeadersData->ReadSegments(
10540 AppendSegmentToString, &headersString, UINT32_MAX(4294967295U), &numRead);
10541 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"
, 10541); return rv; } } while (false)
;
10542
10543 // used during the manipulation of the String from the InputStream
10544 nsAutoCString headerName;
10545 nsAutoCString headerValue;
10546 int32_t crlf;
10547 int32_t colon;
10548
10549 //
10550 // Iterate over the headersString: for each "\r\n" delimited chunk,
10551 // add the value as a header to the nsIHttpChannel
10552 //
10553
10554 static const char kWhitespace[] = "\b\t\r\n ";
10555 while (true) {
10556 crlf = headersString.Find("\r\n");
10557 if (crlf == kNotFound) {
10558 return NS_OK;
10559 }
10560
10561 const nsACString& oneHeader = StringHead(headersString, crlf);
10562
10563 colon = oneHeader.FindChar(':');
10564 if (colon == kNotFound) {
10565 return NS_ERROR_UNEXPECTED;
10566 }
10567
10568 headerName = StringHead(oneHeader, colon);
10569 headerValue = Substring(oneHeader, colon + 1);
10570
10571 headerName.Trim(kWhitespace);
10572 headerValue.Trim(kWhitespace);
10573
10574 headersString.Cut(0, crlf + 2);
10575
10576 //
10577 // FINALLY: we can set the header!
10578 //
10579
10580 rv = httpChannel->SetRequestHeader(headerName, headerValue, true);
10581 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"
, 10581); return rv; } } while (false)
;
10582 }
10583
10584 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"
, 10584); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "oops" ")"); do { *((volatile int
*)__null) = 10584; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
10585 return NS_ERROR_UNEXPECTED;
10586}
10587
10588/* static */ uint32_t nsDocShell::ComputeURILoaderFlags(
10589 BrowsingContext* aBrowsingContext, uint32_t aLoadType,
10590 bool aIsDocumentLoad) {
10591 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"
, 10591); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aBrowsingContext"
")"); do { *((volatile int*)__null) = 10591; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10592
10593 uint32_t openFlags = 0;
10594 if (aLoadType == LOAD_LINK) {
10595 openFlags |= nsIURILoader::IS_CONTENT_PREFERRED;
10596 }
10597 if (!aBrowsingContext->GetAllowContentRetargeting()) {
10598 openFlags |= nsIURILoader::DONT_RETARGET;
10599 }
10600
10601 // Unless the pref is set, object/embed loads always specify DONT_RETARGET.
10602 // See bug 1868001 for details.
10603 if (!aIsDocumentLoad &&
10604 !StaticPrefs::dom_navigation_object_embed_allow_retargeting()) {
10605 openFlags |= nsIURILoader::DONT_RETARGET;
10606 }
10607
10608 return openFlags;
10609}
10610
10611nsresult nsDocShell::OpenInitializedChannel(nsIChannel* aChannel,
10612 nsIURILoader* aURILoader,
10613 uint32_t aOpenFlags) {
10614 nsresult rv = NS_OK;
10615
10616 // If anything fails here, make sure to clear our initial ClientSource.
10617 auto cleanupInitialClient =
10618 MakeScopeExit([&] { mInitialClientSource.reset(); });
10619
10620 nsCOMPtr<nsPIDOMWindowOuter> win = GetWindow();
10621 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"
, 10621); return NS_ERROR_FAILURE; } } while (false)
;
10622
10623 MaybeCreateInitialClientSource();
10624
10625 // Let the client channel helper know if we are using DocumentChannel,
10626 // since redirects get handled in the parent process in that case.
10627 RefPtr<net::DocumentChannel> docChannel = do_QueryObject(aChannel);
10628 if (docChannel && XRE_IsContentProcess()) {
10629 // Tell the content process nsDocumentOpenInfo to not try to do
10630 // any sort of targeting.
10631 aOpenFlags |= nsIURILoader::DONT_RETARGET;
10632 }
10633
10634 // Since we are loading a document we need to make sure the proper reserved
10635 // and initial client data is stored on the nsILoadInfo. The
10636 // ClientChannelHelper does this and ensures that it is propagated properly
10637 // on redirects. We pass no reserved client here so that the helper will
10638 // create the reserved ClientSource if necessary.
10639 Maybe<ClientInfo> noReservedClient;
10640 if (docChannel) {
10641 // When using DocumentChannel, all redirect handling is done in the parent,
10642 // so we just need the child variant to watch for the internal redirect
10643 // to the final channel.
10644 rv = AddClientChannelHelperInChild(aChannel,
10645 GetMainThreadSerialEventTarget());
10646 docChannel->SetInitialClientInfo(GetInitialClientInfo());
10647 } else {
10648 rv = AddClientChannelHelper(aChannel, std::move(noReservedClient),
10649 GetInitialClientInfo(),
10650 GetMainThreadSerialEventTarget());
10651 }
10652 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"
, 10652); return rv; } } while (false)
;
10653
10654 rv = aURILoader->OpenURI(aChannel, aOpenFlags, this);
10655 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"
, 10655); return rv; } } while (false)
;
10656
10657 // We're about to load a new page and it may take time before necko
10658 // gives back any data, so main thread might have a chance to process a
10659 // collector slice
10660 nsJSContext::MaybeRunNextCollectorSlice(this, JS::GCReason::DOCSHELL);
10661
10662 // Success. Keep the initial ClientSource if it exists.
10663 cleanupInitialClient.release();
10664
10665 return NS_OK;
10666}
10667
10668nsresult nsDocShell::OpenRedirectedChannel(nsDocShellLoadState* aLoadState) {
10669 nsCOMPtr<nsIChannel> channel = aLoadState->GetPendingRedirectedChannel();
10670 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"
, 10670); AnnotateMozCrashReason("MOZ_ASSERT" "(" "channel" ")"
); do { *((volatile int*)__null) = 10670; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
10671
10672 // If anything fails here, make sure to clear our initial ClientSource.
10673 auto cleanupInitialClient =
10674 MakeScopeExit([&] { mInitialClientSource.reset(); });
10675
10676 nsCOMPtr<nsPIDOMWindowOuter> win = GetWindow();
10677 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"
, 10677); return NS_ERROR_FAILURE; } } while (false)
;
10678
10679 MaybeCreateInitialClientSource();
10680
10681 nsCOMPtr<nsILoadInfo> loadInfo = channel->LoadInfo();
10682
10683 LoadInfo* li = static_cast<LoadInfo*>(loadInfo.get());
10684 if (loadInfo->GetExternalContentPolicyType() ==
10685 ExtContentPolicy::TYPE_DOCUMENT) {
10686 li->UpdateBrowsingContextID(mBrowsingContext->Id());
10687 } else if (loadInfo->GetExternalContentPolicyType() ==
10688 ExtContentPolicy::TYPE_SUBDOCUMENT) {
10689 li->UpdateFrameBrowsingContextID(mBrowsingContext->Id());
10690 }
10691
10692 // If we did a process switch, then we should have an existing allocated
10693 // ClientInfo, so we just need to allocate a corresponding ClientSource.
10694 CreateReservedSourceIfNeeded(channel, GetMainThreadSerialEventTarget());
10695
10696 RefPtr<nsDocumentOpenInfo> loader =
10697 new nsDocumentOpenInfo(this, nsIURILoader::DONT_RETARGET, nullptr);
10698 channel->SetLoadGroup(mLoadGroup);
10699
10700 MOZ_ALWAYS_SUCCEEDS(loader->Prepare())do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(loader->Prepare())), 1)))), 1))) { } else { do { static_assert
( mozilla::detail::AssertionConditionType<decltype(false)>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(false))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("false" " (" "NS_SUCCEEDED(loader->Prepare())" ")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 10700); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "false"
") (" "NS_SUCCEEDED(loader->Prepare())" ")"); do { *((volatile
int*)__null) = 10700; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false); } } while (false)
;
10701
10702 nsresult rv = NS_OK;
10703 if (XRE_IsParentProcess()) {
10704 // If we're in the parent, the we don't have an nsIChildChannel, just
10705 // the original channel, which is already open in this process.
10706
10707 // DocumentLoadListener expects to get an nsIParentChannel, so
10708 // we create a wrapper around the channel and nsIStreamListener
10709 // that forwards functionality as needed, and then we register
10710 // it under the provided identifier.
10711 RefPtr<ParentChannelWrapper> wrapper =
10712 new ParentChannelWrapper(channel, loader);
10713 wrapper->Register(aLoadState->GetPendingRedirectChannelRegistrarId());
10714
10715 mLoadGroup->AddRequest(channel, nullptr);
10716 } else if (nsCOMPtr<nsIChildChannel> childChannel =
10717 do_QueryInterface(channel)) {
10718 // Our channel was redirected from another process, so doesn't need to
10719 // be opened again. However, it does need its listener hooked up
10720 // correctly.
10721 rv = childChannel->CompleteRedirectSetup(loader);
10722 } else {
10723 // It's possible for the redirected channel to not implement
10724 // nsIChildChannel and be entirely local (like srcdoc). In that case we
10725 // can just open the local instance and it will work.
10726 rv = channel->AsyncOpen(loader);
10727 }
10728 if (rv == NS_ERROR_NO_CONTENT) {
10729 return NS_OK;
10730 }
10731 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"
, 10731); return rv; } } while (false)
;
10732
10733 // Success. Keep the initial ClientSource if it exists.
10734 cleanupInitialClient.release();
10735 return NS_OK;
10736}
10737
10738// https://html.spec.whatwg.org/#scrolling-to-a-fragment
10739nsresult nsDocShell::ScrollToAnchor(bool aCurHasRef, bool aNewHasRef,
10740 nsACString& aNewHash, uint32_t aLoadType) {
10741 if (!mCurrentURI) {
10742 return NS_OK;
10743 }
10744
10745 RefPtr<PresShell> presShell = GetPresShell();
10746 if (!presShell) {
10747 // If we failed to get the shell, or if there is no shell,
10748 // nothing left to do here.
10749 return NS_OK;
10750 }
10751
10752 ScrollContainerFrame* rootScroll = presShell->GetRootScrollContainerFrame();
10753 if (rootScroll) {
10754 rootScroll->ClearDidHistoryRestore();
10755 }
10756
10757 // If it's a load from history, we don't have any anchor jumping to do.
10758 // Scrollbar position will be restored by the caller based on positions stored
10759 // in session history.
10760 bool scroll = aLoadType != LOAD_HISTORY && aLoadType != LOAD_RELOAD_NORMAL;
10761 // If the load contains text directives, try to apply them. This may fail if
10762 // the load is a same-document load that was initiated before the document was
10763 // fully loaded and the target is not yet included in the DOM tree.
10764 // For this case, the `uninvokedTextDirectives` are not cleared, so that
10765 // `Document::ScrollToRef()` can re-apply the text directive.
10766 // `Document::ScrollToRef()` is (presumably) the second "async" call mentioned
10767 // in sec. 7.4.2.3.3 in the HTML spec, "Fragment navigations":
10768 // https://html.spec.whatwg.org/#scroll-to-fragid:~:text=This%20algorithm%20will%20be%20called%20twice
10769
10770 const RefPtr fragmentDirective = GetDocument()->FragmentDirective();
10771 const nsTArray<RefPtr<nsRange>> textDirectiveRanges =
10772 fragmentDirective->FindTextFragmentsInDocument();
10773 fragmentDirective->HighlightTextDirectives(textDirectiveRanges);
10774 const bool scrollToTextDirective =
10775 !textDirectiveRanges.IsEmpty() &&
10776 fragmentDirective->IsTextDirectiveAllowedToBeScrolledTo();
10777 const RefPtr<nsRange> textDirectiveToScroll =
10778 scrollToTextDirective ? textDirectiveRanges[0] : nullptr;
10779
10780 // If we have no new anchor, we do not want to scroll, unless there is a
10781 // current anchor and we are doing a history load. So return if we have no
10782 // new anchor, and there is no current anchor or the load is not a history
10783 // load.
10784 if ((!aCurHasRef || aLoadType != LOAD_HISTORY) && !aNewHasRef &&
10785 !scrollToTextDirective) {
10786 return NS_OK;
10787 }
10788
10789 // Both the new and current URIs refer to the same page. We can now
10790 // browse to the hash stored in the new URI.
10791
10792 if (aNewHash.IsEmpty() && !scrollToTextDirective) {
10793 // 2. If fragment is the empty string, then return the special value top of
10794 // the document.
10795 //
10796 // Tell the shell it's at an anchor without scrolling.
10797 presShell->GoToAnchor(u""_ns, nullptr, false);
10798
10799 if (scroll) {
10800 // Scroll to the top of the page. Ignore the return value; failure to
10801 // scroll here (e.g. if there is no root scrollframe) is not grounds for
10802 // canceling the load!
10803 SetCurScrollPosEx(0, 0);
10804 }
10805
10806 return NS_OK;
10807 }
10808
10809 // 3. Let potentialIndicatedElement be the result of finding a potential
10810 // indicated element given document and fragment.
10811 NS_ConvertUTF8toUTF16 uStr(aNewHash);
10812
10813 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"
, 10813); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!uStr.IsEmpty() || scrollToTextDirective"
")"); do { *((volatile int*)__null) = 10813; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10814
10815 auto rv = presShell->GoToAnchor(uStr, textDirectiveToScroll, scroll,
10816 ScrollFlags::ScrollSmoothAuto);
10817
10818 // 4. If potentialIndicatedElement is not null, then return
10819 // potentialIndicatedElement.
10820 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
10821 return NS_OK;
10822 }
10823
10824 // 5. Let fragmentBytes be the result of percent-decoding fragment.
10825 nsAutoCString fragmentBytes;
10826 const bool unescaped = NS_UnescapeURL(aNewHash.Data(), aNewHash.Length(),
10827 /* aFlags = */ 0, fragmentBytes);
10828
10829 if (!unescaped) {
10830 // Another attempt is only necessary if characters were unescaped.
10831 return NS_OK;
10832 }
10833
10834 if (fragmentBytes.IsEmpty()) {
10835 // When aNewHash contains "%00", the unescaped string may be empty, and
10836 // GoToAnchor asserts if we ask it to scroll to an empty ref.
10837 presShell->GoToAnchor(u""_ns, nullptr, false);
10838 return NS_OK;
10839 }
10840
10841 // 6. Let decodedFragment be the result of running UTF-8 decode without BOM on
10842 // fragmentBytes.
10843 nsAutoString decodedFragment;
10844 rv = UTF_8_ENCODING->DecodeWithoutBOMHandling(fragmentBytes, decodedFragment);
10845 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"
, 10845); return rv; } } while (false)
;
10846
10847 // 7. Set potentialIndicatedElement to the result of finding a potential
10848 // indicated element given document and decodedFragment.
10849 //
10850 // Ignore the return value of GoToAnchor, since it will return an error if
10851 // there is no such anchor in the document, which is actually a success
10852 // condition for us (we want to update the session history with the new URI no
10853 // matter whether we actually scrolled somewhere).
10854 presShell->GoToAnchor(decodedFragment, nullptr, scroll,
10855 ScrollFlags::ScrollSmoothAuto);
10856
10857 return NS_OK;
10858}
10859
10860bool nsDocShell::OnNewURI(nsIURI* aURI, nsIChannel* aChannel,
10861 nsIPrincipal* aTriggeringPrincipal,
10862 nsIPrincipal* aPrincipalToInherit,
10863 nsIPrincipal* aPartitionedPrincipalToInherit,
10864 nsIContentSecurityPolicy* aCsp,
10865 bool aAddToGlobalHistory, bool aCloneSHChildren) {
10866 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"
, 10866); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aURI" ") ("
"uri is null" ")"); do { *((volatile int*)__null) = 10866; __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
;
10867 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"
, 10867); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aChannel || !aTriggeringPrincipal"
") (" "Shouldn't have both set" ")"); do { *((volatile int*)
__null) = 10867; __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
10868
10869 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"
, 10870); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aPrincipalToInherit || (aPrincipalToInherit && aTriggeringPrincipal)"
")"); do { *((volatile int*)__null) = 10870; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
10870 (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"
, 10870); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aPrincipalToInherit || (aPrincipalToInherit && aTriggeringPrincipal)"
")"); do { *((volatile int*)__null) = 10870; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10871
10872#if defined(DEBUG1)
10873 if (MOZ_LOG_TEST(gDocShellLog, LogLevel::Debug)(__builtin_expect(!!(mozilla::detail::log_test(gDocShellLog, LogLevel
::Debug)), 0))
) {
10874 nsAutoCString chanName;
10875 if (aChannel) {
10876 aChannel->GetName(chanName);
10877 } else {
10878 chanName.AssignLiteral("<no channel>");
10879 }
10880
10881 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)
10882 ("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)
10883 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)
;
10884 }
10885#endif
10886
10887 bool equalUri = false;
10888
10889 // Get the post data and the HTTP response code from the channel.
10890 uint32_t responseStatus = 0;
10891 nsCOMPtr<nsIInputStream> inputStream;
10892 if (aChannel) {
10893 nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(aChannel));
10894
10895 // Check if the HTTPChannel is hiding under a multiPartChannel
10896 if (!httpChannel) {
10897 GetHttpChannel(aChannel, getter_AddRefs(httpChannel));
10898 }
10899
10900 if (httpChannel) {
10901 nsCOMPtr<nsIUploadChannel> uploadChannel(do_QueryInterface(httpChannel));
10902 if (uploadChannel) {
10903 uploadChannel->GetUploadStream(getter_AddRefs(inputStream));
10904 }
10905
10906 // If the response status indicates an error, unlink this session
10907 // history entry from any entries sharing its document.
10908 nsresult rv = httpChannel->GetResponseStatus(&responseStatus);
10909 if (mLSHE && NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && responseStatus >= 400) {
10910 mLSHE->AbandonBFCacheEntry();
10911 // FIXME Do the same for mLoadingEntry
10912 }
10913 }
10914 }
10915
10916 // Determine if this type of load should update history.
10917 bool updateGHistory = ShouldUpdateGlobalHistory(mLoadType);
10918
10919 // We don't update session history on reload unless we're loading
10920 // an iframe in shift-reload case.
10921 bool updateSHistory = mBrowsingContext->ShouldUpdateSessionHistory(mLoadType);
10922
10923 // Create SH Entry (mLSHE) only if there is a SessionHistory object in the
10924 // root browsing context.
10925 // FIXME If session history in the parent is enabled then we only do this if
10926 // the session history object is in process, otherwise we can't really
10927 // use the mLSHE anyway. Once session history is only stored in the
10928 // parent then this code will probably be removed anyway.
10929 RefPtr<ChildSHistory> rootSH = GetRootSessionHistory();
10930 if (!rootSH) {
10931 updateSHistory = false;
10932 updateGHistory = false; // XXX Why global history too?
10933 }
10934
10935 // Check if the url to be loaded is the same as the one already loaded.
10936 if (mCurrentURI) {
10937 aURI->Equals(mCurrentURI, &equalUri);
10938 }
10939
10940#ifdef DEBUG1
10941 bool shAvailable = (rootSH != nullptr);
10942
10943 // XXX This log message is almost useless because |updateSHistory|
10944 // and |updateGHistory| are not correct at this point.
10945
10946 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)
10947 (" 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)
10948 " 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)
10949 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)
;
10950#endif
10951
10952 /* If the url to be loaded is the same as the one already there,
10953 * and the original loadType is LOAD_NORMAL, LOAD_LINK, or
10954 * LOAD_STOP_CONTENT, set loadType to LOAD_NORMAL_REPLACE so that
10955 * AddToSessionHistory() won't mess with the current SHEntry and
10956 * if this page has any frame children, it also will be handled
10957 * properly. see bug 83684
10958 *
10959 * NB: If mOSHE is null but we have a current URI, then it probably
10960 * means that we must be at the transient about:blank content viewer;
10961 * we should let the normal load continue, since there's nothing to
10962 * replace. Sometimes this happens after a session restore (eg process
10963 * switch) and mCurrentURI is not about:blank; we assume we can let the load
10964 * continue (Bug 1301399).
10965 *
10966 * XXX Hopefully changing the loadType at this time will not hurt
10967 * anywhere. The other way to take care of sequentially repeating
10968 * frameset pages is to add new methods to nsIDocShellTreeItem.
10969 * Hopefully I don't have to do that.
10970 */
10971 if (equalUri &&
10972 (mozilla::SessionHistoryInParent() ? !!mActiveEntry : !!mOSHE) &&
10973 (mLoadType == LOAD_NORMAL || mLoadType == LOAD_LINK ||
10974 mLoadType == LOAD_STOP_CONTENT) &&
10975 !inputStream) {
10976 mLoadType = LOAD_NORMAL_REPLACE;
10977 }
10978
10979 // If this is a refresh to the currently loaded url, we don't
10980 // have to update session or global history.
10981 if (mLoadType == LOAD_REFRESH && !inputStream && equalUri) {
10982 SetHistoryEntryAndUpdateBC(Some<nsISHEntry*>(mOSHE), Nothing());
10983 }
10984
10985 /* If the user pressed shift-reload, cache will create a new cache key
10986 * for the page. Save the new cacheKey in Session History.
10987 * see bug 90098
10988 */
10989 if (aChannel && IsForceReloadType(mLoadType)) {
10990 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"
, 10992); 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) = 10992; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
10991 "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"
, 10992); 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) = 10992; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
10992 " 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"
, 10992); 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) = 10992; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10993
10994 nsCOMPtr<nsICacheInfoChannel> cacheChannel(do_QueryInterface(aChannel));
10995 uint32_t cacheKey = 0;
10996 // Get the Cache Key and store it in SH.
10997 if (cacheChannel) {
10998 cacheChannel->GetCacheKey(&cacheKey);
10999 }
11000 // If we already have a loading history entry, store the new cache key
11001 // in it. Otherwise, since we're doing a reload and won't be updating
11002 // our history entry, store the cache key in our current history entry.
11003 SetCacheKeyOnHistoryEntry(mLSHE ? mLSHE : mOSHE, cacheKey);
11004
11005 if (!mozilla::SessionHistoryInParent()) {
11006 // Since we're force-reloading, clear all the sub frame history.
11007 ClearFrameHistory(mLSHE);
11008 ClearFrameHistory(mOSHE);
11009 }
11010 }
11011
11012 if (!mozilla::SessionHistoryInParent()) {
11013 // Clear subframe history on refresh.
11014 // XXX: history.go(0) won't go this path as mLoadType is LOAD_HISTORY in
11015 // this case. One should re-validate after bug 1331865 fixed.
11016 if (mLoadType == LOAD_REFRESH) {
11017 ClearFrameHistory(mLSHE);
11018 ClearFrameHistory(mOSHE);
11019 }
11020
11021 if (updateSHistory) {
11022 // Update session history if necessary...
11023 if (!mLSHE && (mItemType == typeContent) && mURIResultedInDocument) {
11024 /* This is a fresh page getting loaded for the first time
11025 *.Create a Entry for it and add it to SH, if this is the
11026 * rootDocShell
11027 */
11028 (void)AddToSessionHistory(aURI, aChannel, aTriggeringPrincipal,
11029 aPrincipalToInherit,
11030 aPartitionedPrincipalToInherit, aCsp,
11031 aCloneSHChildren, getter_AddRefs(mLSHE));
11032 }
11033 } else if (GetSessionHistory() && mLSHE && mURIResultedInDocument) {
11034 // Even if we don't add anything to SHistory, ensure the current index
11035 // points to the same SHEntry as our mLSHE.
11036
11037 GetSessionHistory()->LegacySHistory()->EnsureCorrectEntryAtCurrIndex(
11038 mLSHE);
11039 }
11040 }
11041
11042 // If this is a POST request, we do not want to include this in global
11043 // history.
11044 if (ShouldAddURIVisit(aChannel) && updateGHistory && aAddToGlobalHistory &&
11045 !net::ChannelIsPost(aChannel)) {
11046 nsCOMPtr<nsIURI> previousURI;
11047 uint32_t previousFlags = 0;
11048
11049 if (mLoadType & LOAD_CMD_RELOAD) {
11050 // On a reload request, we don't set redirecting flags.
11051 previousURI = aURI;
11052 } else {
11053 ExtractLastVisit(aChannel, getter_AddRefs(previousURI), &previousFlags);
11054 }
11055
11056 AddURIVisit(aURI, previousURI, previousFlags, responseStatus);
11057 }
11058
11059 // If this was a history load or a refresh, or it was a history load but
11060 // later changed to LOAD_NORMAL_REPLACE due to redirection, update the index
11061 // in session history.
11062 if (!mozilla::SessionHistoryInParent() && rootSH &&
11063 ((mLoadType & (LOAD_CMD_HISTORY | LOAD_CMD_RELOAD)) ||
11064 mLoadType == LOAD_NORMAL_REPLACE || mLoadType == LOAD_REFRESH_REPLACE)) {
11065 mPreviousEntryIndex = rootSH->Index();
11066 if (!mozilla::SessionHistoryInParent()) {
11067 rootSH->LegacySHistory()->UpdateIndex();
11068 }
11069 mLoadedEntryIndex = rootSH->Index();
11070 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)
11071 ("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)
11072 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)
;
11073 }
11074
11075 // aCloneSHChildren exactly means "we are not loading a new document".
11076 uint32_t locationFlags =
11077 aCloneSHChildren ? uint32_t(LOCATION_CHANGE_SAME_DOCUMENT) : 0;
11078
11079 bool onLocationChangeNeeded =
11080 SetCurrentURI(aURI, aChannel, false,
11081 /* aIsInitialAboutBlank */ false, locationFlags);
11082 // Make sure to store the referrer from the channel, if any
11083 nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(aChannel));
11084 if (httpChannel) {
11085 mReferrerInfo = httpChannel->GetReferrerInfo();
11086 }
11087 return onLocationChangeNeeded;
11088}
11089
11090Maybe<Wireframe> nsDocShell::GetWireframe() {
11091 const bool collectWireFrame =
11092 mozilla::SessionHistoryInParent() &&
11093 StaticPrefs::browser_history_collectWireframes() &&
11094 mBrowsingContext->IsTopContent() && mActiveEntry;
11095
11096 if (!collectWireFrame) {
11097 return Nothing();
11098 }
11099
11100 RefPtr<Document> doc = mDocumentViewer->GetDocument();
11101 Nullable<Wireframe> wireframe;
11102 doc->GetWireframeWithoutFlushing(false, wireframe);
11103 if (wireframe.IsNull()) {
11104 return Nothing();
11105 }
11106 return Some(wireframe.Value());
11107}
11108
11109bool nsDocShell::CollectWireframe() {
11110 Maybe<Wireframe> wireframe = GetWireframe();
11111 if (wireframe.isNothing()) {
11112 return false;
11113 }
11114
11115 if (XRE_IsParentProcess()) {
11116 SessionHistoryEntry* entry =
11117 mBrowsingContext->Canonical()->GetActiveSessionHistoryEntry();
11118 if (entry) {
11119 entry->SetWireframe(wireframe);
11120 }
11121 } else {
11122 mozilla::Unused
11123 << ContentChild::GetSingleton()->SendSessionHistoryEntryWireframe(
11124 mBrowsingContext, wireframe.ref());
11125 }
11126
11127 return true;
11128}
11129
11130//*****************************************************************************
11131// nsDocShell: Session History
11132//*****************************************************************************
11133
11134NS_IMETHODIMPnsresult
11135nsDocShell::AddState(JS::Handle<JS::Value> aData, const nsAString& aTitle,
11136 const nsAString& aURL, bool aReplace, JSContext* aCx) {
11137 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)
11138 ("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)
11139 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)
11140 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)
;
11141 // Implements History.pushState and History.replaceState
11142
11143 // Here's what we do, roughly in the order specified by HTML5. The specific
11144 // steps we are executing are at
11145 // <https://html.spec.whatwg.org/multipage/history.html#dom-history-pushstate>
11146 // and
11147 // <https://html.spec.whatwg.org/multipage/history.html#url-and-history-update-steps>.
11148 // This function basically implements #dom-history-pushstate and
11149 // UpdateURLAndHistory implements #url-and-history-update-steps.
11150 //
11151 // A. Serialize aData using structured clone. This is #dom-history-pushstate
11152 // step 5.
11153 // B. If the third argument is present, #dom-history-pushstate step 7.
11154 // 7.1. Resolve the url, relative to our document.
11155 // 7.2. If (a) fails, raise a SECURITY_ERR
11156 // 7.4. Compare the resulting absolute URL to the document's address. If
11157 // any part of the URLs difer other than the <path>, <query>, and
11158 // <fragment> components, raise a SECURITY_ERR and abort.
11159 // C. If !aReplace, #url-and-history-update-steps steps 2.1-2.3:
11160 // Remove from the session history all entries after the current entry,
11161 // as we would after a regular navigation, and save the current
11162 // entry's scroll position (bug 590573).
11163 // D. #url-and-history-update-steps step 2.4 or step 3. As apropriate,
11164 // either add a state object entry to the session history after the
11165 // current entry with the following properties, or modify the current
11166 // session history entry to set
11167 // a. cloned data as the state object,
11168 // b. if the third argument was present, the absolute URL found in
11169 // step 2
11170 // Also clear the new history entry's POST data (see bug 580069).
11171 // E. If aReplace is false (i.e. we're doing a pushState instead of a
11172 // replaceState), notify bfcache that we've navigated to a new page.
11173 // F. If the third argument is present, set the document's current address
11174 // to the absolute URL found in step B. This is
11175 // #url-and-history-update-steps step 4.
11176 //
11177 // It's important that this function not run arbitrary scripts after step A
11178 // and before completing step E. For example, if a script called
11179 // history.back() before we completed step E, bfcache might destroy an
11180 // active content viewer. Since EvictOutOfRangeDocumentViewers at the end of
11181 // step E might run script, we can't just put a script blocker around the
11182 // critical section.
11183 //
11184 // Note that we completely ignore the aTitle parameter.
11185
11186 nsresult rv;
11187
11188 // Don't clobber the load type of an existing network load.
11189 AutoRestore<uint32_t> loadTypeResetter(mLoadType);
11190
11191 // pushState effectively becomes replaceState when we've started a network
11192 // load but haven't adopted its document yet. This mirrors what we do with
11193 // changes to the hash at this stage of the game.
11194 if (JustStartedNetworkLoad()) {
11195 aReplace = true;
11196 }
11197
11198 RefPtr<Document> document = GetDocument();
11199 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"
, 11199); return NS_ERROR_FAILURE; } } while (false)
;
11200
11201 // Step A: Serialize aData using structured clone.
11202 // https://html.spec.whatwg.org/multipage/history.html#dom-history-pushstate
11203 // step 5.
11204 nsCOMPtr<nsIStructuredCloneContainer> scContainer;
11205
11206 // scContainer->Init might cause arbitrary JS to run, and this code might
11207 // navigate the page we're on, potentially to a different origin! (bug
11208 // 634834) To protect against this, we abort if our principal changes due
11209 // to the InitFromJSVal() call.
11210 {
11211 RefPtr<Document> origDocument = GetDocument();
11212 if (!origDocument) {
11213 return NS_ERROR_DOM_SECURITY_ERR;
11214 }
11215 nsCOMPtr<nsIPrincipal> origPrincipal = origDocument->NodePrincipal();
11216
11217 scContainer = new nsStructuredCloneContainer();
11218 rv = scContainer->InitFromJSVal(aData, aCx);
11219 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"
, 11219); return rv; } } while (false)
;
11220
11221 RefPtr<Document> newDocument = GetDocument();
11222 if (!newDocument) {
11223 return NS_ERROR_DOM_SECURITY_ERR;
11224 }
11225 nsCOMPtr<nsIPrincipal> newPrincipal = newDocument->NodePrincipal();
11226
11227 bool principalsEqual = false;
11228 origPrincipal->Equals(newPrincipal, &principalsEqual);
11229 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"
, 11229); return NS_ERROR_DOM_SECURITY_ERR; } } while (false)
;
11230 }
11231
11232 // Check that the state object isn't too long.
11233 int32_t maxStateObjSize = StaticPrefs::browser_history_maxStateObjectSize();
11234 if (maxStateObjSize < 0) {
11235 maxStateObjSize = 0;
11236 }
11237
11238 uint64_t scSize;
11239 rv = scContainer->GetSerializedNBytes(&scSize);
11240 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"
, 11240); return rv; } } while (false)
;
11241
11242 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"
, 11242); return NS_ERROR_ILLEGAL_VALUE; } } while (false)
;
11243
11244 // Step B: Resolve aURL.
11245 // https://html.spec.whatwg.org/multipage/history.html#dom-history-pushstate
11246 // step 7.
11247 bool equalURIs = true;
11248 nsCOMPtr<nsIURI> currentURI;
11249 if (mCurrentURI) {
11250 currentURI = nsIOService::CreateExposableURI(mCurrentURI);
11251 } else {
11252 currentURI = mCurrentURI;
11253 }
11254 nsCOMPtr<nsIURI> newURI;
11255 if (aURL.Length() == 0) {
11256 newURI = currentURI;
11257 } else {
11258 // 7.1: Resolve aURL relative to mURI
11259
11260 nsIURI* docBaseURI = document->GetDocBaseURI();
11261 if (!docBaseURI) {
11262 return NS_ERROR_FAILURE;
11263 }
11264
11265 nsAutoCString spec;
11266 docBaseURI->GetSpec(spec);
11267
11268 rv = NS_NewURI(getter_AddRefs(newURI), aURL,
11269 document->GetDocumentCharacterSet(), docBaseURI);
11270
11271 // 7.2: If 2a fails, raise a SECURITY_ERR
11272 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
11273 return NS_ERROR_DOM_SECURITY_ERR;
11274 }
11275
11276 // 7.4 and 7.5: Same-origin check.
11277 if (!nsContentUtils::URIIsLocalFile(newURI)) {
11278 // In addition to checking that the security manager says that
11279 // the new URI has the same origin as our current URI, we also
11280 // check that the two URIs have the same userpass. (The
11281 // security manager says that |http://foo.com| and
11282 // |http://me@foo.com| have the same origin.) currentURI
11283 // won't contain the password part of the userpass, so this
11284 // means that it's never valid to specify a password in a
11285 // pushState or replaceState URI.
11286
11287 nsCOMPtr<nsIScriptSecurityManager> secMan =
11288 do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID"@mozilla.org/scriptsecuritymanager;1");
11289 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"
, 11289); return NS_ERROR_FAILURE; } } while (false)
;
11290
11291 // It's very important that we check that newURI is of the same
11292 // origin as currentURI, not docBaseURI, because a page can
11293 // set docBaseURI arbitrarily to any domain.
11294 nsAutoCString currentUserPass, newUserPass;
11295 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"
, 11296); return NS_ERROR_FAILURE; } } while (false)
11296 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"
, 11296); return NS_ERROR_FAILURE; } } while (false)
;
11297 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"
, 11297); return NS_ERROR_FAILURE; } } while (false)
;
11298 bool isPrivateWin =
11299 document->NodePrincipal()->OriginAttributesRef().IsPrivateBrowsing();
11300 if (NS_FAILED(secMan->CheckSameOriginURI(currentURI, newURI, true,((bool)(__builtin_expect(!!(NS_FAILED_impl(secMan->CheckSameOriginURI
(currentURI, newURI, true, isPrivateWin))), 0)))
11301 isPrivateWin))((bool)(__builtin_expect(!!(NS_FAILED_impl(secMan->CheckSameOriginURI
(currentURI, newURI, true, isPrivateWin))), 0)))
||
11302 !currentUserPass.Equals(newUserPass)) {
11303 return NS_ERROR_DOM_SECURITY_ERR;
11304 }
11305 } else {
11306 // It's a file:// URI
11307 nsCOMPtr<nsIPrincipal> principal = document->GetPrincipal();
11308
11309 if (!principal || NS_FAILED(principal->CheckMayLoadWithReporting(((bool)(__builtin_expect(!!(NS_FAILED_impl(principal->CheckMayLoadWithReporting
( newURI, false, document->InnerWindowID()))), 0)))
11310 newURI, false, document->InnerWindowID()))((bool)(__builtin_expect(!!(NS_FAILED_impl(principal->CheckMayLoadWithReporting
( newURI, false, document->InnerWindowID()))), 0)))
) {
11311 return NS_ERROR_DOM_SECURITY_ERR;
11312 }
11313 }
11314
11315 if (currentURI) {
11316 currentURI->Equals(newURI, &equalURIs);
11317 } else {
11318 equalURIs = false;
11319 }
11320
11321 } // end of same-origin check
11322
11323 // Step 8: call "URL and history update steps"
11324 rv = UpdateURLAndHistory(document, newURI, scContainer, aTitle, aReplace,
11325 currentURI, equalURIs);
11326 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"
, 11326); return rv; } } while (false)
;
11327
11328 return NS_OK;
11329}
11330
11331nsresult nsDocShell::UpdateURLAndHistory(Document* aDocument, nsIURI* aNewURI,
11332 nsIStructuredCloneContainer* aData,
11333 const nsAString& aTitle, bool aReplace,
11334 nsIURI* aCurrentURI, bool aEqualURIs) {
11335 // Implements
11336 // https://html.spec.whatwg.org/multipage/history.html#url-and-history-update-steps
11337
11338 // If we have a pending title change, handle it before creating a new entry.
11339 aDocument->DoNotifyPossibleTitleChange();
11340
11341 // Step 2, if aReplace is false: Create a new entry in the session
11342 // history. This will erase all SHEntries after the new entry and make this
11343 // entry the current one. This operation may modify mOSHE, which we need
11344 // later, so we keep a reference here.
11345 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"
, 11345); return NS_ERROR_FAILURE; } } while (false)
;
11346 nsCOMPtr<nsISHEntry> oldOSHE = mOSHE;
11347
11348 // If this push/replaceState changed the document's current URI and the new
11349 // URI differs from the old URI in more than the hash, or if the old
11350 // SHEntry's URI was modified in this way by a push/replaceState call
11351 // set URIWasModified to true for the current SHEntry (bug 669671).
11352 bool sameExceptHashes = true;
11353 aNewURI->EqualsExceptRef(aCurrentURI, &sameExceptHashes);
11354 bool uriWasModified;
11355 if (sameExceptHashes) {
11356 if (mozilla::SessionHistoryInParent()) {
11357 uriWasModified = mActiveEntry && mActiveEntry->GetURIWasModified();
11358 } else {
11359 uriWasModified = oldOSHE && oldOSHE->GetURIWasModified();
11360 }
11361 } else {
11362 uriWasModified = true;
11363 }
11364
11365 mLoadType = LOAD_PUSHSTATE;
11366
11367 nsCOMPtr<nsISHEntry> newSHEntry;
11368 if (!aReplace) {
11369 // Step 2.
11370
11371 // Step 2.2, "Remove any tasks queued by the history traversal task
11372 // source that are associated with any Document objects in the
11373 // top-level browsing context's document family." This is very hard in
11374 // SessionHistoryInParent since we can't synchronously access the
11375 // pending navigations that are already sent to the parent. We can
11376 // abort any AsyncGo navigations that are waiting to be sent. If we
11377 // send a message to the parent, it would be processed after any
11378 // navigations previously sent. So long as we consider the "history
11379 // traversal task source" to be the list in this process we match the
11380 // spec. If we move the entire list to the parent, we can handle the
11381 // aborting of loads there, but we don't have a way to synchronously
11382 // remove entries as we do here for non-SHIP.
11383 RefPtr<ChildSHistory> shistory = GetRootSessionHistory();
11384 if (shistory) {
11385 shistory->RemovePendingHistoryNavigations();
11386 }
11387
11388 nsPoint scrollPos = GetCurScrollPos();
11389
11390 bool scrollRestorationIsManual;
11391 if (mozilla::SessionHistoryInParent()) {
11392 // FIXME Need to save the current scroll position on mActiveEntry.
11393 scrollRestorationIsManual = mActiveEntry->GetScrollRestorationIsManual();
11394 } else {
11395 // Save the current scroll position (bug 590573). Step 2.3.
11396 mOSHE->SetScrollPosition(scrollPos.x, scrollPos.y);
11397
11398 scrollRestorationIsManual = mOSHE->GetScrollRestorationIsManual();
11399 }
11400
11401 nsCOMPtr<nsIContentSecurityPolicy> csp = aDocument->GetCsp();
11402
11403 if (mozilla::SessionHistoryInParent()) {
11404 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)
11405 ("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)
;
11406
11407 nsString title(mActiveEntry->GetTitle());
11408 nsCOMPtr<nsIReferrerInfo> referrerInfo = mActiveEntry->GetReferrerInfo();
11409
11410 UpdateActiveEntry(false,
11411 /* aPreviousScrollPos = */ Some(scrollPos), aNewURI,
11412 /* aOriginalURI = */ nullptr,
11413 /* aReferrerInfo = */ referrerInfo,
11414 /* aTriggeringPrincipal = */ aDocument->NodePrincipal(),
11415 csp, title, scrollRestorationIsManual, aData,
11416 uriWasModified);
11417 } else {
11418 // Since we're not changing which page we have loaded, pass
11419 // true for aCloneChildren.
11420 nsresult rv = AddToSessionHistory(
11421 aNewURI, nullptr,
11422 aDocument->NodePrincipal(), // triggeringPrincipal
11423 nullptr, nullptr, csp, true, getter_AddRefs(newSHEntry));
11424 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"
, 11424); return rv; } } while (false)
;
11425
11426 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"
, 11426); return NS_ERROR_FAILURE; } } while (false)
;
11427
11428 // Session history entries created by pushState inherit scroll restoration
11429 // mode from the current entry.
11430 newSHEntry->SetScrollRestorationIsManual(scrollRestorationIsManual);
11431
11432 // Set the new SHEntry's title (bug 655273).
11433 nsString title;
11434 mOSHE->GetTitle(title);
11435 newSHEntry->SetTitle(title);
11436
11437 nsCOMPtr<nsIReferrerInfo> referrerInfo = mOSHE->GetReferrerInfo();
11438 newSHEntry->SetReferrerInfo(referrerInfo);
11439
11440 // Link the new SHEntry to the old SHEntry's BFCache entry, since the
11441 // two entries correspond to the same document.
11442 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"
, 11443); return NS_ERROR_FAILURE; } } while (false)
11443 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"
, 11443); return NS_ERROR_FAILURE; } } while (false)
;
11444
11445 // AddToSessionHistory may not modify mOSHE. In case it doesn't,
11446 // we'll just set mOSHE here.
11447 mOSHE = newSHEntry;
11448 }
11449 } else if (mozilla::SessionHistoryInParent()) {
11450 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)
11451 ("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)
11452 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)
;
11453 // Setting the resultPrincipalURI to nullptr is fine here: it will cause
11454 // NS_GetFinalChannelURI to use the originalURI as the URI, which is aNewURI
11455 // in our case. We could also set it to aNewURI, with the same result.
11456 // We don't use aTitle here, see bug 544535.
11457 nsString title;
11458 nsCOMPtr<nsIReferrerInfo> referrerInfo;
11459 if (mActiveEntry) {
11460 title = mActiveEntry->GetTitle();
11461 referrerInfo = mActiveEntry->GetReferrerInfo();
11462 } else {
11463 referrerInfo = nullptr;
11464 }
11465 UpdateActiveEntry(
11466 true, /* aPreviousScrollPos = */ Nothing(), aNewURI, aNewURI,
11467 /* aReferrerInfo = */ referrerInfo, aDocument->NodePrincipal(),
11468 aDocument->GetCsp(), title,
11469 mActiveEntry && mActiveEntry->GetScrollRestorationIsManual(), aData,
11470 uriWasModified);
11471 } else {
11472 // Step 3.
11473 newSHEntry = mOSHE;
11474
11475 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)
;
11476 // Since we're not changing which page we have loaded, pass
11477 // true for aCloneChildren.
11478 if (!newSHEntry) {
11479 nsresult rv = AddToSessionHistory(
11480 aNewURI, nullptr,
11481 aDocument->NodePrincipal(), // triggeringPrincipal
11482 nullptr, nullptr, aDocument->GetCsp(), true,
11483 getter_AddRefs(newSHEntry));
11484 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"
, 11484); return rv; } } while (false)
;
11485 mOSHE = newSHEntry;
11486 }
11487
11488 nsCOMPtr<nsIReferrerInfo> referrerInfo = mOSHE->GetReferrerInfo();
11489
11490 newSHEntry->SetURI(aNewURI);
11491 newSHEntry->SetOriginalURI(aNewURI);
11492 // We replaced the URI of the entry, clear the unstripped URI as it
11493 // shouldn't be used for reloads anymore.
11494 newSHEntry->SetUnstrippedURI(nullptr);
11495 // Setting the resultPrincipalURI to nullptr is fine here: it will cause
11496 // NS_GetFinalChannelURI to use the originalURI as the URI, which is aNewURI
11497 // in our case. We could also set it to aNewURI, with the same result.
11498 newSHEntry->SetResultPrincipalURI(nullptr);
11499 newSHEntry->SetLoadReplace(false);
11500 newSHEntry->SetReferrerInfo(referrerInfo);
11501 }
11502
11503 if (!mozilla::SessionHistoryInParent()) {
11504 // Step 2.4 and 3: Modify new/original session history entry and clear its
11505 // POST data, if there is any.
11506 newSHEntry->SetStateData(aData);
11507 newSHEntry->SetPostData(nullptr);
11508
11509 newSHEntry->SetURIWasModified(uriWasModified);
11510
11511 // Step E as described at the top of AddState: If aReplace is false,
11512 // indicating that we're doing a pushState rather than a replaceState,
11513 // notify bfcache that we've added a page to the history so it can evict
11514 // content viewers if appropriate. Otherwise call ReplaceEntry so that we
11515 // notify nsIHistoryListeners that an entry was replaced. We may not have a
11516 // root session history if this call is coming from a document.open() in a
11517 // docshell subtree that disables session history.
11518 RefPtr<ChildSHistory> rootSH = GetRootSessionHistory();
11519 if (rootSH) {
11520 rootSH->LegacySHistory()->EvictDocumentViewersOrReplaceEntry(newSHEntry,
11521 aReplace);
11522 }
11523 }
11524
11525 // Step 4: If the document's URI changed, update document's URI and update
11526 // global history.
11527 //
11528 // We need to call FireOnLocationChange so that the browser's address bar
11529 // gets updated and the back button is enabled, but we only need to
11530 // explicitly call FireOnLocationChange if we're not calling SetCurrentURI,
11531 // since SetCurrentURI will call FireOnLocationChange for us.
11532 //
11533 // Both SetCurrentURI(...) and FireDummyOnLocationChange() pass
11534 // nullptr for aRequest param to FireOnLocationChange(...). Such an update
11535 // notification is allowed only when we know docshell is not loading a new
11536 // document and it requires LOCATION_CHANGE_SAME_DOCUMENT flag. Otherwise,
11537 // FireOnLocationChange(...) breaks security UI.
11538 //
11539 // If the docshell is shutting down, don't update the document URI, as we
11540 // can't load into a docshell that is being destroyed.
11541 if (!aEqualURIs && !mIsBeingDestroyed) {
11542 aDocument->SetDocumentURI(aNewURI);
11543 SetCurrentURI(aNewURI, nullptr, /* aFireLocationChange */ true,
11544 /* aIsInitialAboutBlank */ false,
11545 GetSameDocumentNavigationFlags(aNewURI));
11546
11547 AddURIVisit(aNewURI, aCurrentURI, 0);
11548
11549 // AddURIVisit doesn't set the title for the new URI in global history,
11550 // so do that here.
11551 UpdateGlobalHistoryTitle(aNewURI);
11552
11553 // Inform the favicon service that our old favicon applies to this new
11554 // URI.
11555 CopyFavicon(aCurrentURI, aNewURI, UsePrivateBrowsing());
11556 } else {
11557 FireDummyOnLocationChange();
11558 }
11559 aDocument->SetStateObject(aData);
11560
11561 return NS_OK;
11562}
11563
11564NS_IMETHODIMPnsresult
11565nsDocShell::GetCurrentScrollRestorationIsManual(bool* aIsManual) {
11566 if (mozilla::SessionHistoryInParent()) {
11567 *aIsManual = mActiveEntry && mActiveEntry->GetScrollRestorationIsManual();
11568 return NS_OK;
11569 }
11570
11571 *aIsManual = false;
11572 if (mOSHE) {
11573 return mOSHE->GetScrollRestorationIsManual(aIsManual);
11574 }
11575
11576 return NS_OK;
11577}
11578
11579NS_IMETHODIMPnsresult
11580nsDocShell::SetCurrentScrollRestorationIsManual(bool aIsManual) {
11581 SetScrollRestorationIsManualOnHistoryEntry(mOSHE, aIsManual);
11582
11583 return NS_OK;
11584}
11585
11586void nsDocShell::SetScrollRestorationIsManualOnHistoryEntry(
11587 nsISHEntry* aSHEntry, bool aIsManual) {
11588 if (aSHEntry) {
11589 aSHEntry->SetScrollRestorationIsManual(aIsManual);
11590 }
11591
11592 if (mActiveEntry && mBrowsingContext) {
11593 mActiveEntry->SetScrollRestorationIsManual(aIsManual);
11594 if (XRE_IsParentProcess()) {
11595 SessionHistoryEntry* entry =
11596 mBrowsingContext->Canonical()->GetActiveSessionHistoryEntry();
11597 if (entry) {
11598 entry->SetScrollRestorationIsManual(aIsManual);
11599 }
11600 } else {
11601 mozilla::Unused << ContentChild::GetSingleton()
11602 ->SendSessionHistoryEntryScrollRestorationIsManual(
11603 mBrowsingContext, aIsManual);
11604 }
11605 }
11606}
11607
11608void nsDocShell::SetCacheKeyOnHistoryEntry(nsISHEntry* aSHEntry,
11609 uint32_t aCacheKey) {
11610 if (aSHEntry) {
11611 aSHEntry->SetCacheKey(aCacheKey);
11612 }
11613
11614 if (mActiveEntry && mBrowsingContext) {
11615 mActiveEntry->SetCacheKey(aCacheKey);
11616 if (XRE_IsParentProcess()) {
11617 SessionHistoryEntry* entry =
11618 mBrowsingContext->Canonical()->GetActiveSessionHistoryEntry();
11619 if (entry) {
11620 entry->SetCacheKey(aCacheKey);
11621 }
11622 } else {
11623 mozilla::Unused
11624 << ContentChild::GetSingleton()->SendSessionHistoryEntryCacheKey(
11625 mBrowsingContext, aCacheKey);
11626 }
11627 }
11628}
11629
11630/* static */
11631bool nsDocShell::ShouldAddToSessionHistory(nsIURI* aURI, nsIChannel* aChannel) {
11632 // I believe none of the about: urls should go in the history. But then
11633 // that could just be me... If the intent is only deny about:blank then we
11634 // should just do a spec compare, rather than two gets of the scheme and
11635 // then the path. -Gagan
11636 nsresult rv;
11637 nsAutoCString buf;
11638
11639 rv = aURI->GetScheme(buf);
11640 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
11641 return false;
11642 }
11643
11644 if (buf.EqualsLiteral("about")) {
11645 rv = aURI->GetPathQueryRef(buf);
11646 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
11647 return false;
11648 }
11649
11650 if (buf.EqualsLiteral("blank")) {
11651 return false;
11652 }
11653 // We only want to add about:newtab if it's not privileged, and
11654 // if it is not configured to show the blank page.
11655 if (buf.EqualsLiteral("newtab")) {
11656 if (!StaticPrefs::browser_newtabpage_enabled()) {
11657 return false;
11658 }
11659
11660 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"
, 11660); return false; } } while (false)
;
11661 nsCOMPtr<nsIPrincipal> resultPrincipal;
11662 rv = nsContentUtils::GetSecurityManager()->GetChannelResultPrincipal(
11663 aChannel, getter_AddRefs(resultPrincipal));
11664 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"
, 11664); return false; } } while (false)
;
11665 return !resultPrincipal->IsSystemPrincipal();
11666 }
11667 }
11668
11669 return true;
11670}
11671
11672nsresult nsDocShell::AddToSessionHistory(
11673 nsIURI* aURI, nsIChannel* aChannel, nsIPrincipal* aTriggeringPrincipal,
11674 nsIPrincipal* aPrincipalToInherit,
11675 nsIPrincipal* aPartitionedPrincipalToInherit,
11676 nsIContentSecurityPolicy* aCsp, bool aCloneChildren,
11677 nsISHEntry** aNewEntry) {
11678 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"
, 11678); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aURI" ") ("
"uri is null" ")"); do { *((volatile int*)__null) = 11678; __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
;
11679 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"
, 11679); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aChannel || !aTriggeringPrincipal"
") (" "Shouldn't have both set" ")"); do { *((volatile int*)
__null) = 11679; __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
11680 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"
, 11680); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "!mozilla::SessionHistoryInParent()"
")"); do { *((volatile int*)__null) = 11680; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11681
11682#if defined(DEBUG1)
11683 if (MOZ_LOG_TEST(gDocShellLog, LogLevel::Debug)(__builtin_expect(!!(mozilla::detail::log_test(gDocShellLog, LogLevel
::Debug)), 0))
) {
11684 nsAutoCString chanName;
11685 if (aChannel) {
11686 aChannel->GetName(chanName);
11687 } else {
11688 chanName.AssignLiteral("<no channel>");
11689 }
11690
11691 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)
11692 ("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)
11693 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)
;
11694 }
11695#endif
11696
11697 nsresult rv = NS_OK;
11698 nsCOMPtr<nsISHEntry> entry;
11699
11700 /*
11701 * If this is a LOAD_FLAGS_REPLACE_HISTORY in a subframe, we use
11702 * the existing SH entry in the page and replace the url and
11703 * other vitalities.
11704 */
11705 if (LOAD_TYPE_HAS_FLAGS(mLoadType, LOAD_FLAGS_REPLACE_HISTORY)((mLoadType) & ((LOAD_FLAGS_REPLACE_HISTORY) << 16)
)
&&
11706 !mBrowsingContext->IsTop()) {
11707 // This is a subframe
11708 entry = mOSHE;
11709 if (entry) {
11710 entry->ClearEntry();
11711 }
11712 }
11713
11714 // Create a new entry if necessary.
11715 if (!entry) {
11716 entry = new nsSHEntry();
11717 }
11718
11719 // Get the post data & referrer
11720 nsCOMPtr<nsIInputStream> inputStream;
11721 nsCOMPtr<nsIURI> originalURI;
11722 nsCOMPtr<nsIURI> resultPrincipalURI;
11723 nsCOMPtr<nsIURI> unstrippedURI;
11724 bool loadReplace = false;
11725 nsCOMPtr<nsIReferrerInfo> referrerInfo;
11726 uint32_t cacheKey = 0;
11727 nsCOMPtr<nsIPrincipal> triggeringPrincipal = aTriggeringPrincipal;
11728 nsCOMPtr<nsIPrincipal> principalToInherit = aPrincipalToInherit;
11729 nsCOMPtr<nsIPrincipal> partitionedPrincipalToInherit =
11730 aPartitionedPrincipalToInherit;
11731 nsCOMPtr<nsIContentSecurityPolicy> csp = aCsp;
11732 bool expired = false; // by default the page is not expired
11733 bool discardLayoutState = false;
11734 nsCOMPtr<nsICacheInfoChannel> cacheChannel;
11735 bool userActivation = false;
11736
11737 if (aChannel) {
11738 cacheChannel = do_QueryInterface(aChannel);
11739
11740 /* If there is a caching channel, get the Cache Key and store it
11741 * in SH.
11742 */
11743 if (cacheChannel) {
11744 cacheChannel->GetCacheKey(&cacheKey);
11745 }
11746 nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(aChannel));
11747
11748 // Check if the httpChannel is hiding under a multipartChannel
11749 if (!httpChannel) {
11750 GetHttpChannel(aChannel, getter_AddRefs(httpChannel));
11751 }
11752 if (httpChannel) {
11753 nsCOMPtr<nsIUploadChannel> uploadChannel(do_QueryInterface(httpChannel));
11754 if (uploadChannel) {
11755 uploadChannel->GetUploadStream(getter_AddRefs(inputStream));
11756 }
11757 httpChannel->GetOriginalURI(getter_AddRefs(originalURI));
11758 uint32_t loadFlags;
11759 aChannel->GetLoadFlags(&loadFlags);
11760 loadReplace = loadFlags & nsIChannel::LOAD_REPLACE;
11761 rv = httpChannel->GetReferrerInfo(getter_AddRefs(referrerInfo));
11762 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"
, 11762); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { *((volatile int*)__null) = 11762; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11763
11764 discardLayoutState = ShouldDiscardLayoutState(httpChannel);
11765 }
11766
11767 nsCOMPtr<nsILoadInfo> loadInfo = aChannel->LoadInfo();
11768 if (!triggeringPrincipal) {
11769 triggeringPrincipal = loadInfo->TriggeringPrincipal();
11770 }
11771 if (!csp) {
11772 csp = loadInfo->GetCspToInherit();
11773 }
11774
11775 loadInfo->GetResultPrincipalURI(getter_AddRefs(resultPrincipalURI));
11776
11777 loadInfo->GetUnstrippedURI(getter_AddRefs(unstrippedURI));
11778
11779 userActivation = loadInfo->GetHasValidUserGestureActivation();
11780
11781 // For now keep storing just the principal in the SHEntry.
11782 if (!principalToInherit) {
11783 if (loadInfo->GetLoadingSandboxed()) {
11784 if (loadInfo->GetLoadingPrincipal()) {
11785 principalToInherit = NullPrincipal::CreateWithInheritedAttributes(
11786 loadInfo->GetLoadingPrincipal());
11787 } else {
11788 // get the OriginAttributes
11789 OriginAttributes attrs;
11790 loadInfo->GetOriginAttributes(&attrs);
11791 principalToInherit = NullPrincipal::Create(attrs);
11792 }
11793 } else {
11794 principalToInherit = loadInfo->PrincipalToInherit();
11795 }
11796 }
11797
11798 if (!partitionedPrincipalToInherit) {
11799 // XXXehsan is it correct to fall back to the principal to inherit in all
11800 // cases? For example, what about the cases where we are using the load
11801 // info's principal to inherit? Do we need to add a similar concept to
11802 // load info for partitioned principal?
11803 partitionedPrincipalToInherit = principalToInherit;
11804 }
11805 }
11806
11807 nsAutoString srcdoc;
11808 bool srcdocEntry = false;
11809 nsCOMPtr<nsIURI> baseURI;
11810
11811 nsCOMPtr<nsIInputStreamChannel> inStrmChan = do_QueryInterface(aChannel);
11812 if (inStrmChan) {
11813 bool isSrcdocChannel;
11814 inStrmChan->GetIsSrcdocChannel(&isSrcdocChannel);
11815 if (isSrcdocChannel) {
11816 inStrmChan->GetSrcdocData(srcdoc);
11817 srcdocEntry = true;
11818 inStrmChan->GetBaseURI(getter_AddRefs(baseURI));
11819 } else {
11820 srcdoc.SetIsVoid(true);
11821 }
11822 }
11823 /* If cache got a 'no-store', ask SH not to store
11824 * HistoryLayoutState. By default, SH will set this
11825 * flag to true and save HistoryLayoutState.
11826 */
11827 bool saveLayoutState = !discardLayoutState;
11828
11829 if (cacheChannel) {
11830 // Check if the page has expired from cache
11831 uint32_t expTime = 0;
11832 cacheChannel->GetCacheTokenExpirationTime(&expTime);
11833 uint32_t now = PRTimeToSeconds(PR_Now());
11834 if (expTime <= now) {
11835 expired = true;
11836 }
11837 }
11838
11839 // Title is set in nsDocShell::SetTitle()
11840 entry->Create(aURI, // uri
11841 u""_ns, // Title
11842 inputStream, // Post data stream
11843 cacheKey, // CacheKey
11844 mContentTypeHint, // Content-type
11845 triggeringPrincipal, // Channel or provided principal
11846 principalToInherit, partitionedPrincipalToInherit, csp,
11847 HistoryID(), GetCreatedDynamically(), originalURI,
11848 resultPrincipalURI, unstrippedURI, loadReplace, referrerInfo,
11849 srcdoc, srcdocEntry, baseURI, saveLayoutState, expired,
11850 userActivation);
11851
11852 if (mBrowsingContext->IsTop() && GetSessionHistory()) {
11853 bool shouldPersist = ShouldAddToSessionHistory(aURI, aChannel);
11854 Maybe<int32_t> previousEntryIndex;
11855 Maybe<int32_t> loadedEntryIndex;
11856 rv = GetSessionHistory()->LegacySHistory()->AddToRootSessionHistory(
11857 aCloneChildren, mOSHE, mBrowsingContext, entry, mLoadType,
11858 shouldPersist, &previousEntryIndex, &loadedEntryIndex);
11859
11860 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"
, 11860); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
") (" "Could not add entry to root session history" ")"); do
{ *((volatile int*)__null) = 11860; __attribute__((nomerge))
::abort(); } while (false); } } while (false)
;
11861 if (previousEntryIndex.isSome()) {
11862 mPreviousEntryIndex = previousEntryIndex.value();
11863 }
11864 if (loadedEntryIndex.isSome()) {
11865 mLoadedEntryIndex = loadedEntryIndex.value();
11866 }
11867
11868 // aCloneChildren implies that we are retaining the same document, thus we
11869 // need to signal to the top WC that the new SHEntry may receive a fresh
11870 // user interaction flag.
11871 if (aCloneChildren) {
11872 WindowContext* topWc = mBrowsingContext->GetTopWindowContext();
11873 if (topWc && !topWc->IsDiscarded()) {
11874 MOZ_ALWAYS_SUCCEEDS(topWc->SetSHEntryHasUserInteraction(false))do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(topWc->SetSHEntryHasUserInteraction(false))), 1)))), 1)))
{ } else { do { static_assert( mozilla::detail::AssertionConditionType
<decltype(false)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("false" " (" "NS_SUCCEEDED(topWc->SetSHEntryHasUserInteraction(false))"
")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 11874); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "false"
") (" "NS_SUCCEEDED(topWc->SetSHEntryHasUserInteraction(false))"
")"); do { *((volatile int*)__null) = 11874; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false); } } while
(false)
;
11875 }
11876 }
11877 } else {
11878 // This is a subframe, make sure that this new SHEntry will be
11879 // marked with user interaction.
11880 WindowContext* topWc = mBrowsingContext->GetTopWindowContext();
11881 if (topWc && !topWc->IsDiscarded()) {
11882 MOZ_ALWAYS_SUCCEEDS(topWc->SetSHEntryHasUserInteraction(false))do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(topWc->SetSHEntryHasUserInteraction(false))), 1)))), 1)))
{ } else { do { static_assert( mozilla::detail::AssertionConditionType
<decltype(false)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("false" " (" "NS_SUCCEEDED(topWc->SetSHEntryHasUserInteraction(false))"
")", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 11882); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "false"
") (" "NS_SUCCEEDED(topWc->SetSHEntryHasUserInteraction(false))"
")"); do { *((volatile int*)__null) = 11882; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false); } } while
(false)
;
11883 }
11884 if (!mOSHE || !LOAD_TYPE_HAS_FLAGS(mLoadType, LOAD_FLAGS_REPLACE_HISTORY)((mLoadType) & ((LOAD_FLAGS_REPLACE_HISTORY) << 16)
)
) {
11885 rv = AddChildSHEntryToParent(entry, mBrowsingContext->ChildOffset(),
11886 aCloneChildren);
11887 }
11888 }
11889
11890 // Return the new SH entry...
11891 if (aNewEntry) {
11892 *aNewEntry = nullptr;
11893 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
11894 entry.forget(aNewEntry);
11895 }
11896 }
11897
11898 return rv;
11899}
11900
11901void nsDocShell::UpdateActiveEntry(
11902 bool aReplace, const Maybe<nsPoint>& aPreviousScrollPos, nsIURI* aURI,
11903 nsIURI* aOriginalURI, nsIReferrerInfo* aReferrerInfo,
11904 nsIPrincipal* aTriggeringPrincipal, nsIContentSecurityPolicy* aCsp,
11905 const nsAString& aTitle, bool aScrollRestorationIsManual,
11906 nsIStructuredCloneContainer* aData, bool aURIWasModified) {
11907 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"
, 11907); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mozilla::SessionHistoryInParent()"
")"); do { *((volatile int*)__null) = 11907; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11908 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"
, 11908); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aURI" ") ("
"uri is null" ")"); do { *((volatile int*)__null) = 11908; __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
;
11909 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"
, 11910); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mLoadType == LOAD_PUSHSTATE"
") (" "This code only deals with pushState" ")"); do { *((volatile
int*)__null) = 11910; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
11910 "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"
, 11910); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mLoadType == LOAD_PUSHSTATE"
") (" "This code only deals with pushState" ")"); do { *((volatile
int*)__null) = 11910; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
11911 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"
, 11911); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aReplace"
")"); do { *((volatile int*)__null) = 11911; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false); } } while
(false)
;
11912
11913 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)
11914 ("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)
11915 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)
;
11916
11917 // Even if we're replacing an existing entry we create new a
11918 // SessionHistoryInfo. In the parent process we'll keep the existing
11919 // SessionHistoryEntry, but just replace its SessionHistoryInfo, that way the
11920 // entry keeps identity but its data is replaced.
11921 bool replace = aReplace && mActiveEntry;
11922
11923 if (!replace) {
11924 CollectWireframe();
11925 }
11926
11927 if (mActiveEntry) {
11928 // Link this entry to the previous active entry.
11929 mActiveEntry = MakeUnique<SessionHistoryInfo>(*mActiveEntry, aURI);
11930 } else {
11931 mActiveEntry = MakeUnique<SessionHistoryInfo>(
11932 aURI, aTriggeringPrincipal, nullptr, nullptr, aCsp, mContentTypeHint);
11933 }
11934 mActiveEntry->SetOriginalURI(aOriginalURI);
11935 mActiveEntry->SetUnstrippedURI(nullptr);
11936 mActiveEntry->SetReferrerInfo(aReferrerInfo);
11937 mActiveEntry->SetTitle(aTitle);
11938 mActiveEntry->SetStateData(static_cast<nsStructuredCloneContainer*>(aData));
11939 mActiveEntry->SetURIWasModified(aURIWasModified);
11940 mActiveEntry->SetScrollRestorationIsManual(aScrollRestorationIsManual);
11941
11942 if (replace) {
11943 mBrowsingContext->ReplaceActiveSessionHistoryEntry(mActiveEntry.get());
11944 } else {
11945 mBrowsingContext->IncrementHistoryEntryCountForBrowsingContext();
11946 // FIXME We should probably just compute mChildOffset in the parent
11947 // instead of passing it over IPC here.
11948 mBrowsingContext->SetActiveSessionHistoryEntry(
11949 aPreviousScrollPos, mActiveEntry.get(), mLoadType,
11950 /* aCacheKey = */ 0);
11951 // FIXME Do we need to update mPreviousEntryIndex and mLoadedEntryIndex?
11952 }
11953}
11954
11955nsresult nsDocShell::LoadHistoryEntry(nsISHEntry* aEntry, uint32_t aLoadType,
11956 bool aUserActivation) {
11957 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"
, 11957); return NS_ERROR_FAILURE; } } while (false)
;
11958
11959 nsresult rv;
11960 RefPtr<nsDocShellLoadState> loadState;
11961 rv = aEntry->CreateLoadInfo(getter_AddRefs(loadState));
11962 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"
, 11962); return rv; } } while (false)
;
11963
11964 // Calling CreateAboutBlankDocumentViewer can set mOSHE to null, and if
11965 // that's the only thing holding a ref to aEntry that will cause aEntry to
11966 // die while we're loading it. So hold a strong ref to aEntry here, just
11967 // in case.
11968 nsCOMPtr<nsISHEntry> kungFuDeathGrip(aEntry);
11969
11970 loadState->SetHasValidUserGestureActivation(
11971 loadState->HasValidUserGestureActivation() || aUserActivation);
11972
11973 loadState->SetTextDirectiveUserActivation(
11974 loadState->GetTextDirectiveUserActivation() || aUserActivation);
11975
11976 return LoadHistoryEntry(loadState, aLoadType, aEntry == mOSHE);
11977}
11978
11979nsresult nsDocShell::LoadHistoryEntry(const LoadingSessionHistoryInfo& aEntry,
11980 uint32_t aLoadType,
11981 bool aUserActivation) {
11982 RefPtr<nsDocShellLoadState> loadState = aEntry.CreateLoadInfo();
11983 loadState->SetHasValidUserGestureActivation(
11984 loadState->HasValidUserGestureActivation() || aUserActivation);
11985
11986 loadState->SetTextDirectiveUserActivation(
11987 loadState->GetTextDirectiveUserActivation() || aUserActivation);
11988
11989 return LoadHistoryEntry(loadState, aLoadType, aEntry.mLoadingCurrentEntry);
11990}
11991
11992nsresult nsDocShell::LoadHistoryEntry(nsDocShellLoadState* aLoadState,
11993 uint32_t aLoadType,
11994 bool aLoadingCurrentEntry) {
11995 if (!IsNavigationAllowed()) {
11996 return NS_OK;
11997 }
11998
11999 // We are setting load type afterwards so we don't have to
12000 // send it in an IPC message
12001 aLoadState->SetLoadType(aLoadType);
12002
12003 nsresult rv;
12004 if (SchemeIsJavascript(aLoadState->URI())) {
12005 // We're loading a URL that will execute script from inside asyncOpen.
12006 // Replace the current document with about:blank now to prevent
12007 // anything from the current document from leaking into any JavaScript
12008 // code in the URL.
12009 // Don't cache the presentation if we're going to just reload the
12010 // current entry. Caching would lead to trying to save the different
12011 // content viewers in the same nsISHEntry object.
12012 rv = CreateAboutBlankDocumentViewer(
12013 aLoadState->PrincipalToInherit(),
12014 aLoadState->PartitionedPrincipalToInherit(), nullptr, nullptr,
12015 /* aIsInitialDocument */ false, Nothing(), !aLoadingCurrentEntry);
12016
12017 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
12018 // The creation of the intermittent about:blank content
12019 // viewer failed for some reason (potentially because the
12020 // user prevented it). Interrupt the history load.
12021 return NS_OK;
12022 }
12023
12024 if (!aLoadState->TriggeringPrincipal()) {
12025 // Ensure that we have a triggeringPrincipal. Otherwise javascript:
12026 // URIs will pick it up from the about:blank page we just loaded,
12027 // and we don't really want even that in this case.
12028 nsCOMPtr<nsIPrincipal> principal =
12029 NullPrincipal::Create(GetOriginAttributes());
12030 aLoadState->SetTriggeringPrincipal(principal);
12031 }
12032 }
12033
12034 /* If there is a valid postdata *and* the user pressed
12035 * reload or shift-reload, take user's permission before we
12036 * repost the data to the server.
12037 */
12038 if ((aLoadType & LOAD_CMD_RELOAD) && aLoadState->PostDataStream()) {
12039 bool repost;
12040 rv = ConfirmRepost(&repost);
12041 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
12042 return rv;
12043 }
12044
12045 // If the user pressed cancel in the dialog, return. We're done here.
12046 if (!repost) {
12047 return NS_BINDING_ABORTED;
12048 }
12049 }
12050
12051 // If there is no valid triggeringPrincipal, we deny the load
12052 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"
, 12053); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->TriggeringPrincipal()"
") (" "need a valid triggeringPrincipal to load from history"
")"); do { *((volatile int*)__null) = 12053; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
12053 "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"
, 12053); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->TriggeringPrincipal()"
") (" "need a valid triggeringPrincipal to load from history"
")"); do { *((volatile int*)__null) = 12053; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12054 if (!aLoadState->TriggeringPrincipal()) {
12055 return NS_ERROR_FAILURE;
12056 }
12057
12058 return InternalLoad(aLoadState); // No nsIRequest
12059}
12060
12061NS_IMETHODIMPnsresult
12062nsDocShell::PersistLayoutHistoryState() {
12063 nsresult rv = NS_OK;
12064
12065 if (mozilla::SessionHistoryInParent() ? !!mActiveEntry : !!mOSHE) {
12066 bool scrollRestorationIsManual;
12067 if (mozilla::SessionHistoryInParent()) {
12068 scrollRestorationIsManual = mActiveEntry->GetScrollRestorationIsManual();
12069 } else {
12070 scrollRestorationIsManual = mOSHE->GetScrollRestorationIsManual();
12071 }
12072 nsCOMPtr<nsILayoutHistoryState> layoutState;
12073 if (RefPtr<PresShell> presShell = GetPresShell()) {
12074 rv = presShell->CaptureHistoryState(getter_AddRefs(layoutState));
12075 } else if (scrollRestorationIsManual) {
12076 // Even if we don't have layout anymore, we may want to reset the
12077 // current scroll state in layout history.
12078 GetLayoutHistoryState(getter_AddRefs(layoutState));
12079 }
12080
12081 if (scrollRestorationIsManual && layoutState) {
12082 layoutState->ResetScrollState();
12083 }
12084 }
12085
12086 return rv;
12087}
12088
12089void nsDocShell::SwapHistoryEntries(nsISHEntry* aOldEntry,
12090 nsISHEntry* aNewEntry) {
12091 if (aOldEntry == mOSHE) {
12092 mOSHE = aNewEntry;
12093 }
12094
12095 if (aOldEntry == mLSHE) {
12096 mLSHE = aNewEntry;
12097 }
12098}
12099
12100void nsDocShell::SetHistoryEntryAndUpdateBC(const Maybe<nsISHEntry*>& aLSHE,
12101 const Maybe<nsISHEntry*>& aOSHE) {
12102 // We want to hold on to the reference in mLSHE before we update it.
12103 // Otherwise, SetHistoryEntry could release the last reference to
12104 // the entry while aOSHE is pointing to it.
12105 nsCOMPtr<nsISHEntry> deathGripOldLSHE;
12106 if (aLSHE.isSome()) {
12107 deathGripOldLSHE = SetHistoryEntry(&mLSHE, aLSHE.value());
12108 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"
, 12108); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mLSHE.get() == aLSHE.value()"
")"); do { *((volatile int*)__null) = 12108; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12109 }
12110 nsCOMPtr<nsISHEntry> deathGripOldOSHE;
12111 if (aOSHE.isSome()) {
12112 deathGripOldOSHE = SetHistoryEntry(&mOSHE, aOSHE.value());
12113 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"
, 12113); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mOSHE.get() == aOSHE.value()"
")"); do { *((volatile int*)__null) = 12113; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12114 }
12115}
12116
12117already_AddRefed<nsISHEntry> nsDocShell::SetHistoryEntry(
12118 nsCOMPtr<nsISHEntry>* aPtr, nsISHEntry* aEntry) {
12119 // We need to sync up the docshell and session history trees for
12120 // subframe navigation. If the load was in a subframe, we forward up to
12121 // the root docshell, which will then recursively sync up all docshells
12122 // to their corresponding entries in the new session history tree.
12123 // If we don't do this, then we can cache a content viewer on the wrong
12124 // cloned entry, and subsequently restore it at the wrong time.
12125 RefPtr<BrowsingContext> topBC = mBrowsingContext->Top();
12126 if (topBC->IsDiscarded()) {
12127 topBC = nullptr;
12128 }
12129 RefPtr<BrowsingContext> currBC =
12130 mBrowsingContext->IsDiscarded() ? nullptr : mBrowsingContext;
12131 if (topBC && *aPtr) {
12132 (*aPtr)->SyncTreesForSubframeNavigation(aEntry, topBC, currBC);
12133 }
12134 nsCOMPtr<nsISHEntry> entry(aEntry);
12135 entry.swap(*aPtr);
12136 return entry.forget();
12137}
12138
12139already_AddRefed<ChildSHistory> nsDocShell::GetRootSessionHistory() {
12140 RefPtr<ChildSHistory> childSHistory =
12141 mBrowsingContext->Top()->GetChildSessionHistory();
12142 return childSHistory.forget();
12143}
12144
12145nsresult nsDocShell::GetHttpChannel(nsIChannel* aChannel,
12146 nsIHttpChannel** aReturn) {
12147 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"
, 12147); return NS_ERROR_INVALID_POINTER; } } while (false)
;
12148 if (!aChannel) {
12149 return NS_ERROR_FAILURE;
12150 }
12151
12152 nsCOMPtr<nsIMultiPartChannel> multiPartChannel(do_QueryInterface(aChannel));
12153 if (multiPartChannel) {
12154 nsCOMPtr<nsIChannel> baseChannel;
12155 multiPartChannel->GetBaseChannel(getter_AddRefs(baseChannel));
12156 nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(baseChannel));
12157 *aReturn = httpChannel;
12158 NS_IF_ADDREF(*aReturn)ns_if_addref(*aReturn);
12159 }
12160 return NS_OK;
12161}
12162
12163bool nsDocShell::ShouldDiscardLayoutState(nsIHttpChannel* aChannel) {
12164 // By default layout State will be saved.
12165 if (!aChannel) {
12166 return false;
12167 }
12168
12169 // figure out if SH should be saving layout state
12170 bool noStore = false;
12171 Unused << aChannel->IsNoStoreResponse(&noStore);
12172 return noStore;
12173}
12174
12175NS_IMETHODIMPnsresult
12176nsDocShell::GetEditor(nsIEditor** aEditor) {
12177 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"
, 12177); return NS_ERROR_INVALID_POINTER; } } while (false)
;
12178 RefPtr<HTMLEditor> htmlEditor = GetHTMLEditorInternal();
12179 htmlEditor.forget(aEditor);
12180 return NS_OK;
12181}
12182
12183NS_IMETHODIMPnsresult
12184nsDocShell::SetEditor(nsIEditor* aEditor) {
12185 HTMLEditor* htmlEditor = aEditor ? aEditor->GetAsHTMLEditor() : nullptr;
12186 // If TextEditor comes, throw an error.
12187 if (aEditor && !htmlEditor) {
12188 return NS_ERROR_INVALID_ARG;
12189 }
12190 return SetHTMLEditorInternal(htmlEditor);
12191}
12192
12193HTMLEditor* nsDocShell::GetHTMLEditorInternal() {
12194 return mEditorData ? mEditorData->GetHTMLEditor() : nullptr;
12195}
12196
12197nsresult nsDocShell::SetHTMLEditorInternal(HTMLEditor* aHTMLEditor) {
12198 if (!aHTMLEditor && !mEditorData) {
12199 return NS_OK;
12200 }
12201
12202 nsresult rv = EnsureEditorData();
12203 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
12204 return rv;
12205 }
12206
12207 return mEditorData->SetHTMLEditor(aHTMLEditor);
12208}
12209
12210NS_IMETHODIMPnsresult
12211nsDocShell::GetEditable(bool* aEditable) {
12212 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"
, 12212); return NS_ERROR_INVALID_POINTER; } } while (false)
;
12213 *aEditable = mEditorData && mEditorData->GetEditable();
12214 return NS_OK;
12215}
12216
12217NS_IMETHODIMPnsresult
12218nsDocShell::GetHasEditingSession(bool* aHasEditingSession) {
12219 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"
, 12219); return NS_ERROR_INVALID_POINTER; } } while (false)
;
12220
12221 if (mEditorData) {
12222 *aHasEditingSession = !!mEditorData->GetEditingSession();
12223 } else {
12224 *aHasEditingSession = false;
12225 }
12226
12227 return NS_OK;
12228}
12229
12230NS_IMETHODIMPnsresult
12231nsDocShell::MakeEditable(bool aInWaitForUriLoad) {
12232 nsresult rv = EnsureEditorData();
12233 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
12234 return rv;
12235 }
12236
12237 return mEditorData->MakeEditable(aInWaitForUriLoad);
12238}
12239
12240/* static */ bool nsDocShell::ShouldAddURIVisit(nsIChannel* aChannel) {
12241 bool needToAddURIVisit = true;
12242 nsCOMPtr<nsIPropertyBag2> props(do_QueryInterface(aChannel));
12243 if (props) {
12244 mozilla::Unused << props->GetPropertyAsBool(
12245 u"docshell.needToAddURIVisit"_ns, &needToAddURIVisit);
12246 }
12247
12248 return needToAddURIVisit;
12249}
12250
12251/* static */ void nsDocShell::ExtractLastVisit(
12252 nsIChannel* aChannel, nsIURI** aURI, uint32_t* aChannelRedirectFlags) {
12253 nsCOMPtr<nsIPropertyBag2> props(do_QueryInterface(aChannel));
12254 if (!props) {
12255 return;
12256 }
12257
12258 nsresult rv;
12259 nsCOMPtr<nsIURI> uri(do_GetProperty(props, u"docshell.previousURI"_ns, &rv));
12260 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
12261 uri.forget(aURI);
12262
12263 rv = props->GetPropertyAsUint32(u"docshell.previousFlags"_ns,
12264 aChannelRedirectFlags);
12265
12266 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"
, 12268); } } while (false)
12267 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"
, 12268); } } while (false)
12268 "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"
, 12268); } } while (false)
;
12269
12270 } else {
12271 // There is no last visit for this channel, so this must be the first
12272 // link. Link the visit to the referrer of this request, if any.
12273 // Treat referrer as null if there is an error getting it.
12274 NS_GetReferrerFromChannel(aChannel, aURI);
12275 }
12276}
12277
12278void nsDocShell::SaveLastVisit(nsIChannel* aChannel, nsIURI* aURI,
12279 uint32_t aChannelRedirectFlags) {
12280 nsCOMPtr<nsIWritablePropertyBag2> props(do_QueryInterface(aChannel));
12281 if (!props || !aURI) {
12282 return;
12283 }
12284
12285 props->SetPropertyAsInterface(u"docshell.previousURI"_ns, aURI);
12286 props->SetPropertyAsUint32(u"docshell.previousFlags"_ns,
12287 aChannelRedirectFlags);
12288}
12289
12290/* static */ void nsDocShell::InternalAddURIVisit(
12291 nsIURI* aURI, nsIURI* aPreviousURI, uint32_t aChannelRedirectFlags,
12292 uint32_t aResponseStatus, BrowsingContext* aBrowsingContext,
12293 nsIWidget* aWidget, uint32_t aLoadType, bool aWasUpgraded) {
12294 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"
, 12294); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aURI" ") ("
"Visited URI is null!" ")"); do { *((volatile int*)__null) =
12294; __attribute__((nomerge)) ::abort(); } while (false); }
} while (false)
;
12295 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"
, 12296); 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) = 12296; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
12296 "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"
, 12296); 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) = 12296; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
12297
12298 bool usePrivateBrowsing = false;
12299 aBrowsingContext->GetUsePrivateBrowsing(&usePrivateBrowsing);
12300
12301 // Only content-type docshells save URI visits. Also don't do
12302 // anything here if we're not supposed to use global history.
12303 if (!aBrowsingContext->IsContent() ||
12304 !aBrowsingContext->GetUseGlobalHistory() || usePrivateBrowsing) {
12305 return;
12306 }
12307
12308 nsCOMPtr<IHistory> history = components::History::Service();
12309
12310 if (history) {
12311 uint32_t visitURIFlags = 0;
12312
12313 if (aBrowsingContext->IsTop()) {
12314 visitURIFlags |= IHistory::TOP_LEVEL;
12315 }
12316
12317 if (aChannelRedirectFlags & nsIChannelEventSink::REDIRECT_TEMPORARY) {
12318 visitURIFlags |= IHistory::REDIRECT_TEMPORARY;
12319 } else if (aChannelRedirectFlags &
12320 nsIChannelEventSink::REDIRECT_PERMANENT) {
12321 visitURIFlags |= IHistory::REDIRECT_PERMANENT;
12322 } else {
12323 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"
, 12325); 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) = 12325; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
12324 "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"
, 12325); 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) = 12325; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
12325 "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"
, 12325); 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) = 12325; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
;
12326 }
12327
12328 if (aResponseStatus >= 300 && aResponseStatus < 400) {
12329 visitURIFlags |= IHistory::REDIRECT_SOURCE;
12330 if (aResponseStatus == 301 || aResponseStatus == 308) {
12331 visitURIFlags |= IHistory::REDIRECT_SOURCE_PERMANENT;
12332 }
12333 }
12334 // Errors 400-501 and 505 are considered unrecoverable, in the sense a
12335 // simple retry attempt by the user is unlikely to solve them.
12336 // 408 is special cased, since may actually indicate a temporary
12337 // connection problem.
12338 else if (aResponseStatus != 408 &&
12339 ((aResponseStatus >= 400 && aResponseStatus <= 501) ||
12340 aResponseStatus == 505)) {
12341 visitURIFlags |= IHistory::UNRECOVERABLE_ERROR;
12342 }
12343
12344 if (aWasUpgraded) {
12345 visitURIFlags |=
12346 IHistory::REDIRECT_SOURCE | IHistory::REDIRECT_SOURCE_UPGRADED;
12347 }
12348
12349 mozilla::Unused << history->VisitURI(aWidget, aURI, aPreviousURI,
12350 visitURIFlags,
12351 aBrowsingContext->BrowserId());
12352 }
12353}
12354
12355void nsDocShell::AddURIVisit(nsIURI* aURI, nsIURI* aPreviousURI,
12356 uint32_t aChannelRedirectFlags,
12357 uint32_t aResponseStatus) {
12358 nsPIDOMWindowOuter* outer = GetWindow();
12359 nsCOMPtr<nsIWidget> widget = widget::WidgetUtils::DOMWindowToWidget(outer);
12360
12361 InternalAddURIVisit(aURI, aPreviousURI, aChannelRedirectFlags,
12362 aResponseStatus, mBrowsingContext, widget, mLoadType,
12363 false);
12364}
12365
12366//*****************************************************************************
12367// nsDocShell: Helper Routines
12368//*****************************************************************************
12369
12370NS_IMETHODIMPnsresult
12371nsDocShell::SetLoadType(uint32_t aLoadType) {
12372 mLoadType = aLoadType;
12373 return NS_OK;
12374}
12375
12376NS_IMETHODIMPnsresult
12377nsDocShell::GetLoadType(uint32_t* aLoadType) {
12378 *aLoadType = mLoadType;
12379 return NS_OK;
12380}
12381
12382nsresult nsDocShell::ConfirmRepost(bool* aRepost) {
12383 if (StaticPrefs::dom_confirm_repost_testing_always_accept()) {
12384 *aRepost = true;
12385 return NS_OK;
12386 }
12387
12388 nsCOMPtr<nsIPromptCollection> prompter =
12389 do_GetService("@mozilla.org/embedcomp/prompt-collection;1");
12390 if (!prompter) {
12391 return NS_ERROR_NOT_AVAILABLE;
12392 }
12393
12394 return prompter->ConfirmRepost(mBrowsingContext, aRepost);
12395}
12396
12397nsresult nsDocShell::GetPromptAndStringBundle(nsIPrompt** aPrompt,
12398 nsIStringBundle** aStringBundle) {
12399 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"
, 12400); return NS_ERROR_FAILURE; } } while (false)
12400 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"
, 12400); return NS_ERROR_FAILURE; } } while (false)
;
12401
12402 nsCOMPtr<nsIStringBundleService> stringBundleService =
12403 mozilla::components::StringBundle::Service();
12404 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"
, 12404); return NS_ERROR_FAILURE; } } while (false)
;
12405
12406 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"
, 12408); return NS_ERROR_FAILURE; } } while (false)
12407 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"
, 12408); return NS_ERROR_FAILURE; } } while (false)
12408 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"
, 12408); return NS_ERROR_FAILURE; } } while (false)
;
12409
12410 return NS_OK;
12411}
12412
12413ScrollContainerFrame* nsDocShell::GetRootScrollContainerFrame() {
12414 PresShell* presShell = GetPresShell();
12415 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"
, 12415); return nullptr; } } while (false)
;
12416
12417 return presShell->GetRootScrollContainerFrame();
12418}
12419
12420nsresult nsDocShell::EnsureScriptEnvironment() {
12421 if (mScriptGlobal) {
12422 return NS_OK;
12423 }
12424
12425 if (mIsBeingDestroyed) {
12426 return NS_ERROR_NOT_AVAILABLE;
12427 }
12428
12429#ifdef DEBUG1
12430 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"
, 12432); MOZ_PretendNoReturn(); } } while (0)
12431 "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"
, 12432); MOZ_PretendNoReturn(); } } while (0)
12432 "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"
, 12432); MOZ_PretendNoReturn(); } } while (0)
;
12433
12434 // Yeah, this isn't re-entrant safe, but that's ok since if we
12435 // re-enter this method, we'll infinitely loop...
12436 AutoRestore<bool> boolSetter(mInEnsureScriptEnv);
12437 mInEnsureScriptEnv = true;
12438#endif
12439
12440 nsCOMPtr<nsIWebBrowserChrome> browserChrome(do_GetInterface(mTreeOwner));
12441 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"
, 12441); return NS_ERROR_NOT_AVAILABLE; } } while (false)
;
12442
12443 uint32_t chromeFlags;
12444 browserChrome->GetChromeFlags(&chromeFlags);
12445
12446 // If our window is modal and we're not opened as chrome, make
12447 // this window a modal content window.
12448 mScriptGlobal = nsGlobalWindowOuter::Create(this, mItemType == typeChrome);
12449 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"
, 12449); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mScriptGlobal"
")"); do { *((volatile int*)__null) = 12449; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12450
12451 // Ensure the script object is set up to run script.
12452 return mScriptGlobal->EnsureScriptEnvironment();
12453}
12454
12455nsresult nsDocShell::EnsureEditorData() {
12456 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"
, 12456); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mIsBeingDestroyed"
")"); do { *((volatile int*)__null) = 12456; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12457
12458 bool openDocHasDetachedEditor = mOSHE && mOSHE->HasDetachedEditor();
12459 if (!mEditorData && !mIsBeingDestroyed && !openDocHasDetachedEditor) {
12460 // We shouldn't recreate the editor data if it already exists, or
12461 // we're shutting down, or we already have a detached editor data
12462 // stored in the session history. We should only have one editordata
12463 // per docshell.
12464 mEditorData = MakeUnique<nsDocShellEditorData>(this);
12465 }
12466
12467 return mEditorData ? NS_OK : NS_ERROR_NOT_AVAILABLE;
12468}
12469
12470nsresult nsDocShell::EnsureFind() {
12471 if (!mFind) {
12472 mFind = new nsWebBrowserFind();
12473 }
12474
12475 // we promise that the nsIWebBrowserFind that we return has been set
12476 // up to point to the focused, or content window, so we have to
12477 // set that up each time.
12478
12479 nsIScriptGlobalObject* scriptGO = GetScriptGlobalObject();
12480 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"
, 12480); return NS_ERROR_UNEXPECTED; } } while (false)
;
12481
12482 // default to our window
12483 nsCOMPtr<nsPIDOMWindowOuter> ourWindow = do_QueryInterface(scriptGO);
12484 nsCOMPtr<nsPIDOMWindowOuter> windowToSearch;
12485 nsFocusManager::GetFocusedDescendant(ourWindow,
12486 nsFocusManager::eIncludeAllDescendants,
12487 getter_AddRefs(windowToSearch));
12488
12489 nsCOMPtr<nsIWebBrowserFindInFrames> findInFrames = do_QueryInterface(mFind);
12490 if (!findInFrames) {
12491 return NS_ERROR_NO_INTERFACE;
12492 }
12493
12494 nsresult rv = findInFrames->SetRootSearchFrame(ourWindow);
12495 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
12496 return rv;
12497 }
12498 rv = findInFrames->SetCurrentSearchFrame(windowToSearch);
12499 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
12500 return rv;
12501 }
12502
12503 return NS_OK;
12504}
12505
12506NS_IMETHODIMPnsresult
12507nsDocShell::IsBeingDestroyed(bool* aDoomed) {
12508 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"
, 12508); return NS_ERROR_INVALID_ARG; } } while (false)
;
12509 *aDoomed = mIsBeingDestroyed;
12510 return NS_OK;
12511}
12512
12513NS_IMETHODIMPnsresult
12514nsDocShell::GetIsExecutingOnLoadHandler(bool* aResult) {
12515 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"
, 12515); return NS_ERROR_INVALID_ARG; } } while (false)
;
12516 *aResult = mIsExecutingOnLoadHandler;
12517 return NS_OK;
12518}
12519
12520NS_IMETHODIMPnsresult
12521nsDocShell::GetLayoutHistoryState(nsILayoutHistoryState** aLayoutHistoryState) {
12522 nsCOMPtr<nsILayoutHistoryState> state;
12523 if (mozilla::SessionHistoryInParent()) {
12524 if (mActiveEntry) {
12525 state = mActiveEntry->GetLayoutHistoryState();
12526 }
12527 } else {
12528 if (mOSHE) {
12529 state = mOSHE->GetLayoutHistoryState();
12530 }
12531 }
12532 state.forget(aLayoutHistoryState);
12533 return NS_OK;
12534}
12535
12536NS_IMETHODIMPnsresult
12537nsDocShell::SetLayoutHistoryState(nsILayoutHistoryState* aLayoutHistoryState) {
12538 if (mOSHE) {
12539 mOSHE->SetLayoutHistoryState(aLayoutHistoryState);
12540 }
12541 if (mActiveEntry) {
12542 mActiveEntry->SetLayoutHistoryState(aLayoutHistoryState);
12543 }
12544 return NS_OK;
12545}
12546
12547nsDocShell::InterfaceRequestorProxy::InterfaceRequestorProxy(
12548 nsIInterfaceRequestor* aRequestor) {
12549 if (aRequestor) {
12550 mWeakPtr = do_GetWeakReference(aRequestor);
12551 }
12552}
12553
12554nsDocShell::InterfaceRequestorProxy::~InterfaceRequestorProxy() {
12555 mWeakPtr = nullptr;
12556}
12557
12558NS_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"
, 12558); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { *((volatile int*)__null) =
12558; __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"
, 12558); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"nsDocShell::InterfaceRequestorProxy\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 12558; __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"
, 12558); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { *((volatile int*)__null) = 12558
; __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"
, 12558); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"nsDocShell::InterfaceRequestorProxy\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 12558; __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"
, 12558); MOZ_PretendNoReturn(); } } while (0); nsresult rv =
NS_ERROR_FAILURE; static_assert(1 > 0, "Need more arguments to NS_INTERFACE_TABLE"
); static const QITableEntry table[] = { {&mozilla::detail
::kImplementedIID<nsDocShell::InterfaceRequestorProxy, nsIInterfaceRequestor
>, int32_t( reinterpret_cast<char*>(static_cast<nsIInterfaceRequestor
*>((nsDocShell::InterfaceRequestorProxy*)0x1000)) - reinterpret_cast
<char*>((nsDocShell::InterfaceRequestorProxy*)0x1000))}
, {&mozilla::detail::kImplementedIID<nsDocShell::InterfaceRequestorProxy
, nsISupports>, int32_t(reinterpret_cast<char*>(static_cast
<nsISupports*>( static_cast<nsIInterfaceRequestor*>
((nsDocShell::InterfaceRequestorProxy*)0x1000))) - reinterpret_cast
<char*>((nsDocShell::InterfaceRequestorProxy*)0x1000))}
, { nullptr, 0 } } ; static_assert((sizeof(table) / sizeof(table
[0])) > 1, "need at least 1 interface"); rv = NS_TableDrivenQI
(static_cast<void*>(this), aIID, aInstancePtr, table); return
rv; }
12559
12560NS_IMETHODIMPnsresult
12561nsDocShell::InterfaceRequestorProxy::GetInterface(const nsIID& aIID,
12562 void** aSink) {
12563 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"
, 12563); return NS_ERROR_INVALID_POINTER; } } while (false)
;
12564 nsCOMPtr<nsIInterfaceRequestor> ifReq = do_QueryReferent(mWeakPtr);
12565 if (ifReq) {
12566 return ifReq->GetInterface(aIID, aSink);
12567 }
12568 *aSink = nullptr;
12569 return NS_NOINTERFACE;
12570}
12571
12572//*****************************************************************************
12573// nsDocShell::nsIAuthPromptProvider
12574//*****************************************************************************
12575
12576NS_IMETHODIMPnsresult
12577nsDocShell::GetAuthPrompt(uint32_t aPromptReason, const nsIID& aIID,
12578 void** aResult) {
12579 // a priority prompt request will override a false mAllowAuth setting
12580 bool priorityPrompt = (aPromptReason == PROMPT_PROXY);
12581
12582 if (!mAllowAuth && !priorityPrompt) {
12583 return NS_ERROR_NOT_AVAILABLE;
12584 }
12585
12586 // we're either allowing auth, or it's a proxy request
12587 nsresult rv;
12588 nsCOMPtr<nsIPromptFactory> wwatch =
12589 do_GetService(NS_WINDOWWATCHER_CONTRACTID"@mozilla.org/embedcomp/window-watcher;1", &rv);
12590 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"
, 12590); return rv; } } while (false)
;
12591
12592 rv = EnsureScriptEnvironment();
12593 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"
, 12593); return rv; } } while (false)
;
12594
12595 // Get the an auth prompter for our window so that the parenting
12596 // of the dialogs works as it should when using tabs.
12597
12598 return wwatch->GetPrompt(mScriptGlobal, aIID,
12599 reinterpret_cast<void**>(aResult));
12600}
12601
12602//*****************************************************************************
12603// nsDocShell::nsILoadContext
12604//*****************************************************************************
12605
12606NS_IMETHODIMPnsresult
12607nsDocShell::GetAssociatedWindow(mozIDOMWindowProxy** aWindow) {
12608 CallGetInterface(this, aWindow);
12609 return NS_OK;
12610}
12611
12612NS_IMETHODIMPnsresult
12613nsDocShell::GetTopWindow(mozIDOMWindowProxy** aWindow) {
12614 return mBrowsingContext->GetTopWindow(aWindow);
12615}
12616
12617NS_IMETHODIMPnsresult
12618nsDocShell::GetTopFrameElement(Element** aElement) {
12619 return mBrowsingContext->GetTopFrameElement(aElement);
12620}
12621
12622NS_IMETHODIMPnsresult
12623nsDocShell::GetUseTrackingProtection(bool* aUseTrackingProtection) {
12624 return mBrowsingContext->GetUseTrackingProtection(aUseTrackingProtection);
12625}
12626
12627NS_IMETHODIMPnsresult
12628nsDocShell::SetUseTrackingProtection(bool aUseTrackingProtection) {
12629 return mBrowsingContext->SetUseTrackingProtection(aUseTrackingProtection);
12630}
12631
12632NS_IMETHODIMPnsresult
12633nsDocShell::GetIsContent(bool* aIsContent) {
12634 *aIsContent = (mItemType == typeContent);
12635 return NS_OK;
12636}
12637
12638bool nsDocShell::IsOKToLoadURI(nsIURI* aURI) {
12639 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"
, 12639); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aURI" ") ("
"Must have a URI!" ")"); do { *((volatile int*)__null) = 12639
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
;
12640
12641 if (!mFiredUnloadEvent) {
12642 return true;
12643 }
12644
12645 if (!mLoadingURI) {
12646 return false;
12647 }
12648
12649 bool isPrivateWin = false;
12650 Document* doc = GetDocument();
12651 if (doc) {
12652 isPrivateWin =
12653 doc->NodePrincipal()->OriginAttributesRef().IsPrivateBrowsing();
12654 }
12655
12656 nsCOMPtr<nsIScriptSecurityManager> secMan =
12657 do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID"@mozilla.org/scriptsecuritymanager;1");
12658 return secMan && NS_SUCCEEDED(secMan->CheckSameOriginURI(((bool)(__builtin_expect(!!(!NS_FAILED_impl(secMan->CheckSameOriginURI
( aURI, mLoadingURI, false, isPrivateWin))), 1)))
12659 aURI, mLoadingURI, false, isPrivateWin))((bool)(__builtin_expect(!!(!NS_FAILED_impl(secMan->CheckSameOriginURI
( aURI, mLoadingURI, false, isPrivateWin))), 1)))
;
12660}
12661
12662//
12663// Routines for selection and clipboard
12664//
12665nsresult nsDocShell::GetControllerForCommand(const char* aCommand,
12666 nsIController** aResult) {
12667 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"
, 12667); return NS_ERROR_INVALID_POINTER; } } while (false)
;
12668 *aResult = nullptr;
12669
12670 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"
, 12670); return NS_ERROR_FAILURE; } } while (false)
;
12671
12672 nsCOMPtr<nsPIWindowRoot> root = mScriptGlobal->GetTopWindowRoot();
12673 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"
, 12673); return NS_ERROR_FAILURE; } } while (false)
;
12674
12675 return root->GetControllerForCommand(aCommand, false /* for any window */,
12676 aResult);
12677}
12678
12679NS_IMETHODIMPnsresult
12680nsDocShell::IsCommandEnabled(const char* aCommand, bool* aResult) {
12681 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"
, 12681); return NS_ERROR_INVALID_POINTER; } } while (false)
;
12682 *aResult = false;
12683
12684 nsresult rv = NS_ERROR_FAILURE;
12685
12686 nsCOMPtr<nsIController> controller;
12687 rv = GetControllerForCommand(aCommand, getter_AddRefs(controller));
12688 if (controller) {
12689 rv = controller->IsCommandEnabled(aCommand, aResult);
12690 }
12691
12692 return rv;
12693}
12694
12695NS_IMETHODIMPnsresult
12696nsDocShell::DoCommand(const char* aCommand) {
12697 nsresult rv = NS_ERROR_FAILURE;
12698
12699 nsCOMPtr<nsIController> controller;
12700 rv = GetControllerForCommand(aCommand, getter_AddRefs(controller));
12701 if (controller) {
12702 rv = controller->DoCommand(aCommand);
12703 }
12704
12705 return rv;
12706}
12707
12708NS_IMETHODIMPnsresult
12709nsDocShell::DoCommandWithParams(const char* aCommand,
12710 nsICommandParams* aParams) {
12711 nsCOMPtr<nsIController> controller;
12712 nsresult rv = GetControllerForCommand(aCommand, getter_AddRefs(controller));
12713 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"
, 12713)
) {
12714 return rv;
12715 }
12716
12717 nsCOMPtr<nsICommandController> commandController =
12718 do_QueryInterface(controller, &rv);
12719 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"
, 12719)
) {
12720 return rv;
12721 }
12722
12723 return commandController->DoCommandWithParams(aCommand, aParams);
12724}
12725
12726nsresult nsDocShell::EnsureCommandHandler() {
12727 if (!mCommandManager) {
12728 if (nsCOMPtr<nsPIDOMWindowOuter> domWindow = GetWindow()) {
12729 mCommandManager = new nsCommandManager(domWindow);
12730 }
12731 }
12732 return mCommandManager ? NS_OK : NS_ERROR_FAILURE;
12733}
12734
12735// link handling
12736
12737class OnLinkClickEvent : public Runnable {
12738 public:
12739 OnLinkClickEvent(nsDocShell* aHandler, nsIContent* aContent,
12740 nsDocShellLoadState* aLoadState, bool aNoOpenerImplied,
12741 bool aIsTrusted, nsIPrincipal* aTriggeringPrincipal);
12742
12743 NS_IMETHODvirtual nsresult Run() override {
12744 // We need to set up an AutoJSAPI here for the following reason: When we
12745 // do OnLinkClickSync we'll eventually end up in
12746 // nsGlobalWindow::OpenInternal which only does popup blocking if
12747 // !LegacyIsCallerChromeOrNativeCode(). So we need to fake things so that
12748 // we don't look like native code as far as LegacyIsCallerNativeCode() is
12749 // concerned.
12750 AutoJSAPI jsapi;
12751 if (mIsTrusted || jsapi.Init(mContent->OwnerDoc()->GetScopeObject())) {
12752 mHandler->OnLinkClickSync(mContent, mLoadState, mNoOpenerImplied,
12753 mTriggeringPrincipal);
12754 }
12755 return NS_OK;
12756 }
12757
12758 private:
12759 RefPtr<nsDocShell> mHandler;
12760 nsCOMPtr<nsIContent> mContent;
12761 RefPtr<nsDocShellLoadState> mLoadState;
12762 nsCOMPtr<nsIPrincipal> mTriggeringPrincipal;
12763 bool mNoOpenerImplied;
12764 bool mIsTrusted;
12765};
12766
12767OnLinkClickEvent::OnLinkClickEvent(nsDocShell* aHandler, nsIContent* aContent,
12768 nsDocShellLoadState* aLoadState,
12769 bool aNoOpenerImplied, bool aIsTrusted,
12770 nsIPrincipal* aTriggeringPrincipal)
12771 : mozilla::Runnable("OnLinkClickEvent"),
12772 mHandler(aHandler),
12773 mContent(aContent),
12774 mLoadState(aLoadState),
12775 mTriggeringPrincipal(aTriggeringPrincipal),
12776 mNoOpenerImplied(aNoOpenerImplied),
12777 mIsTrusted(aIsTrusted) {}
12778
12779nsresult nsDocShell::OnLinkClick(
12780 nsIContent* aContent, nsIURI* aURI, const nsAString& aTargetSpec,
12781 const nsAString& aFileName, nsIInputStream* aPostDataStream,
12782 nsIInputStream* aHeadersDataStream, bool aIsUserTriggered, bool aIsTrusted,
12783 nsIPrincipal* aTriggeringPrincipal, nsIContentSecurityPolicy* aCsp) {
12784#ifndef ANDROID
12785 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"
, 12785); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aTriggeringPrincipal"
") (" "Need a valid triggeringPrincipal" ")"); do { *((volatile
int*)__null) = 12785; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
12786#endif
12787 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"
, 12787); MOZ_PretendNoReturn(); } } while (0)
;
12788
12789 if (!IsNavigationAllowed() || !IsOKToLoadURI(aURI)) {
12790 return NS_OK;
12791 }
12792
12793 // On history navigation through Back/Forward buttons, don't execute
12794 // automatic JavaScript redirection such as |anchorElement.click()| or
12795 // |formElement.submit()|.
12796 //
12797 // XXX |formElement.submit()| bypasses this checkpoint because it calls
12798 // nsDocShell::OnLinkClickSync(...) instead.
12799 if (ShouldBlockLoadingForBackButton()) {
12800 return NS_OK;
12801 }
12802
12803 if (aContent->IsEditable()) {
12804 return NS_OK;
12805 }
12806
12807 Document* ownerDoc = aContent->OwnerDoc();
12808 if (nsContentUtils::IsExternalProtocol(aURI)) {
12809 ownerDoc->EnsureNotEnteringAndExitFullscreen();
12810 }
12811
12812 bool noOpenerImplied = false;
12813 nsAutoString target(aTargetSpec);
12814 if (aFileName.IsVoid() &&
12815 ShouldOpenInBlankTarget(aTargetSpec, aURI, aContent, aIsUserTriggered)) {
12816 target = u"_blank";
12817 if (!aTargetSpec.Equals(target)) {
12818 noOpenerImplied = true;
12819 }
12820 }
12821
12822 RefPtr<nsDocShellLoadState> loadState = new nsDocShellLoadState(aURI);
12823 loadState->SetTarget(target);
12824 loadState->SetFileName(aFileName);
12825 loadState->SetPostDataStream(aPostDataStream);
12826 loadState->SetHeadersStream(aHeadersDataStream);
12827 loadState->SetFirstParty(true);
12828 loadState->SetTriggeringPrincipal(
12829 aTriggeringPrincipal ? aTriggeringPrincipal : aContent->NodePrincipal());
12830 loadState->SetPrincipalToInherit(aContent->NodePrincipal());
12831 loadState->SetCsp(aCsp ? aCsp : aContent->GetCsp());
12832 loadState->SetAllowFocusMove(UserActivation::IsHandlingUserInput());
12833
12834 const bool hasValidUserGestureActivation =
12835 ownerDoc->HasValidTransientUserGestureActivation();
12836 loadState->SetHasValidUserGestureActivation(hasValidUserGestureActivation);
12837 loadState->SetTextDirectiveUserActivation(
12838 ownerDoc->ConsumeTextDirectiveUserActivation() ||
12839 hasValidUserGestureActivation);
12840
12841 nsCOMPtr<nsIRunnable> ev =
12842 new OnLinkClickEvent(this, aContent, loadState, noOpenerImplied,
12843 aIsTrusted, aTriggeringPrincipal);
12844 return Dispatch(ev.forget());
12845}
12846
12847bool nsDocShell::ShouldOpenInBlankTarget(const nsAString& aOriginalTarget,
12848 nsIURI* aLinkURI, nsIContent* aContent,
12849 bool aIsUserTriggered) {
12850 if (net::SchemeIsJavascript(aLinkURI)) {
12851 return false;
12852 }
12853
12854 // External links from within app tabs should always open in new tabs
12855 // instead of replacing the app tab's page (Bug 575561)
12856 // nsIURI.host can throw for non-nsStandardURL nsIURIs. If we fail to
12857 // get either host, just return false to use the original target.
12858 nsAutoCString linkHost;
12859 if (NS_FAILED(aLinkURI->GetHost(linkHost))((bool)(__builtin_expect(!!(NS_FAILED_impl(aLinkURI->GetHost
(linkHost))), 0)))
) {
12860 return false;
12861 }
12862
12863 // The targetTopLevelLinkClicksToBlank property on BrowsingContext allows
12864 // privileged code to change the default targeting behaviour. In particular,
12865 // if a user-initiated link click for the (or targetting the) top-level frame
12866 // is detected, we default the target to "_blank" to give it a new
12867 // top-level BrowsingContext.
12868 if (mBrowsingContext->TargetTopLevelLinkClicksToBlank() && aIsUserTriggered &&
12869 ((aOriginalTarget.IsEmpty() && mBrowsingContext->IsTop()) ||
12870 aOriginalTarget == u"_top"_ns)) {
12871 return true;
12872 }
12873
12874 // Don't modify non-default targets.
12875 if (!aOriginalTarget.IsEmpty()) {
12876 return false;
12877 }
12878
12879 // Only check targets that are in extension panels or app tabs.
12880 // (isAppTab will be false for app tab subframes).
12881 nsString mmGroup = mBrowsingContext->Top()->GetMessageManagerGroup();
12882 if (!mmGroup.EqualsLiteral("webext-browsers") &&
12883 !mBrowsingContext->IsAppTab()) {
12884 return false;
12885 }
12886
12887 nsCOMPtr<nsIURI> docURI = aContent->OwnerDoc()->GetDocumentURIObject();
12888 if (!docURI) {
12889 return false;
12890 }
12891
12892 nsAutoCString docHost;
12893 if (NS_FAILED(docURI->GetHost(docHost))((bool)(__builtin_expect(!!(NS_FAILED_impl(docURI->GetHost
(docHost))), 0)))
) {
12894 return false;
12895 }
12896
12897 if (linkHost.Equals(docHost)) {
12898 return false;
12899 }
12900
12901 // Special case: ignore "www" prefix if it is part of host string
12902 return linkHost.Length() < docHost.Length()
12903 ? !docHost.Equals("www."_ns + linkHost)
12904 : !linkHost.Equals("www."_ns + docHost);
12905}
12906
12907static bool ElementCanHaveNoopener(nsIContent* aContent) {
12908 // Make sure we are dealing with either an <A>, <AREA>, or <FORM> element in
12909 // the HTML, XHTML, or SVG namespace.
12910 return aContent->IsAnyOfHTMLElements(nsGkAtoms::a, nsGkAtoms::area,
12911 nsGkAtoms::form) ||
12912 aContent->IsSVGElement(nsGkAtoms::a);
12913}
12914
12915nsresult nsDocShell::OnLinkClickSync(nsIContent* aContent,
12916 nsDocShellLoadState* aLoadState,
12917 bool aNoOpenerImplied,
12918 nsIPrincipal* aTriggeringPrincipal) {
12919 if (!IsNavigationAllowed() || !IsOKToLoadURI(aLoadState->URI())) {
12920 return NS_OK;
12921 }
12922
12923 // XXX When the linking node was HTMLFormElement, it is synchronous event.
12924 // That is, the caller of this method is not |OnLinkClickEvent::Run()|
12925 // but |HTMLFormElement::SubmitSubmission(...)|.
12926 if (aContent->IsHTMLElement(nsGkAtoms::form) &&
12927 ShouldBlockLoadingForBackButton()) {
12928 return NS_OK;
12929 }
12930
12931 if (aContent->IsEditable()) {
12932 return NS_OK;
12933 }
12934
12935 // if the triggeringPrincipal is not passed explicitly, then we
12936 // fall back to using doc->NodePrincipal() as the triggeringPrincipal.
12937 nsCOMPtr<nsIPrincipal> triggeringPrincipal =
12938 aTriggeringPrincipal ? aTriggeringPrincipal : aContent->NodePrincipal();
12939
12940 {
12941 // defer to an external protocol handler if necessary...
12942 nsCOMPtr<nsIExternalProtocolService> extProtService =
12943 do_GetService(NS_EXTERNALPROTOCOLSERVICE_CONTRACTID"@mozilla.org/uriloader/external-protocol-service;1");
12944 if (extProtService) {
12945 nsAutoCString scheme;
12946 aLoadState->URI()->GetScheme(scheme);
12947 if (!scheme.IsEmpty()) {
12948 // if the URL scheme does not correspond to an exposed protocol, then
12949 // we need to hand this link click over to the external protocol
12950 // handler.
12951 bool isExposed;
12952 nsresult rv =
12953 extProtService->IsExposedProtocol(scheme.get(), &isExposed);
12954 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && !isExposed) {
12955 return extProtService->LoadURI(
12956 aLoadState->URI(), triggeringPrincipal, nullptr, mBrowsingContext,
12957 /* aTriggeredExternally */
12958 false,
12959 /* aHasValidUserGestureActivation */
12960 aContent->OwnerDoc()->HasValidTransientUserGestureActivation());
12961 }
12962 }
12963 }
12964 }
12965 uint32_t triggeringSandboxFlags = 0;
12966 uint64_t triggeringWindowId = 0;
12967 bool triggeringStorageAccess = false;
12968 if (mBrowsingContext) {
12969 triggeringSandboxFlags = aContent->OwnerDoc()->GetSandboxFlags();
12970 triggeringWindowId = aContent->OwnerDoc()->InnerWindowID();
12971 triggeringStorageAccess = aContent->OwnerDoc()->UsingStorageAccess();
12972 }
12973
12974 uint32_t flags = INTERNAL_LOAD_FLAGS_NONE;
12975 bool elementCanHaveNoopener = ElementCanHaveNoopener(aContent);
12976 bool triggeringPrincipalIsSystemPrincipal =
12977 aLoadState->TriggeringPrincipal()->IsSystemPrincipal();
12978 if (elementCanHaveNoopener) {
12979 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"
, 12979); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aContent->IsHTMLElement() || aContent->IsSVGElement()"
")"); do { *((volatile int*)__null) = 12979; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12980 nsAutoString relString;
12981 aContent->AsElement()->GetAttr(nsGkAtoms::rel, relString);
12982 nsWhitespaceTokenizerTemplate<nsContentUtils::IsHTMLWhitespace> tok(
12983 relString);
12984
12985 bool targetBlank = aLoadState->Target().LowerCaseEqualsLiteral("_blank");
12986 bool explicitOpenerSet = false;
12987
12988 // The opener behaviour follows a hierarchy, such that if a higher
12989 // priority behaviour is specified, it always takes priority. That
12990 // priority is currently: norefrerer > noopener > opener > default
12991
12992 while (tok.hasMoreTokens()) {
12993 const nsAString& token = tok.nextToken();
12994 if (token.LowerCaseEqualsLiteral("noreferrer")) {
12995 flags |= INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER |
12996 INTERNAL_LOAD_FLAGS_NO_OPENER;
12997 // noreferrer cannot be overwritten by a 'rel=opener'.
12998 explicitOpenerSet = true;
12999 break;
13000 }
13001
13002 if (token.LowerCaseEqualsLiteral("noopener")) {
13003 flags |= INTERNAL_LOAD_FLAGS_NO_OPENER;
13004 explicitOpenerSet = true;
13005 }
13006
13007 if (targetBlank && StaticPrefs::dom_targetBlankNoOpener_enabled() &&
13008 token.LowerCaseEqualsLiteral("opener") && !explicitOpenerSet) {
13009 explicitOpenerSet = true;
13010 }
13011 }
13012
13013 if (targetBlank && StaticPrefs::dom_targetBlankNoOpener_enabled() &&
13014 !explicitOpenerSet && !triggeringPrincipalIsSystemPrincipal) {
13015 flags |= INTERNAL_LOAD_FLAGS_NO_OPENER;
13016 }
13017
13018 if (aNoOpenerImplied) {
13019 flags |= INTERNAL_LOAD_FLAGS_NO_OPENER;
13020 }
13021 }
13022
13023 // Get the owner document of the link that was clicked, this will be
13024 // the document that the link is in, or the last document that the
13025 // link was in. From that document, we'll get the URI to use as the
13026 // referrer, since the current URI in this docshell may be a
13027 // new document that we're in the process of loading.
13028 RefPtr<Document> referrerDoc = aContent->OwnerDoc();
13029
13030 // Now check that the referrerDoc's inner window is the current inner
13031 // window for mScriptGlobal. If it's not, then we don't want to
13032 // follow this link.
13033 nsPIDOMWindowInner* referrerInner = referrerDoc->GetInnerWindow();
13034 if (!mScriptGlobal || !referrerInner ||
13035 mScriptGlobal->GetCurrentInnerWindow() != referrerInner) {
13036 // We're no longer the current inner window
13037 return NS_OK;
13038 }
13039
13040 // referrer could be null here in some odd cases, but that's ok,
13041 // we'll just load the link w/o sending a referrer in those cases.
13042
13043 // If this is an anchor element, grab its type property to use as a hint
13044 nsAutoString typeHint;
13045 RefPtr<HTMLAnchorElement> anchor = HTMLAnchorElement::FromNode(aContent);
13046 if (anchor) {
13047 anchor->GetType(typeHint);
13048 NS_ConvertUTF16toUTF8 utf8Hint(typeHint);
13049 nsAutoCString type, dummy;
13050 NS_ParseRequestContentType(utf8Hint, type, dummy);
13051 CopyUTF8toUTF16(type, typeHint);
13052 }
13053
13054 uint32_t loadType = LOAD_LINK;
13055 if (aLoadState->IsFormSubmission()) {
13056 if (aLoadState->Target().IsEmpty()) {
13057 // We set the right load type here for form submissions with an empty
13058 // target. Form submission with a non-empty target are handled in
13059 // nsDocShell::PerformRetargeting after we've selected the correct target
13060 // BC.
13061 loadType = GetLoadTypeForFormSubmission(GetBrowsingContext(), aLoadState);
13062 }
13063 } else {
13064 // Link click can be triggered inside an onload handler, and we don't want
13065 // to add history entry in this case.
13066 bool inOnLoadHandler = false;
13067 GetIsExecutingOnLoadHandler(&inOnLoadHandler);
13068 if (inOnLoadHandler) {
13069 loadType = LOAD_NORMAL_REPLACE;
13070 }
13071 }
13072
13073 nsCOMPtr<nsIReferrerInfo> referrerInfo =
13074 elementCanHaveNoopener ? new ReferrerInfo(*aContent->AsElement())
13075 : new ReferrerInfo(*referrerDoc);
13076
13077 aLoadState->SetTriggeringSandboxFlags(triggeringSandboxFlags);
13078 aLoadState->SetTriggeringWindowId(triggeringWindowId);
13079 aLoadState->SetTriggeringStorageAccess(triggeringStorageAccess);
13080 aLoadState->SetReferrerInfo(referrerInfo);
13081 aLoadState->SetInternalLoadFlags(flags);
13082 aLoadState->SetTypeHint(NS_ConvertUTF16toUTF8(typeHint));
13083 aLoadState->SetLoadType(loadType);
13084 aLoadState->SetSourceBrowsingContext(mBrowsingContext);
13085
13086 nsresult rv = InternalLoad(aLoadState);
13087
13088 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
13089 nsPingListener::DispatchPings(this, aContent, aLoadState->URI(),
13090 referrerInfo);
13091 }
13092
13093 return rv;
13094}
13095
13096nsresult nsDocShell::OnOverLink(nsIContent* aContent, nsIURI* aURI,
13097 const nsAString& aTargetSpec) {
13098 if (aContent->IsEditable()) {
13099 return NS_OK;
13100 }
13101
13102 nsresult rv = NS_ERROR_FAILURE;
13103
13104 nsCOMPtr<nsIWebBrowserChrome> browserChrome = do_GetInterface(mTreeOwner);
13105 if (!browserChrome) {
13106 return rv;
13107 }
13108
13109 nsCOMPtr<nsIURI> exposableURI = nsIOService::CreateExposableURI(aURI);
13110 nsAutoCString spec;
13111 rv = exposableURI->GetDisplaySpec(spec);
13112 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"
, 13112); return rv; } } while (false)
;
13113
13114 NS_ConvertUTF8toUTF16 uStr(spec);
13115
13116 PredictorPredict(aURI, mCurrentURI, nsINetworkPredictor::PREDICT_LINK,
13117 aContent->NodePrincipal()->OriginAttributesRef(), nullptr);
13118
13119 rv = browserChrome->SetLinkStatus(uStr);
13120 return rv;
13121}
13122
13123nsresult nsDocShell::OnLeaveLink() {
13124 nsCOMPtr<nsIWebBrowserChrome> browserChrome(do_GetInterface(mTreeOwner));
13125 nsresult rv = NS_ERROR_FAILURE;
13126
13127 if (browserChrome) {
13128 rv = browserChrome->SetLinkStatus(u""_ns);
13129 }
13130 return rv;
13131}
13132
13133bool nsDocShell::ShouldBlockLoadingForBackButton() {
13134 if (!(mLoadType & LOAD_CMD_HISTORY) ||
13135 UserActivation::IsHandlingUserInput() ||
13136 !Preferences::GetBool("accessibility.blockjsredirection")) {
13137 return false;
13138 }
13139
13140 bool canGoForward = false;
13141 GetCanGoForward(&canGoForward);
13142 return canGoForward;
13143}
13144
13145//----------------------------------------------------------------------
13146// Web Shell Services API
13147
13148// This functions is only called when a new charset is detected in loading a
13149// document.
13150nsresult nsDocShell::CharsetChangeReloadDocument(
13151 mozilla::NotNull<const mozilla::Encoding*> aEncoding, int32_t aSource) {
13152 // XXX hack. keep the aCharset and aSource wait to pick it up
13153 nsCOMPtr<nsIDocumentViewer> viewer;
13154 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"
, 13154); return NS_ERROR_FAILURE; } } while (false)
;
13155 if (viewer) {
13156 int32_t source;
13157 Unused << viewer->GetReloadEncodingAndSource(&source);
13158 if (aSource > source) {
13159 viewer->SetReloadEncodingAndSource(aEncoding, aSource);
13160 if (eCharsetReloadRequested != mCharsetReloadState) {
13161 mCharsetReloadState = eCharsetReloadRequested;
13162 switch (mLoadType) {
13163 case LOAD_RELOAD_BYPASS_PROXY_AND_CACHE:
13164 return Reload(LOAD_FLAGS_CHARSET_CHANGE | LOAD_FLAGS_BYPASS_CACHE |
13165 LOAD_FLAGS_BYPASS_PROXY);
13166 case LOAD_RELOAD_BYPASS_CACHE:
13167 return Reload(LOAD_FLAGS_CHARSET_CHANGE | LOAD_FLAGS_BYPASS_CACHE);
13168 default:
13169 return Reload(LOAD_FLAGS_CHARSET_CHANGE);
13170 }
13171 }
13172 }
13173 }
13174 // return failure if this request is not accepted due to mCharsetReloadState
13175 return NS_ERROR_DOCSHELL_REQUEST_REJECTED;
13176}
13177
13178nsresult nsDocShell::CharsetChangeStopDocumentLoad() {
13179 if (eCharsetReloadRequested != mCharsetReloadState) {
13180 Stop(nsIWebNavigation::STOP_ALL);
13181 return NS_OK;
13182 }
13183 // return failer if this request is not accepted due to mCharsetReloadState
13184 return NS_ERROR_DOCSHELL_REQUEST_REJECTED;
13185}
13186
13187NS_IMETHODIMPnsresult nsDocShell::ExitPrintPreview() {
13188#if NS_PRINT_PREVIEW1
13189 nsCOMPtr<nsIWebBrowserPrint> viewer = do_QueryInterface(mDocumentViewer);
13190 return viewer->ExitPrintPreview();
13191#else
13192 return NS_OK;
13193#endif
13194}
13195
13196/* [infallible] */
13197NS_IMETHODIMPnsresult nsDocShell::GetIsTopLevelContentDocShell(
13198 bool* aIsTopLevelContentDocShell) {
13199 *aIsTopLevelContentDocShell = false;
13200
13201 if (mItemType == typeContent) {
13202 *aIsTopLevelContentDocShell = mBrowsingContext->IsTopContent();
13203 }
13204
13205 return NS_OK;
13206}
13207
13208// Implements nsILoadContext.originAttributes
13209NS_IMETHODIMPnsresult
13210nsDocShell::GetScriptableOriginAttributes(JSContext* aCx,
13211 JS::MutableHandle<JS::Value> aVal) {
13212 return mBrowsingContext->GetScriptableOriginAttributes(aCx, aVal);
13213}
13214
13215// Implements nsIDocShell.GetOriginAttributes()
13216NS_IMETHODIMPnsresult
13217nsDocShell::GetOriginAttributes(JSContext* aCx,
13218 JS::MutableHandle<JS::Value> aVal) {
13219 return mBrowsingContext->GetScriptableOriginAttributes(aCx, aVal);
13220}
13221
13222bool nsDocShell::ServiceWorkerAllowedToControlWindow(nsIPrincipal* aPrincipal,
13223 nsIURI* aURI) {
13224 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"
, 13224); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPrincipal"
")"); do { *((volatile int*)__null) = 13224; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
13225 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"
, 13225); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aURI" ")")
; do { *((volatile int*)__null) = 13225; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
13226
13227 if (UsePrivateBrowsing() || mBrowsingContext->GetSandboxFlags()) {
13228 return false;
13229 }
13230
13231 nsCOMPtr<nsIDocShellTreeItem> parent;
13232 GetInProcessSameTypeParent(getter_AddRefs(parent));
13233 nsPIDOMWindowOuter* parentOuter = parent ? parent->GetWindow() : nullptr;
13234 nsPIDOMWindowInner* parentInner =
13235 parentOuter ? parentOuter->GetCurrentInnerWindow() : nullptr;
13236
13237 StorageAccess storage =
13238 StorageAllowedForNewWindow(aPrincipal, aURI, parentInner);
13239
13240 // If the partitioned service worker is enabled, service worker is allowed to
13241 // control the window if partition is enabled.
13242 if (StaticPrefs::privacy_partition_serviceWorkers() && parentInner) {
13243 RefPtr<Document> doc = parentInner->GetExtantDoc();
13244
13245 if (doc && StoragePartitioningEnabled(storage, doc->CookieJarSettings())) {
13246 return true;
13247 }
13248 }
13249
13250 return storage == StorageAccess::eAllow;
13251}
13252
13253nsresult nsDocShell::SetOriginAttributes(const OriginAttributes& aAttrs) {
13254 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"
, 13254); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mIsBeingDestroyed"
")"); do { *((volatile int*)__null) = 13254; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
13255 return mBrowsingContext->SetOriginAttributes(aAttrs);
13256}
13257
13258NS_IMETHODIMPnsresult
13259nsDocShell::ResumeRedirectedLoad(uint64_t aIdentifier, int32_t aHistoryIndex) {
13260 RefPtr<nsDocShell> self = this;
13261 RefPtr<ChildProcessChannelListener> cpcl =
13262 ChildProcessChannelListener::GetSingleton();
13263
13264 // Call into InternalLoad with the pending channel when it is received.
13265 cpcl->RegisterCallback(
13266 aIdentifier, [self, aHistoryIndex](
13267 nsDocShellLoadState* aLoadState,
13268 nsTArray<Endpoint<extensions::PStreamFilterParent>>&&
13269 aStreamFilterEndpoints,
13270 nsDOMNavigationTiming* aTiming) {
13271 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"
, 13271); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->GetPendingRedirectedChannel()"
")"); do { *((volatile int*)__null) = 13271; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
13272 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"
, 13272)
) {
13273 aLoadState->GetPendingRedirectedChannel()->CancelWithReason(
13274 NS_BINDING_ABORTED, "nsDocShell::mIsBeingDestroyed"_ns);
13275 return NS_BINDING_ABORTED;
13276 }
13277
13278 self->mLoadType = aLoadState->LoadType();
13279 nsCOMPtr<nsIURI> previousURI;
13280 uint32_t previousFlags = 0;
13281 ExtractLastVisit(aLoadState->GetPendingRedirectedChannel(),
13282 getter_AddRefs(previousURI), &previousFlags);
13283 self->SaveLastVisit(aLoadState->GetPendingRedirectedChannel(),
13284 previousURI, previousFlags);
13285
13286 if (aTiming) {
13287 self->mTiming = new nsDOMNavigationTiming(self, aTiming);
13288 self->mBlankTiming = false;
13289 }
13290
13291 // If we're performing a history load, locate the correct history entry,
13292 // and set the relevant bits on our loadState.
13293 if (aHistoryIndex >= 0 && self->GetSessionHistory() &&
13294 !mozilla::SessionHistoryInParent()) {
13295 nsCOMPtr<nsISHistory> legacySHistory =
13296 self->GetSessionHistory()->LegacySHistory();
13297
13298 nsCOMPtr<nsISHEntry> entry;
13299 nsresult rv = legacySHistory->GetEntryAtIndex(aHistoryIndex,
13300 getter_AddRefs(entry));
13301 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
13302 legacySHistory->InternalSetRequestedIndex(aHistoryIndex);
13303 aLoadState->SetLoadType(LOAD_HISTORY);
13304 aLoadState->SetSHEntry(entry);
13305 }
13306 }
13307
13308 self->InternalLoad(aLoadState);
13309
13310 if (aLoadState->GetOriginalURIString().isSome()) {
13311 // Save URI string in case it's needed later when
13312 // sending to search engine service in EndPageLoad()
13313 self->mOriginalUriString = *aLoadState->GetOriginalURIString();
13314 }
13315
13316 for (auto& endpoint : aStreamFilterEndpoints) {
13317 extensions::StreamFilterParent::Attach(
13318 aLoadState->GetPendingRedirectedChannel(), std::move(endpoint));
13319 }
13320
13321 // If the channel isn't pending, then it means that InternalLoad
13322 // never connected it, and we shouldn't try to continue. This
13323 // can happen even if InternalLoad returned NS_OK.
13324 bool pending = false;
13325 aLoadState->GetPendingRedirectedChannel()->IsPending(&pending);
13326 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"
, 13326); MOZ_PretendNoReturn(); } } while (0)
;
13327 if (!pending) {
13328 return NS_BINDING_ABORTED;
13329 }
13330 return NS_OK;
13331 });
13332 return NS_OK;
13333}
13334
13335NS_IMETHODIMPnsresult
13336nsDocShell::SetOriginAttributes(JS::Handle<JS::Value> aOriginAttributes,
13337 JSContext* aCx) {
13338 OriginAttributes attrs;
13339 if (!aOriginAttributes.isObject() || !attrs.Init(aCx, aOriginAttributes)) {
13340 return NS_ERROR_INVALID_ARG;
13341 }
13342
13343 return SetOriginAttributes(attrs);
13344}
13345
13346NS_IMETHODIMPnsresult
13347nsDocShell::GetAsyncPanZoomEnabled(bool* aOut) {
13348 if (PresShell* presShell = GetPresShell()) {
13349 *aOut = presShell->AsyncPanZoomEnabled();
13350 return NS_OK;
13351 }
13352
13353 // If we don't have a presShell, fall back to the default platform value of
13354 // whether or not APZ is enabled.
13355 *aOut = gfxPlatform::AsyncPanZoomEnabled();
13356 return NS_OK;
13357}
13358
13359bool nsDocShell::HasUnloadedParent() {
13360 for (WindowContext* wc = GetBrowsingContext()->GetParentWindowContext(); wc;
13361 wc = wc->GetParentWindowContext()) {
13362 if (!wc->IsCurrent() || wc->IsDiscarded() ||
13363 wc->GetBrowsingContext()->IsDiscarded()) {
13364 // If a parent is OOP and the parent WindowContext is no
13365 // longer current, we can assume the parent was unloaded.
13366 return true;
13367 }
13368
13369 if (wc->GetBrowsingContext()->IsInProcess() &&
13370 (!wc->GetBrowsingContext()->GetDocShell() ||
13371 wc->GetBrowsingContext()->GetDocShell()->GetIsInUnload())) {
13372 return true;
13373 }
13374 }
13375 return false;
13376}
13377
13378/* static */
13379bool nsDocShell::ShouldUpdateGlobalHistory(uint32_t aLoadType) {
13380 return !(aLoadType == LOAD_BYPASS_HISTORY || aLoadType == LOAD_ERROR_PAGE ||
13381 aLoadType & LOAD_CMD_HISTORY);
13382}
13383
13384void nsDocShell::UpdateGlobalHistoryTitle(nsIURI* aURI) {
13385 if (!mBrowsingContext->GetUseGlobalHistory() || UsePrivateBrowsing()) {
13386 return;
13387 }
13388
13389 // Global history is interested into sub-frame visits only for link-coloring
13390 // purposes, thus title updates are skipped for those.
13391 //
13392 // Moreover, some iframe documents (such as the ones created via
13393 // document.open()) inherit the document uri of the caller, which would cause
13394 // us to override a previously set page title with one from the subframe.
13395 if (IsSubframe()) {
13396 return;
13397 }
13398
13399 if (nsCOMPtr<IHistory> history = components::History::Service()) {
13400 history->SetURITitle(aURI, mTitle);
13401 }
13402}
13403
13404bool nsDocShell::IsInvisible() { return mInvisible; }
13405
13406void nsDocShell::SetInvisible(bool aInvisible) { mInvisible = aInvisible; }
13407
13408/* static */
13409void nsDocShell::MaybeNotifyKeywordSearchLoading(const nsString& aProvider,
13410 const nsString& aKeyword) {
13411 if (aProvider.IsEmpty()) {
13412 return;
13413 }
13414 nsresult rv;
13415 nsCOMPtr<nsISupportsString> isupportsString =
13416 do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID"@mozilla.org/supports-string;1", &rv);
13417 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"
, 13417); return; } } while (false)
;
13418
13419 rv = isupportsString->SetData(aProvider);
13420 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"
, 13420); return; } } while (false)
;
13421
13422 nsCOMPtr<nsIObserverService> obsSvc = services::GetObserverService();
13423 if (obsSvc) {
13424 // Note that "keyword-search" refers to a search via the url
13425 // bar, not a bookmarks keyword search.
13426 obsSvc->NotifyObservers(isupportsString, "keyword-search", aKeyword.get());
13427 }
13428}
13429
13430NS_IMETHODIMPnsresult
13431nsDocShell::ShouldPrepareForIntercept(nsIURI* aURI, nsIChannel* aChannel,
13432 bool* aShouldIntercept) {
13433 return mInterceptController->ShouldPrepareForIntercept(aURI, aChannel,
13434 aShouldIntercept);
13435}
13436
13437NS_IMETHODIMPnsresult
13438nsDocShell::ChannelIntercepted(nsIInterceptedChannel* aChannel) {
13439 return mInterceptController->ChannelIntercepted(aChannel);
13440}
13441
13442bool nsDocShell::InFrameSwap() {
13443 RefPtr<nsDocShell> shell = this;
13444 do {
13445 if (shell->mInFrameSwap) {
13446 return true;
13447 }
13448 shell = shell->GetInProcessParentDocshell();
13449 } while (shell);
13450 return false;
13451}
13452
13453UniquePtr<ClientSource> nsDocShell::TakeInitialClientSource() {
13454 return std::move(mInitialClientSource);
13455}
13456
13457NS_IMETHODIMPnsresult
13458nsDocShell::GetEditingSession(nsIEditingSession** aEditSession) {
13459 if (!NS_SUCCEEDED(EnsureEditorData())((bool)(__builtin_expect(!!(!NS_FAILED_impl(EnsureEditorData(
))), 1)))
) {
13460 return NS_ERROR_FAILURE;
13461 }
13462
13463 *aEditSession = do_AddRef(mEditorData->GetEditingSession()).take();
13464 return *aEditSession ? NS_OK : NS_ERROR_FAILURE;
13465}
13466
13467NS_IMETHODIMPnsresult
13468nsDocShell::GetScriptableBrowserChild(nsIBrowserChild** aBrowserChild) {
13469 *aBrowserChild = GetBrowserChild().take();
13470 return *aBrowserChild ? NS_OK : NS_ERROR_FAILURE;
13471}
13472
13473already_AddRefed<nsIBrowserChild> nsDocShell::GetBrowserChild() {
13474 nsCOMPtr<nsIBrowserChild> tc = do_QueryReferent(mBrowserChild);
13475 return tc.forget();
13476}
13477
13478nsCommandManager* nsDocShell::GetCommandManager() {
13479 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"
, 13479); return nullptr; } } while (false)
;
13480 return mCommandManager;
13481}
13482
13483NS_IMETHODIMP_(void)void
13484nsDocShell::GetOriginAttributes(mozilla::OriginAttributes& aAttrs) {
13485 mBrowsingContext->GetOriginAttributes(aAttrs);
13486}
13487
13488HTMLEditor* nsIDocShell::GetHTMLEditor() {
13489 nsDocShell* docShell = static_cast<nsDocShell*>(this);
13490 return docShell->GetHTMLEditorInternal();
13491}
13492
13493nsresult nsIDocShell::SetHTMLEditor(HTMLEditor* aHTMLEditor) {
13494 nsDocShell* docShell = static_cast<nsDocShell*>(this);
13495 return docShell->SetHTMLEditorInternal(aHTMLEditor);
13496}
13497
13498#define MATRIX_LENGTH 20
13499
13500NS_IMETHODIMPnsresult
13501nsDocShell::SetColorMatrix(const nsTArray<float>& aMatrix) {
13502 if (aMatrix.Length() == MATRIX_LENGTH) {
13503 mColorMatrix.reset(new gfx::Matrix5x4());
13504 static_assert(
13505 MATRIX_LENGTH * sizeof(float) == sizeof(mColorMatrix->components),
13506 "Size mismatch for our memcpy");
13507 memcpy(mColorMatrix->components, aMatrix.Elements(),
13508 sizeof(mColorMatrix->components));
13509 } else if (aMatrix.Length() == 0) {
13510 mColorMatrix.reset();
13511 } else {
13512 return NS_ERROR_INVALID_ARG;
13513 }
13514
13515 PresShell* presShell = GetPresShell();
13516 if (!presShell) {
13517 return NS_ERROR_FAILURE;
13518 }
13519
13520 nsIFrame* frame = presShell->GetRootFrame();
13521 if (!frame) {
13522 return NS_ERROR_FAILURE;
13523 }
13524
13525 frame->SchedulePaint();
13526
13527 return NS_OK;
13528}
13529
13530NS_IMETHODIMPnsresult
13531nsDocShell::GetColorMatrix(nsTArray<float>& aMatrix) {
13532 if (mColorMatrix) {
13533 aMatrix.SetLength(MATRIX_LENGTH);
13534 static_assert(
13535 MATRIX_LENGTH * sizeof(float) == sizeof(mColorMatrix->components),
13536 "Size mismatch for our memcpy");
13537 memcpy(aMatrix.Elements(), mColorMatrix->components,
13538 MATRIX_LENGTH * sizeof(float));
13539 }
13540
13541 return NS_OK;
13542}
13543
13544#undef MATRIX_LENGTH
13545
13546NS_IMETHODIMPnsresult
13547nsDocShell::GetIsForceReloading(bool* aForceReload) {
13548 *aForceReload = IsForceReloading();
13549 return NS_OK;
13550}
13551
13552bool nsDocShell::IsForceReloading() { return IsForceReloadType(mLoadType); }
13553
13554NS_IMETHODIMPnsresult
13555nsDocShell::GetBrowsingContextXPCOM(BrowsingContext** aBrowsingContext) {
13556 *aBrowsingContext = do_AddRef(mBrowsingContext).take();
13557 return NS_OK;
13558}
13559
13560BrowsingContext* nsDocShell::GetBrowsingContext() { return mBrowsingContext; }
13561
13562bool nsDocShell::GetIsAttemptingToNavigate() {
13563 // XXXbz the document.open spec says to abort even if there's just a
13564 // queued navigation task, sort of. It's not clear whether browsers
13565 // actually do that, and we didn't use to do it, so for now let's
13566 // not do that.
13567 // https://github.com/whatwg/html/issues/3447 tracks the spec side of this.
13568 if (mDocumentRequest) {
13569 // There's definitely a navigation in progress.
13570 return true;
13571 }
13572
13573 // javascript: channels have slightly weird behavior: they're LOAD_BACKGROUND
13574 // until the script runs, which means they're not sending loadgroup
13575 // notifications and hence not getting set as mDocumentRequest. Look through
13576 // our loadgroup for document-level javascript: loads.
13577 if (!mLoadGroup) {
13578 return false;
13579 }
13580
13581 nsCOMPtr<nsISimpleEnumerator> requests;
13582 mLoadGroup->GetRequests(getter_AddRefs(requests));
13583 bool hasMore = false;
13584 while (NS_SUCCEEDED(requests->HasMoreElements(&hasMore))((bool)(__builtin_expect(!!(!NS_FAILED_impl(requests->HasMoreElements
(&hasMore))), 1)))
&& hasMore) {
13585 nsCOMPtr<nsISupports> elem;
13586 requests->GetNext(getter_AddRefs(elem));
13587 nsCOMPtr<nsIScriptChannel> scriptChannel(do_QueryInterface(elem));
13588 if (!scriptChannel) {
13589 continue;
13590 }
13591
13592 if (scriptChannel->GetIsDocumentLoad()) {
13593 // This is a javascript: load that might lead to a new document,
13594 // hence a navigation.
13595 return true;
13596 }
13597 }
13598
13599 return mCheckingSessionHistory;
13600}
13601
13602void nsDocShell::SetLoadingSessionHistoryInfo(
13603 const mozilla::dom::LoadingSessionHistoryInfo& aLoadingInfo,
13604 bool aNeedToReportActiveAfterLoadingBecomesActive) {
13605 // FIXME Would like to assert this, but can't yet.
13606 // MOZ_ASSERT(!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, "Setting the loading entry on nsDocShell %p to %s"
, this, aLoadingInfo.mInfo.GetURI()->GetSpecOrDefault().get
()); } } while (0)
13608 ("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)
13609 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)
;
13610 mLoadingEntry = MakeUnique<LoadingSessionHistoryInfo>(aLoadingInfo);
13611 mNeedToReportActiveAfterLoadingBecomesActive =
13612 aNeedToReportActiveAfterLoadingBecomesActive;
13613}
13614
13615void nsDocShell::MoveLoadingToActiveEntry(bool aPersist, bool aExpired,
13616 uint32_t aCacheKey,
13617 nsIURI* aPreviousURI) {
13618 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"
, 13618); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mozilla::SessionHistoryInParent()"
")"); do { *((volatile int*)__null) = 13618; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
13619
13620 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)
13621 ("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)
;
13622
13623 UniquePtr<SessionHistoryInfo> previousActiveEntry(mActiveEntry.release());
13624 mozilla::UniquePtr<mozilla::dom::LoadingSessionHistoryInfo> loadingEntry;
13625 mActiveEntryIsLoadingFromSessionHistory =
13626 mLoadingEntry && mLoadingEntry->mLoadIsFromSessionHistory;
13627 if (mLoadingEntry) {
13628 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)
13629 ("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)
13630 "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)
13631 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)
;
13632 mActiveEntry = MakeUnique<SessionHistoryInfo>(mLoadingEntry->mInfo);
13633 mLoadingEntry.swap(loadingEntry);
13634 if (!mActiveEntryIsLoadingFromSessionHistory) {
13635 if (mNeedToReportActiveAfterLoadingBecomesActive) {
13636 // Needed to pass various history length WPTs.
13637 mBrowsingContext->SetActiveSessionHistoryEntry(
13638 mozilla::Nothing(), mActiveEntry.get(), mLoadType,
13639 /* aUpdatedCacheKey = */ 0, false);
13640 }
13641 mBrowsingContext->IncrementHistoryEntryCountForBrowsingContext();
13642 }
13643 }
13644 mNeedToReportActiveAfterLoadingBecomesActive = false;
13645
13646 if (mActiveEntry) {
13647 if (aCacheKey != 0) {
13648 mActiveEntry->SetCacheKey(aCacheKey);
13649 }
13650 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"
, 13650); AnnotateMozCrashReason("MOZ_ASSERT" "(" "loadingEntry"
")"); do { *((volatile int*)__null) = 13650; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
13651 uint32_t loadType =
13652 mLoadType == LOAD_ERROR_PAGE ? mFailedLoadType : mLoadType;
13653
13654 if (loadingEntry->mLoadId != UINT64_MAX(18446744073709551615UL)) {
13655 // We're passing in mCurrentURI, which could be null. SessionHistoryCommit
13656 // does require a non-null uri if this is for a refresh load of the same
13657 // URI, but in that case mCurrentURI won't be null here.
13658 mBrowsingContext->SessionHistoryCommit(
13659 *loadingEntry, loadType, aPreviousURI, previousActiveEntry.get(),
13660 aPersist, false, aExpired, aCacheKey);
13661 }
13662 }
13663}
13664
13665static bool IsFaviconLoad(nsIRequest* aRequest) {
13666 nsCOMPtr<nsIChannel> channel = do_QueryInterface(aRequest);
13667 if (!channel) {
13668 return false;
13669 }
13670
13671 nsCOMPtr<nsILoadInfo> li = channel->LoadInfo();
13672 return li && li->InternalContentPolicyType() ==
13673 nsIContentPolicy::TYPE_INTERNAL_IMAGE_FAVICON;
13674}
13675
13676void nsDocShell::RecordSingleChannelId(bool aStartRequest,
13677 nsIRequest* aRequest) {
13678 // Ignore favicon loads, they don't need to block caching.
13679 if (IsFaviconLoad(aRequest)) {
13680 return;
13681 }
13682
13683 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"
, 13683); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mRequestForBlockingFromBFCacheCount > 0"
")"); do { *((volatile int*)__null) = 13683; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false); } } while
(false)
;
13684
13685 mRequestForBlockingFromBFCacheCount += aStartRequest ? 1 : -1;
13686
13687 if (mBrowsingContext->GetCurrentWindowContext()) {
13688 // We have three states: no request, one request with an id and
13689 // eiher one request without an id or multiple requests. Nothing() is no
13690 // request, Some(non-zero) is one request with an id and Some(0) is one
13691 // request without an id or multiple requests.
13692 Maybe<uint64_t> singleChannelId;
13693 if (mRequestForBlockingFromBFCacheCount > 1) {
13694 singleChannelId = Some(0);
13695 } else if (mRequestForBlockingFromBFCacheCount == 1) {
13696 nsCOMPtr<nsIIdentChannel> identChannel;
13697 if (aStartRequest) {
13698 identChannel = do_QueryInterface(aRequest);
13699 } else {
13700 // aChannel is the channel that's being removed, but we need to check if
13701 // the remaining channel in the loadgroup has an id.
13702 nsCOMPtr<nsISimpleEnumerator> requests;
13703 mLoadGroup->GetRequests(getter_AddRefs(requests));
13704 for (const auto& request : SimpleEnumerator<nsIRequest>(requests)) {
13705 if (!IsFaviconLoad(request) &&
13706 !!(identChannel = do_QueryInterface(request))) {
13707 break;
13708 }
13709 }
13710 }
13711
13712 if (identChannel) {
13713 singleChannelId = Some(identChannel->ChannelId());
13714 } else {
13715 singleChannelId = Some(0);
13716 }
13717 } else {
13718 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"
, 13718); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mRequestForBlockingFromBFCacheCount == 0"
")"); do { *((volatile int*)__null) = 13718; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
13719 singleChannelId = Nothing();
13720 }
13721
13722 if (MOZ_UNLIKELY(MOZ_LOG_TEST(gSHIPBFCacheLog, LogLevel::Verbose))(__builtin_expect(!!((__builtin_expect(!!(mozilla::detail::log_test
(gSHIPBFCacheLog, LogLevel::Verbose)), 0))), 0))
) {
13723 nsAutoCString uri("[no uri]");
13724 if (mCurrentURI) {
13725 uri = mCurrentURI->GetSpecOrDefault();
13726 }
13727 if (singleChannelId.isNothing()) {
13728 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)
13729 ("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)
13730 "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)
13731 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)
;
13732 } else if (singleChannelId.value() == 0) {
13733 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)
13734 ("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)
13735 "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)
13736 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)
;
13737 } else {
13738 MOZ_LOG(gSHIPBFCacheLog, LogLevel::Verbose,do { const ::mozilla::LogModule* moz_real_module = gSHIPBFCacheLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Verbose)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Verbose, "Loadgroup for %s has one request with id %"
"l" "u" " relevant for blocking BFCache", uri.get(), singleChannelId
.value()); } } while (0)
13739 ("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)
13740 " 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)
13741 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)
;
13742 }
13743 }
13744
13745 if (mSingleChannelId != singleChannelId) {
13746 mSingleChannelId = singleChannelId;
13747 WindowGlobalChild* wgc =
13748 mBrowsingContext->GetCurrentWindowContext()->GetWindowGlobalChild();
13749 if (wgc) {
13750 wgc->SendSetSingleChannelId(singleChannelId);
13751 }
13752 }
13753 }
13754}
13755
13756NS_IMETHODIMPnsresult
13757nsDocShell::OnStartRequest(nsIRequest* aRequest) {
13758 if (MOZ_UNLIKELY(MOZ_LOG_TEST(gSHIPBFCacheLog, LogLevel::Verbose))(__builtin_expect(!!((__builtin_expect(!!(mozilla::detail::log_test
(gSHIPBFCacheLog, LogLevel::Verbose)), 0))), 0))
) {
13759 nsAutoCString uri("[no uri]");
13760 if (mCurrentURI) {
13761 uri = mCurrentURI->GetSpecOrDefault();
13762 }
13763 nsAutoCString name;
13764 aRequest->GetName(name);
13765 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)
13766 ("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)
;
13767 }
13768 RecordSingleChannelId(true, aRequest);
13769 return nsDocLoader::OnStartRequest(aRequest);
13770}
13771
13772NS_IMETHODIMPnsresult
13773nsDocShell::OnStopRequest(nsIRequest* aRequest, nsresult aStatusCode) {
13774 if (MOZ_UNLIKELY(MOZ_LOG_TEST(gSHIPBFCacheLog, LogLevel::Verbose))(__builtin_expect(!!((__builtin_expect(!!(mozilla::detail::log_test
(gSHIPBFCacheLog, LogLevel::Verbose)), 0))), 0))
) {
13775 nsAutoCString uri("[no uri]");
13776 if (mCurrentURI) {
13777 uri = mCurrentURI->GetSpecOrDefault();
13778 }
13779 nsAutoCString name;
13780 aRequest->GetName(name);
13781 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)
13782 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)
13783 ("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)
;
13784 }
13785 RecordSingleChannelId(false, aRequest);
13786 return nsDocLoader::OnStopRequest(aRequest, aStatusCode);
13787}
13788
13789void nsDocShell::MaybeDisconnectChildListenersOnPageHide() {
13790 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"
, 13790); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "XRE_IsContentProcess()"
")"); do { *((volatile int*)__null) = 13790; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
13791
13792 if (mChannelToDisconnectOnPageHide != 0 && mLoadGroup) {
13793 nsCOMPtr<nsISimpleEnumerator> requests;
13794 mLoadGroup->GetRequests(getter_AddRefs(requests));
13795 for (const auto& request : SimpleEnumerator<nsIRequest>(requests)) {
13796 RefPtr<DocumentChannel> channel = do_QueryObject(request);
13797 if (channel && channel->ChannelId() == mChannelToDisconnectOnPageHide) {
13798 static_cast<DocumentChannelChild*>(channel.get())
13799 ->DisconnectChildListeners(NS_BINDING_ABORTED, NS_BINDING_ABORTED);
13800 }
13801 }
13802 mChannelToDisconnectOnPageHide = 0;
13803 }
13804}