Bug Summary

File:var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp
Warning:line 3504, 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 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/bin/../lib/gcc/x86_64-linux-gnu/13/../../../../include/c++/13 -internal-isystem /usr/bin/../lib/gcc/x86_64-linux-gnu/13/../../../../include/x86_64-linux-gnu/c++/13 -internal-isystem /usr/bin/../lib/gcc/x86_64-linux-gnu/13/../../../../include/c++/13/backward -internal-isystem /usr/lib/llvm-18/lib/clang/18/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-linux-gnu/13/../../../../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-error=deprecated -Wno-error=deprecated-anon-enum-enum-conversion -Wno-error=deprecated-enum-enum-conversion -Wno-error=deprecated-pragma -Wno-error=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-01-04-012207-8495-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/ScrollTypes.h"
39#include "mozilla/SimpleEnumerator.h"
40#include "mozilla/StaticPrefs_browser.h"
41#include "mozilla/StaticPrefs_docshell.h"
42#include "mozilla/StaticPrefs_dom.h"
43#include "mozilla/StaticPrefs_extensions.h"
44#include "mozilla/StaticPrefs_privacy.h"
45#include "mozilla/StaticPrefs_security.h"
46#include "mozilla/StaticPrefs_ui.h"
47#include "mozilla/StaticPrefs_fission.h"
48#include "mozilla/StartupTimeline.h"
49#include "mozilla/StorageAccess.h"
50#include "mozilla/StoragePrincipalHelper.h"
51#include "mozilla/Telemetry.h"
52
53#include "mozilla/Unused.h"
54#include "mozilla/WidgetUtils.h"
55
56#include "mozilla/dom/AutoEntryScript.h"
57#include "mozilla/dom/ChildProcessChannelListener.h"
58#include "mozilla/dom/ClientChannelHelper.h"
59#include "mozilla/dom/ClientHandle.h"
60#include "mozilla/dom/ClientInfo.h"
61#include "mozilla/dom/ClientManager.h"
62#include "mozilla/dom/ClientSource.h"
63#include "mozilla/dom/ContentChild.h"
64#include "mozilla/dom/ContentFrameMessageManager.h"
65#include "mozilla/dom/DocGroup.h"
66#include "mozilla/dom/Element.h"
67#include "mozilla/dom/HTMLAnchorElement.h"
68#include "mozilla/dom/HTMLIFrameElement.h"
69#include "mozilla/dom/PerformanceNavigation.h"
70#include "mozilla/dom/PermissionMessageUtils.h"
71#include "mozilla/dom/PopupBlocker.h"
72#include "mozilla/dom/ScreenOrientation.h"
73#include "mozilla/dom/ScriptSettings.h"
74#include "mozilla/dom/ServiceWorkerInterceptController.h"
75#include "mozilla/dom/ServiceWorkerUtils.h"
76#include "mozilla/dom/SessionHistoryEntry.h"
77#include "mozilla/dom/SessionStorageManager.h"
78#include "mozilla/dom/SessionStoreChangeListener.h"
79#include "mozilla/dom/SessionStoreChild.h"
80#include "mozilla/dom/SessionStoreUtils.h"
81#include "mozilla/dom/BrowserChild.h"
82#include "mozilla/dom/ToJSValue.h"
83#include "mozilla/dom/UserActivation.h"
84#include "mozilla/dom/ChildSHistory.h"
85#include "mozilla/dom/nsCSPContext.h"
86#include "mozilla/dom/nsHTTPSOnlyUtils.h"
87#include "mozilla/dom/LoadURIOptionsBinding.h"
88#include "mozilla/dom/JSWindowActorChild.h"
89#include "mozilla/dom/DocumentBinding.h"
90#include "mozilla/ipc/ProtocolUtils.h"
91#include "mozilla/net/DocumentChannel.h"
92#include "mozilla/net/DocumentChannelChild.h"
93#include "mozilla/net/ParentChannelWrapper.h"
94#include "mozilla/net/UrlClassifierFeatureFactory.h"
95#include "ReferrerInfo.h"
96
97#include "nsIAuthPrompt.h"
98#include "nsIAuthPrompt2.h"
99#include "nsICachingChannel.h"
100#include "nsICaptivePortalService.h"
101#include "nsIChannel.h"
102#include "nsIChannelEventSink.h"
103#include "nsIClassOfService.h"
104#include "nsIConsoleReportCollector.h"
105#include "nsIContent.h"
106#include "nsIContentInlines.h"
107#include "nsIContentSecurityPolicy.h"
108#include "nsIController.h"
109#include "nsIDocShellTreeItem.h"
110#include "nsIDocShellTreeOwner.h"
111#include "nsIDocumentViewer.h"
112#include "mozilla/dom/Document.h"
113#include "nsHTMLDocument.h"
114#include "nsIDocumentLoaderFactory.h"
115#include "nsIDOMWindow.h"
116#include "nsIEditingSession.h"
117#include "nsIEffectiveTLDService.h"
118#include "nsIExternalProtocolService.h"
119#include "nsIFormPOSTActionChannel.h"
120#include "nsIFrame.h"
121#include "nsIGlobalObject.h"
122#include "nsIHttpChannel.h"
123#include "nsIHttpChannelInternal.h"
124#include "nsIIDNService.h"
125#include "nsIInputStreamChannel.h"
126#include "nsIInterfaceRequestorUtils.h"
127#include "nsILayoutHistoryState.h"
128#include "nsILoadInfo.h"
129#include "nsILoadURIDelegate.h"
130#include "nsIMultiPartChannel.h"
131#include "nsINestedURI.h"
132#include "nsINetworkPredictor.h"
133#include "nsINode.h"
134#include "nsINSSErrorsService.h"
135#include "nsIObserverService.h"
136#include "nsIOService.h"
137#include "nsIPrincipal.h"
138#include "nsIPrivacyTransitionObserver.h"
139#include "nsIPrompt.h"
140#include "nsIPromptCollection.h"
141#include "nsIPromptFactory.h"
142#include "nsIPublicKeyPinningService.h"
143#include "nsIReflowObserver.h"
144#include "nsIScriptChannel.h"
145#include "nsIScriptObjectPrincipal.h"
146#include "nsIScriptSecurityManager.h"
147#include "nsIScrollableFrame.h"
148#include "nsIScrollObserver.h"
149#include "nsISupportsPrimitives.h"
150#include "nsISecureBrowserUI.h"
151#include "nsISeekableStream.h"
152#include "nsISelectionDisplay.h"
153#include "nsISHEntry.h"
154#include "nsISiteSecurityService.h"
155#include "nsISocketProvider.h"
156#include "nsIStringBundle.h"
157#include "nsIStructuredCloneContainer.h"
158#include "nsIBrowserChild.h"
159#include "nsITextToSubURI.h"
160#include "nsITimedChannel.h"
161#include "nsITimer.h"
162#include "nsITransportSecurityInfo.h"
163#include "nsIUploadChannel.h"
164#include "nsIURIFixup.h"
165#include "nsIURIMutator.h"
166#include "nsIURILoader.h"
167#include "nsIViewSourceChannel.h"
168#include "nsIWebBrowserChrome.h"
169#include "nsIWebBrowserChromeFocus.h"
170#include "nsIWebBrowserFind.h"
171#include "nsIWebProgress.h"
172#include "nsIWidget.h"
173#include "nsIWindowWatcher.h"
174#include "nsIWritablePropertyBag2.h"
175#include "nsIX509Cert.h"
176#include "nsIXULRuntime.h"
177
178#include "nsCommandManager.h"
179#include "nsPIDOMWindow.h"
180#include "nsPIWindowRoot.h"
181
182#include "IHistory.h"
183#include "IUrlClassifierUITelemetry.h"
184
185#include "nsArray.h"
186#include "nsArrayUtils.h"
187#include "nsCExternalHandlerService.h"
188#include "nsContentDLF.h"
189#include "nsContentPolicyUtils.h" // NS_CheckContentLoadPolicy(...)
190#include "nsContentSecurityManager.h"
191#include "nsContentSecurityUtils.h"
192#include "nsContentUtils.h"
193#include "nsCURILoader.h"
194#include "nsDocShellCID.h"
195#include "nsDocShellEditorData.h"
196#include "nsDocShellEnumerator.h"
197#include "nsDocShellLoadState.h"
198#include "nsDocShellLoadTypes.h"
199#include "nsDOMCID.h"
200#include "nsDOMNavigationTiming.h"
201#include "nsDSURIContentListener.h"
202#include "nsEditingSession.h"
203#include "nsError.h"
204#include "nsEscape.h"
205#include "nsFocusManager.h"
206#include "nsGlobalWindowInner.h"
207#include "nsGlobalWindowOuter.h"
208#include "nsJSEnvironment.h"
209#include "nsNetCID.h"
210#include "nsNetUtil.h"
211#include "nsObjectLoadingContent.h"
212#include "nsPingListener.h"
213#include "nsPoint.h"
214#include "nsQueryObject.h"
215#include "nsQueryActor.h"
216#include "nsRect.h"
217#include "nsRefreshTimer.h"
218#include "nsSandboxFlags.h"
219#include "nsSHEntry.h"
220#include "nsSHistory.h"
221#include "nsSHEntry.h"
222#include "nsStructuredCloneContainer.h"
223#include "nsSubDocumentFrame.h"
224#include "nsURILoader.h"
225#include "nsURLHelper.h"
226#include "nsView.h"
227#include "nsViewManager.h"
228#include "nsViewSourceHandler.h"
229#include "nsWebBrowserFind.h"
230#include "nsWhitespaceTokenizer.h"
231#include "nsWidgetsCID.h"
232#include "nsXULAppAPI.h"
233
234#include "ThirdPartyUtil.h"
235#include "GeckoProfiler.h"
236#include "mozilla/NullPrincipal.h"
237#include "Navigator.h"
238#include "prenv.h"
239#include "mozilla/ipc/URIUtils.h"
240#include "sslerr.h"
241#include "mozpkix/pkix.h"
242#include "NSSErrorsService.h"
243
244#include "nsDocShellTelemetryUtils.h"
245
246#ifdef MOZ_PLACES1
247# include "nsIFaviconService.h"
248# include "mozIPlacesPendingOperation.h"
249#endif
250
251#if NS_PRINT_PREVIEW1
252# include "nsIDocumentViewerPrint.h"
253# include "nsIWebBrowserPrint.h"
254#endif
255
256using namespace mozilla;
257using namespace mozilla::dom;
258using namespace mozilla::net;
259
260using mozilla::ipc::Endpoint;
261
262// Threshold value in ms for META refresh based redirects
263#define REFRESH_REDIRECT_TIMER15000 15000
264
265static mozilla::LazyLogModule gCharsetMenuLog("CharsetMenu");
266
267#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)
\
268 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)
269
270#ifdef DEBUG1
271unsigned long nsDocShell::gNumberOfDocShells = 0;
272static uint64_t gDocshellIDCounter = 0;
273
274static mozilla::LazyLogModule gDocShellLog("nsDocShell");
275static mozilla::LazyLogModule gDocShellAndDOMWindowLeakLogging(
276 "DocShellAndDOMWindowLeak");
277#endif
278static mozilla::LazyLogModule gDocShellLeakLog("nsDocShellLeak");
279extern mozilla::LazyLogModule gPageCacheLog;
280mozilla::LazyLogModule gSHLog("SessionHistory");
281extern mozilla::LazyLogModule gSHIPBFCacheLog;
282
283const char kAppstringsBundleURL[] =
284 "chrome://global/locale/appstrings.properties";
285
286static bool IsTopLevelDoc(BrowsingContext* aBrowsingContext,
287 nsILoadInfo* aLoadInfo) {
288 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"
, 288); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aBrowsingContext"
")"); do { *((volatile int*)__null) = 288; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
289 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"
, 289); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadInfo" ")"
); do { *((volatile int*)__null) = 289; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
290
291 if (aLoadInfo->GetExternalContentPolicyType() !=
292 ExtContentPolicy::TYPE_DOCUMENT) {
293 return false;
294 }
295
296 return aBrowsingContext->IsTopContent();
297}
298
299// True if loading for top level document loading in active tab.
300static bool IsUrgentStart(BrowsingContext* aBrowsingContext,
301 nsILoadInfo* aLoadInfo, uint32_t aLoadType) {
302 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"
, 302); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aBrowsingContext"
")"); do { *((volatile int*)__null) = 302; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
303 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"
, 303); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadInfo" ")"
); do { *((volatile int*)__null) = 303; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
304
305 if (!IsTopLevelDoc(aBrowsingContext, aLoadInfo)) {
306 return false;
307 }
308
309 if (aLoadType &
310 (nsIDocShell::LOAD_CMD_NORMAL | nsIDocShell::LOAD_CMD_HISTORY)) {
311 return true;
312 }
313
314 return aBrowsingContext->IsActive();
315}
316
317nsDocShell::nsDocShell(BrowsingContext* aBrowsingContext,
318 uint64_t aContentWindowID)
319 : nsDocLoader(true),
320 mContentWindowID(aContentWindowID),
321 mBrowsingContext(aBrowsingContext),
322 mParentCharset(nullptr),
323 mTreeOwner(nullptr),
324 mScrollbarPref(ScrollbarPreference::Auto),
325 mCharsetReloadState(eCharsetReloadInit),
326 mParentCharsetSource(0),
327 mFrameMargins(-1, -1),
328 mItemType(aBrowsingContext->IsContent() ? typeContent : typeChrome),
329 mPreviousEntryIndex(-1),
330 mLoadedEntryIndex(-1),
331 mBusyFlags(BUSY_FLAGS_NONE),
332 mAppType(nsIDocShell::APP_TYPE_UNKNOWN),
333 mLoadType(0),
334 mFailedLoadType(0),
335 mMetaViewportOverride(nsIDocShell::META_VIEWPORT_OVERRIDE_NONE),
336 mChannelToDisconnectOnPageHide(0),
337 mCreatingDocument(false),
338#ifdef DEBUG1
339 mInEnsureScriptEnv(false),
340#endif
341 mInitialized(false),
342 mAllowSubframes(true),
343 mAllowMetaRedirects(true),
344 mAllowImages(true),
345 mAllowMedia(true),
346 mAllowDNSPrefetch(true),
347 mAllowWindowControl(true),
348 mCSSErrorReportingEnabled(false),
349 mAllowAuth(mItemType == typeContent),
350 mAllowKeywordFixup(false),
351 mDisableMetaRefreshWhenInactive(false),
352 mWindowDraggingAllowed(false),
353 mInFrameSwap(false),
354 mFiredUnloadEvent(false),
355 mEODForCurrentDocument(false),
356 mURIResultedInDocument(false),
357 mIsBeingDestroyed(false),
358 mIsExecutingOnLoadHandler(false),
359 mSavingOldViewer(false),
360 mInvisible(false),
361 mHasLoadedNonBlankURI(false),
362 mBlankTiming(false),
363 mTitleValidForCurrentURI(false),
364 mWillChangeProcess(false),
365 mIsNavigating(false),
366 mForcedAutodetection(false),
367 mCheckingSessionHistory(false),
368 mNeedToReportActiveAfterLoadingBecomesActive(false) {
369 // If no outer window ID was provided, generate a new one.
370 if (aContentWindowID == 0) {
371 mContentWindowID = nsContentUtils::GenerateWindowId();
372 }
373
374 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)
;
375
376#ifdef DEBUG1
377 mDocShellID = gDocshellIDCounter++;
378 // We're counting the number of |nsDocShells| to help find leaks
379 ++gNumberOfDocShells;
380 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)
381 ("++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)
382 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)
;
383#endif
384}
385
386nsDocShell::~nsDocShell() {
387 // Avoid notifying observers while we're in the dtor.
388 mIsBeingDestroyed = true;
389
390 Destroy();
391
392 if (mDocumentViewer) {
393 mDocumentViewer->Close(nullptr);
394 mDocumentViewer->Destroy();
395 mDocumentViewer = nullptr;
396 }
397
398 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)
;
399
400#ifdef DEBUG1
401 if (MOZ_LOG_TEST(gDocShellAndDOMWindowLeakLogging, LogLevel::Info)(__builtin_expect(!!(mozilla::detail::log_test(gDocShellAndDOMWindowLeakLogging
, LogLevel::Info)), 0))
) {
402 nsAutoCString url;
403 if (mLastOpenedURI) {
404 url = mLastOpenedURI->GetSpecOrDefault();
405
406 // Data URLs can be very long, so truncate to avoid flooding the log.
407 const uint32_t maxURLLength = 1000;
408 if (url.Length() > maxURLLength) {
409 url.Truncate(maxURLLength);
410 }
411 }
412
413 // We're counting the number of |nsDocShells| to help find leaks
414 --gNumberOfDocShells;
415 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)
416 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)
417 ("--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)
418 (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)
;
419 }
420#endif
421}
422
423bool nsDocShell::Initialize() {
424 if (mInitialized) {
425 // We've already been initialized.
426 return true;
427 }
428
429 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"
, 430); MOZ_PretendNoReturn(); } } while (0)
430 "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"
, 430); MOZ_PretendNoReturn(); } } while (0)
;
431
432 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"
, 432); return false; } } while (false)
;
433 mInitialized = true;
434
435 mDisableMetaRefreshWhenInactive =
436 Preferences::GetBool("browser.meta_refresh_when_inactive.disabled",
437 mDisableMetaRefreshWhenInactive);
438
439 if (nsCOMPtr<nsIObserverService> serv = services::GetObserverService()) {
440 const char* msg = mItemType == typeContent ? NS_WEBNAVIGATION_CREATE"webnavigation-create"
441 : NS_CHROME_WEBNAVIGATION_CREATE"chrome-webnavigation-create";
442 serv->NotifyWhenScriptSafe(GetAsSupports(this), msg, nullptr);
443 }
444
445 return true;
446}
447
448/* static */
449already_AddRefed<nsDocShell> nsDocShell::Create(
450 BrowsingContext* aBrowsingContext, uint64_t aContentWindowID) {
451 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"
, 451); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aBrowsingContext"
") (" "DocShell without a BrowsingContext!" ")"); do { *((volatile
int*)__null) = 451; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
452
453 nsresult rv;
454 RefPtr<nsDocShell> ds = new nsDocShell(aBrowsingContext, aContentWindowID);
455
456 // Initialize the underlying nsDocLoader.
457 rv = ds->nsDocLoader::InitWithBrowsingContext(aBrowsingContext);
458 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"
, 458)
) {
459 return nullptr;
460 }
461
462 // Create our ContentListener
463 ds->mContentListener = new nsDSURIContentListener(ds);
464
465 // We enable if we're in the parent process in order to support non-e10s
466 // configurations.
467 // Note: This check is duplicated in SharedWorkerInterfaceRequestor's
468 // constructor.
469 if (XRE_IsParentProcess()) {
470 ds->mInterceptController = new ServiceWorkerInterceptController();
471 }
472
473 // We want to hold a strong ref to the loadgroup, so it better hold a weak
474 // ref to us... use an InterfaceRequestorProxy to do this.
475 nsCOMPtr<nsIInterfaceRequestor> proxy = new InterfaceRequestorProxy(ds);
476 ds->mLoadGroup->SetNotificationCallbacks(proxy);
477
478 // XXX(nika): We have our BrowsingContext, so we might be able to skip this.
479 // It could be nice to directly set up our DocLoader tree?
480 rv = nsDocLoader::AddDocLoaderAsChildOfRoot(ds);
481 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"
, 481)
) {
482 return nullptr;
483 }
484
485 // Add |ds| as a progress listener to itself. A little weird, but simpler
486 // than reproducing all the listener-notification logic in overrides of the
487 // various methods via which nsDocLoader can be notified. Note that this
488 // holds an nsWeakPtr to |ds|, so it's ok.
489 rv = ds->AddProgressListener(ds, nsIWebProgress::NOTIFY_STATE_DOCUMENT |
490 nsIWebProgress::NOTIFY_STATE_NETWORK |
491 nsIWebProgress::NOTIFY_LOCATION);
492 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"
, 492)
) {
493 return nullptr;
494 }
495
496 // If our BrowsingContext has private browsing enabled, update the number of
497 // private browsing docshells.
498 if (aBrowsingContext->UsePrivateBrowsing()) {
499 ds->NotifyPrivateBrowsingChanged();
500 }
501
502 // If our parent window is present in this process, set up our parent now.
503 RefPtr<WindowContext> parentWC = aBrowsingContext->GetParentWindowContext();
504 if (parentWC && parentWC->IsInProcess()) {
505 // If we don't have a parent element anymore, we can't finish this load!
506 // How'd we get here?
507 RefPtr<Element> parentElement = aBrowsingContext->GetEmbedderElement();
508 if (!parentElement) {
509 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"
, 509); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "nsDocShell::Create() - !parentElement"
")"); do { *((volatile int*)__null) = 509; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
510 return nullptr;
511 }
512
513 // We have an in-process parent window, but don't have a parent nsDocShell?
514 // How'd we get here!
515 nsCOMPtr<nsIDocShell> parentShell =
516 parentElement->OwnerDoc()->GetDocShell();
517 if (!parentShell) {
518 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"
, 518); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "nsDocShell::Create() - !parentShell"
")"); do { *((volatile int*)__null) = 518; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
519 return nullptr;
520 }
521 parentShell->AddChild(ds);
522 }
523
524 // Make |ds| the primary DocShell for the given context.
525 aBrowsingContext->SetDocShell(ds);
526
527 // Set |ds| default load flags on load group.
528 ds->SetLoadGroupDefaultLoadFlags(aBrowsingContext->GetDefaultLoadFlags());
529
530 if (XRE_IsParentProcess()) {
531 aBrowsingContext->Canonical()->MaybeAddAsProgressListener(ds);
532 }
533
534 return ds.forget();
535}
536
537void nsDocShell::DestroyChildren() {
538 for (auto* child : mChildList.ForwardRange()) {
539 nsCOMPtr<nsIDocShellTreeItem> shell = do_QueryObject(child);
540 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"
, 540); MOZ_PretendNoReturn(); } } while (0)
;
541
542 if (shell) {
543 shell->SetTreeOwner(nullptr);
544 }
545 }
546
547 nsDocLoader::DestroyChildren();
548}
549
550NS_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; }
551 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; }
552 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; }
553 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; }
554
555NS_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; }
556NS_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; }
557
558NS_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"
, 558); 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
559 NS_INTERFACE_MAP_ENTRY(nsIDocShell)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIDocShell>)) foundInterface = static_cast
<nsIDocShell*>(this); else
560 NS_INTERFACE_MAP_ENTRY(nsIDocShellTreeItem)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIDocShellTreeItem>)) foundInterface
= static_cast<nsIDocShellTreeItem*>(this); else
561 NS_INTERFACE_MAP_ENTRY(nsIWebNavigation)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIWebNavigation>)) foundInterface
= static_cast<nsIWebNavigation*>(this); else
562 NS_INTERFACE_MAP_ENTRY(nsIBaseWindow)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIBaseWindow>)) foundInterface =
static_cast<nsIBaseWindow*>(this); else
563 NS_INTERFACE_MAP_ENTRY(nsIRefreshURI)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIRefreshURI>)) foundInterface =
static_cast<nsIRefreshURI*>(this); else
564 NS_INTERFACE_MAP_ENTRY(nsIWebProgressListener)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIWebProgressListener>)) foundInterface
= static_cast<nsIWebProgressListener*>(this); else
565 NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsISupportsWeakReference>)) foundInterface
= static_cast<nsISupportsWeakReference*>(this); else
566 NS_INTERFACE_MAP_ENTRY(nsIWebPageDescriptor)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIWebPageDescriptor>)) foundInterface
= static_cast<nsIWebPageDescriptor*>(this); else
567 NS_INTERFACE_MAP_ENTRY(nsIAuthPromptProvider)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIAuthPromptProvider>)) foundInterface
= static_cast<nsIAuthPromptProvider*>(this); else
568 NS_INTERFACE_MAP_ENTRY(nsILoadContext)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsILoadContext>)) foundInterface =
static_cast<nsILoadContext*>(this); else
569 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
570 mInterceptController)if ((mInterceptController) && aIID.Equals(mozilla::detail
::kImplementedIID<std::remove_reference_t<decltype(*this
)>, nsINetworkInterceptController>)) foundInterface = static_cast
<nsINetworkInterceptController*>(this); else
571NS_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; }
572
573NS_IMETHODIMPnsresult
574nsDocShell::GetInterface(const nsIID& aIID, void** aSink) {
575 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"
, 575); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aSink" ") ("
"null out param" ")"); do { *((volatile int*)__null) = 575; __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
;
576
577 *aSink = nullptr;
578
579 if (aIID.Equals(NS_GET_IID(nsICommandManager)(nsICommandManager::COMTypeInfo<nsICommandManager, void>
::kIID)
)) {
580 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"
, 580); return NS_ERROR_FAILURE; } } while (false)
;
581 *aSink = static_cast<nsICommandManager*>(mCommandManager.get());
582 } else if (aIID.Equals(NS_GET_IID(nsIURIContentListener)(nsIURIContentListener::COMTypeInfo<nsIURIContentListener,
void>::kIID)
)) {
583 *aSink = mContentListener;
584 } else if ((aIID.Equals(NS_GET_IID(nsIScriptGlobalObject)(nsIScriptGlobalObject::COMTypeInfo<nsIScriptGlobalObject,
void>::kIID)
) ||
585 aIID.Equals(NS_GET_IID(nsIGlobalObject)(nsIGlobalObject::COMTypeInfo<nsIGlobalObject, void>::kIID
)
) ||
586 aIID.Equals(NS_GET_IID(nsPIDOMWindowOuter)(nsPIDOMWindowOuter::COMTypeInfo<nsPIDOMWindowOuter, void>
::kIID)
) ||
587 aIID.Equals(NS_GET_IID(mozIDOMWindowProxy)(mozIDOMWindowProxy::COMTypeInfo<mozIDOMWindowProxy, void>
::kIID)
) ||
588 aIID.Equals(NS_GET_IID(nsIDOMWindow)(nsIDOMWindow::COMTypeInfo<nsIDOMWindow, void>::kIID))) &&
589 NS_SUCCEEDED(EnsureScriptEnvironment())((bool)(__builtin_expect(!!(!NS_FAILED_impl(EnsureScriptEnvironment
())), 1)))
) {
590 return mScriptGlobal->QueryInterface(aIID, aSink);
591 } else if (aIID.Equals(NS_GET_IID(Document)(Document::COMTypeInfo<Document, void>::kIID)) &&
592 NS_SUCCEEDED(EnsureDocumentViewer())((bool)(__builtin_expect(!!(!NS_FAILED_impl(EnsureDocumentViewer
())), 1)))
) {
593 RefPtr<Document> doc = mDocumentViewer->GetDocument();
594 doc.forget(aSink);
595 return *aSink ? NS_OK : NS_NOINTERFACE;
596 } else if (aIID.Equals(NS_GET_IID(nsIPrompt)(nsIPrompt::COMTypeInfo<nsIPrompt, void>::kIID)) &&
597 NS_SUCCEEDED(EnsureScriptEnvironment())((bool)(__builtin_expect(!!(!NS_FAILED_impl(EnsureScriptEnvironment
())), 1)))
) {
598 nsresult rv;
599 nsCOMPtr<nsIWindowWatcher> wwatch =
600 do_GetService(NS_WINDOWWATCHER_CONTRACTID"@mozilla.org/embedcomp/window-watcher;1", &rv);
601 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"
, 601); return rv; } } while (false)
;
602
603 // Get the an auth prompter for our window so that the parenting
604 // of the dialogs works as it should when using tabs.
605 nsIPrompt* prompt;
606 rv = wwatch->GetNewPrompter(mScriptGlobal, &prompt);
607 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"
, 607); return rv; } } while (false)
;
608
609 *aSink = prompt;
610 return NS_OK;
611 } else if (aIID.Equals(NS_GET_IID(nsIAuthPrompt)(nsIAuthPrompt::COMTypeInfo<nsIAuthPrompt, void>::kIID)) ||
612 aIID.Equals(NS_GET_IID(nsIAuthPrompt2)(nsIAuthPrompt2::COMTypeInfo<nsIAuthPrompt2, void>::kIID
)
)) {
613 return NS_SUCCEEDED(GetAuthPrompt(PROMPT_NORMAL, aIID, aSink))((bool)(__builtin_expect(!!(!NS_FAILED_impl(GetAuthPrompt(PROMPT_NORMAL
, aIID, aSink))), 1)))
614 ? NS_OK
615 : NS_NOINTERFACE;
616 } else if (aIID.Equals(NS_GET_IID(nsISHistory)(nsISHistory::COMTypeInfo<nsISHistory, void>::kIID))) {
617 // This is deprecated, you should instead directly get
618 // ChildSHistory from the browsing context.
619 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"
, 620); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "false"
") (" "Do not try to get a nsISHistory interface from nsIDocShell"
")"); do { *((volatile int*)__null) = 620; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
620 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"
, 620); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "false"
") (" "Do not try to get a nsISHistory interface from nsIDocShell"
")"); do { *((volatile int*)__null) = 620; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
621 return NS_NOINTERFACE;
622 } else if (aIID.Equals(NS_GET_IID(nsIWebBrowserFind)(nsIWebBrowserFind::COMTypeInfo<nsIWebBrowserFind, void>
::kIID)
)) {
623 nsresult rv = EnsureFind();
624 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
625 return rv;
626 }
627
628 *aSink = mFind;
629 NS_ADDREF((nsISupports*)*aSink)((nsISupports*)*aSink)->AddRef();
630 return NS_OK;
631 } else if (aIID.Equals(NS_GET_IID(nsISelectionDisplay)(nsISelectionDisplay::COMTypeInfo<nsISelectionDisplay, void
>::kIID)
)) {
632 if (PresShell* presShell = GetPresShell()) {
633 return presShell->QueryInterface(aIID, aSink);
634 }
635 } else if (aIID.Equals(NS_GET_IID(nsIDocShellTreeOwner)(nsIDocShellTreeOwner::COMTypeInfo<nsIDocShellTreeOwner, void
>::kIID)
)) {
636 nsCOMPtr<nsIDocShellTreeOwner> treeOwner;
637 nsresult rv = GetTreeOwner(getter_AddRefs(treeOwner));
638 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && treeOwner) {
639 return treeOwner->QueryInterface(aIID, aSink);
640 }
641 } else if (aIID.Equals(NS_GET_IID(nsIBrowserChild)(nsIBrowserChild::COMTypeInfo<nsIBrowserChild, void>::kIID
)
)) {
642 *aSink = GetBrowserChild().take();
643 return *aSink ? NS_OK : NS_ERROR_FAILURE;
644 } else {
645 return nsDocLoader::GetInterface(aIID, aSink);
646 }
647
648 NS_IF_ADDREF(((nsISupports*)*aSink))ns_if_addref(((nsISupports*)*aSink));
649 return *aSink ? NS_OK : NS_NOINTERFACE;
650}
651
652NS_IMETHODIMPnsresult
653nsDocShell::SetCancelContentJSEpoch(int32_t aEpoch) {
654 // Note: this gets called fairly early (before a pageload actually starts).
655 // We could probably defer this even longer.
656 nsCOMPtr<nsIBrowserChild> browserChild = GetBrowserChild();
657 static_cast<BrowserChild*>(browserChild.get())
658 ->SetCancelContentJSEpoch(aEpoch);
659 return NS_OK;
660}
661
662nsresult nsDocShell::CheckDisallowedJavascriptLoad(
663 nsDocShellLoadState* aLoadState) {
664 if (!net::SchemeIsJavascript(aLoadState->URI())) {
665 return NS_OK;
666 }
667
668 if (nsCOMPtr<nsIPrincipal> targetPrincipal =
669 GetInheritedPrincipal(/* aConsiderCurrentDocument */ true)) {
670 if (!aLoadState->TriggeringPrincipal()->Subsumes(targetPrincipal)) {
671 return NS_ERROR_DOM_BAD_CROSS_ORIGIN_URI;
672 }
673 return NS_OK;
674 }
675 return NS_ERROR_DOM_BAD_CROSS_ORIGIN_URI;
676}
677
678NS_IMETHODIMPnsresult
679nsDocShell::LoadURI(nsDocShellLoadState* aLoadState, bool aSetNavigating) {
680 return LoadURI(aLoadState, aSetNavigating, false);
681}
682
683nsresult nsDocShell::LoadURI(nsDocShellLoadState* aLoadState,
684 bool aSetNavigating,
685 bool aContinueHandlingSubframeHistory) {
686 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"
, 686); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState" ") ("
"Must have a valid load state!" ")"); do { *((volatile int*)
__null) = 686; __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
687 // NOTE: This comparison between what appears to be internal/external load
688 // flags is intentional, as it's ensuring that the caller isn't using any of
689 // the flags reserved for implementations by the `nsIWebNavigation` interface.
690 // In the future, this check may be dropped.
691 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"
, 693); AnnotateMozCrashReason("MOZ_ASSERT" "(" "(aLoadState->LoadFlags() & INTERNAL_LOAD_FLAGS_LOADURI_SETUP_FLAGS) == 0"
") (" "Should not have these flags set" ")"); do { *((volatile
int*)__null) = 693; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
692 (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"
, 693); AnnotateMozCrashReason("MOZ_ASSERT" "(" "(aLoadState->LoadFlags() & INTERNAL_LOAD_FLAGS_LOADURI_SETUP_FLAGS) == 0"
") (" "Should not have these flags set" ")"); do { *((volatile
int*)__null) = 693; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
693 "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"
, 693); AnnotateMozCrashReason("MOZ_ASSERT" "(" "(aLoadState->LoadFlags() & INTERNAL_LOAD_FLAGS_LOADURI_SETUP_FLAGS) == 0"
") (" "Should not have these flags set" ")"); do { *((volatile
int*)__null) = 693; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
694 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"
, 695); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->TargetBrowsingContext().IsNull()"
") (" "Targeting doesn't occur until InternalLoad" ")"); do {
*((volatile int*)__null) = 695; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
695 "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"
, 695); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->TargetBrowsingContext().IsNull()"
") (" "Targeting doesn't occur until InternalLoad" ")"); do {
*((volatile int*)__null) = 695; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
;
696
697 if (!aLoadState->TriggeringPrincipal()) {
698 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"
, 698); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"LoadURI must have a triggering principal" ")"); do { *((volatile
int*)__null) = 698; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
699 return NS_ERROR_FAILURE;
700 }
701
702 MOZ_TRY(CheckDisallowedJavascriptLoad(aLoadState))do { auto mozTryTempResult_ = ::mozilla::ToResult(CheckDisallowedJavascriptLoad
(aLoadState)); if ((__builtin_expect(!!(mozTryTempResult_.isErr
()), 0))) { return mozTryTempResult_.propagateErr(); } } while
(0)
;
703
704 bool oldIsNavigating = mIsNavigating;
705 auto cleanupIsNavigating =
706 MakeScopeExit([&]() { mIsNavigating = oldIsNavigating; });
707 if (aSetNavigating) {
708 mIsNavigating = true;
709 }
710
711 PopupBlocker::PopupControlState popupState = PopupBlocker::openOverridden;
712 if (aLoadState->HasLoadFlags(LOAD_FLAGS_ALLOW_POPUPS)) {
713 popupState = PopupBlocker::openAllowed;
714 // If we allow popups as part of the navigation, ensure we fake a user
715 // interaction, so that popups can, in fact, be allowed to open.
716 if (WindowContext* wc = mBrowsingContext->GetCurrentWindowContext()) {
717 wc->NotifyUserGestureActivation();
718 }
719 }
720
721 AutoPopupStatePusherAutoPopupStatePusherInternal statePusher(popupState);
722
723 if (aLoadState->GetCancelContentJSEpoch().isSome()) {
724 SetCancelContentJSEpoch(*aLoadState->GetCancelContentJSEpoch());
725 }
726
727 // Note: we allow loads to get through here even if mFiredUnloadEvent is
728 // true; that case will get handled in LoadInternal or LoadHistoryEntry,
729 // so we pass false as the second parameter to IsNavigationAllowed.
730 // However, we don't allow the page to change location *in the middle of*
731 // firing beforeunload, so we do need to check if *beforeunload* is currently
732 // firing, so we call IsNavigationAllowed rather than just IsPrintingOrPP.
733 if (!IsNavigationAllowed(true, false)) {
734 return NS_OK; // JS may not handle returning of an error code
735 }
736
737 nsLoadFlags defaultLoadFlags = mBrowsingContext->GetDefaultLoadFlags();
738 if (aLoadState->HasLoadFlags(LOAD_FLAGS_FORCE_TRR)) {
739 defaultLoadFlags |= nsIRequest::LOAD_TRR_ONLY_MODE;
740 } else if (aLoadState->HasLoadFlags(LOAD_FLAGS_DISABLE_TRR)) {
741 defaultLoadFlags |= nsIRequest::LOAD_TRR_DISABLED_MODE;
742 }
743
744 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"
, 744); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "false"
") (" "NS_SUCCEEDED(mBrowsingContext->SetDefaultLoadFlags(defaultLoadFlags))"
")"); do { *((volatile int*)__null) = 744; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
745
746 if (!StartupTimeline::HasRecord(StartupTimeline::FIRST_LOAD_URI) &&
747 mItemType == typeContent && !NS_IsAboutBlank(aLoadState->URI())) {
748 StartupTimeline::RecordOnce(StartupTimeline::FIRST_LOAD_URI);
749 }
750
751 // LoadType used to be set to a default value here, if no LoadInfo/LoadState
752 // object was passed in. That functionality has been removed as of bug
753 // 1492648. LoadType should now be set up by the caller at the time they
754 // create their nsDocShellLoadState object to pass into LoadURI.
755
756 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)
757 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)
758 ("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)
759 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)
;
760
761 if ((!aLoadState->LoadIsFromSessionHistory() &&
762 !LOAD_TYPE_HAS_FLAGS(aLoadState->LoadType(),((aLoadState->LoadType()) & ((LOAD_FLAGS_REPLACE_HISTORY
) << 16))
763 LOAD_FLAGS_REPLACE_HISTORY)((aLoadState->LoadType()) & ((LOAD_FLAGS_REPLACE_HISTORY
) << 16))
) ||
764 aContinueHandlingSubframeHistory) {
765 // This is possibly a subframe, so handle it accordingly.
766 //
767 // If history exists, it will be loaded into the aLoadState object, and the
768 // LoadType will be changed.
769 if (MaybeHandleSubframeHistory(aLoadState,
770 aContinueHandlingSubframeHistory)) {
771 // MaybeHandleSubframeHistory returns true if we need to continue loading
772 // asynchronously.
773 return NS_OK;
774 }
775 }
776
777 if (aLoadState->LoadIsFromSessionHistory()) {
778 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)
779 ("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)
;
780
781 if (!mozilla::SessionHistoryInParent()) {
782 nsCOMPtr<nsISHEntry> entry = aLoadState->SHEntry();
783 return LoadHistoryEntry(entry, aLoadState->LoadType(),
784 aLoadState->HasValidUserGestureActivation());
785 }
786
787 // FIXME Null check aLoadState->GetLoadingSessionHistoryInfo()?
788 return LoadHistoryEntry(*aLoadState->GetLoadingSessionHistoryInfo(),
789 aLoadState->LoadType(),
790 aLoadState->HasValidUserGestureActivation());
791 }
792
793 // On history navigation via Back/Forward buttons, don't execute
794 // automatic JavaScript redirection such as |location.href = ...| or
795 // |window.open()|
796 //
797 // LOAD_NORMAL: window.open(...) etc.
798 // LOAD_STOP_CONTENT: location.href = ..., location.assign(...)
799 if ((aLoadState->LoadType() == LOAD_NORMAL ||
800 aLoadState->LoadType() == LOAD_STOP_CONTENT) &&
801 ShouldBlockLoadingForBackButton()) {
802 return NS_OK;
803 }
804
805 BrowsingContext::Type bcType = mBrowsingContext->GetType();
806
807 // Set up the inheriting principal in LoadState.
808 nsresult rv = aLoadState->SetupInheritingPrincipal(
809 bcType, mBrowsingContext->OriginAttributesRef());
810 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"
, 810); return rv; } } while (false)
;
811
812 rv = aLoadState->SetupTriggeringPrincipal(
813 mBrowsingContext->OriginAttributesRef());
814 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"
, 814); return rv; } } while (false)
;
815
816 aLoadState->CalculateLoadURIFlags();
817
818 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"
, 819); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->TypeHint().IsVoid()"
") (" "Typehint should be null when calling InternalLoad from LoadURI"
")"); do { *((volatile int*)__null) = 819; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
819 "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"
, 819); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->TypeHint().IsVoid()"
") (" "Typehint should be null when calling InternalLoad from LoadURI"
")"); do { *((volatile int*)__null) = 819; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
820 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"
, 821); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->FileName().IsVoid()"
") (" "FileName should be null when calling InternalLoad from LoadURI"
")"); do { *((volatile int*)__null) = 821; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
821 "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"
, 821); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->FileName().IsVoid()"
") (" "FileName should be null when calling InternalLoad from LoadURI"
")"); do { *((volatile int*)__null) = 821; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
822 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"
, 824); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aLoadState->LoadIsFromSessionHistory()"
") (" "Shouldn't be loading from an entry when calling InternalLoad "
"from LoadURI" ")"); do { *((volatile int*)__null) = 824; __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
823 "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"
, 824); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aLoadState->LoadIsFromSessionHistory()"
") (" "Shouldn't be loading from an entry when calling InternalLoad "
"from LoadURI" ")"); do { *((volatile int*)__null) = 824; __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
824 "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"
, 824); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aLoadState->LoadIsFromSessionHistory()"
") (" "Shouldn't be loading from an entry when calling InternalLoad "
"from LoadURI" ")"); do { *((volatile int*)__null) = 824; __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
;
825
826 // If we have a system triggering principal, we can assume that this load was
827 // triggered by some UI in the browser chrome, such as the URL bar or
828 // bookmark bar. This should count as a user interaction for the current sh
829 // entry, so that the user may navigate back to the current entry, from the
830 // entry that is going to be added as part of this load.
831 nsCOMPtr<nsIPrincipal> triggeringPrincipal =
832 aLoadState->TriggeringPrincipal();
833 if (triggeringPrincipal && triggeringPrincipal->IsSystemPrincipal()) {
834 if (mozilla::SessionHistoryInParent()) {
835 WindowContext* topWc = mBrowsingContext->GetTopWindowContext();
836 if (topWc && !topWc->IsDiscarded()) {
837 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"
, 837); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "false"
") (" "NS_SUCCEEDED(topWc->SetSHEntryHasUserInteraction(true))"
")"); do { *((volatile int*)__null) = 837; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
838 }
839 } else {
840 bool oshe = false;
841 nsCOMPtr<nsISHEntry> currentSHEntry;
842 GetCurrentSHEntry(getter_AddRefs(currentSHEntry), &oshe);
843 if (currentSHEntry) {
844 currentSHEntry->SetHasUserInteraction(true);
845 }
846 }
847 }
848
849 rv = InternalLoad(aLoadState);
850 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"
, 850); return rv; } } while (false)
;
851
852 if (aLoadState->GetOriginalURIString().isSome()) {
853 // Save URI string in case it's needed later when
854 // sending to search engine service in EndPageLoad()
855 mOriginalUriString = *aLoadState->GetOriginalURIString();
856 }
857
858 return NS_OK;
859}
860
861bool nsDocShell::IsLoadingFromSessionHistory() {
862 return mActiveEntryIsLoadingFromSessionHistory;
863}
864
865// StopDetector is modeled similarly to OnloadBlocker; it is a rather
866// dummy nsIRequest implementation which can be added to an nsILoadGroup to
867// detect Cancel calls.
868class StopDetector final : public nsIRequest {
869 public:
870 StopDetector() = default;
871
872 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:
873 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;
874
875 bool Canceled() { return mCanceled; }
876
877 private:
878 ~StopDetector() = default;
879
880 bool mCanceled = false;
881};
882
883NS_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"
, 883); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { *((volatile int*)__null) =
883; __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"
, 883); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"StopDetector\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 883; __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"
, 883); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { *((volatile int*)__null) = 883
; __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"
, 883); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"StopDetector\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 883; __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"
, 883); 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; }
884
885NS_IMETHODIMPnsresult
886StopDetector::GetName(nsACString& aResult) {
887 aResult.AssignLiteral("about:stop-detector");
888 return NS_OK;
889}
890
891NS_IMETHODIMPnsresult
892StopDetector::IsPending(bool* aRetVal) {
893 *aRetVal = true;
894 return NS_OK;
895}
896
897NS_IMETHODIMPnsresult
898StopDetector::GetStatus(nsresult* aStatus) {
899 *aStatus = NS_OK;
900 return NS_OK;
901}
902
903NS_IMETHODIMPnsresult StopDetector::SetCanceledReason(const nsACString& aReason) {
904 return SetCanceledReasonImpl(aReason);
905}
906
907NS_IMETHODIMPnsresult StopDetector::GetCanceledReason(nsACString& aReason) {
908 return GetCanceledReasonImpl(aReason);
909}
910
911NS_IMETHODIMPnsresult StopDetector::CancelWithReason(nsresult aStatus,
912 const nsACString& aReason) {
913 return CancelWithReasonImpl(aStatus, aReason);
914}
915
916NS_IMETHODIMPnsresult
917StopDetector::Cancel(nsresult aStatus) {
918 mCanceled = true;
919 return NS_OK;
920}
921
922NS_IMETHODIMPnsresult
923StopDetector::Suspend(void) { return NS_OK; }
924NS_IMETHODIMPnsresult
925StopDetector::Resume(void) { return NS_OK; }
926
927NS_IMETHODIMPnsresult
928StopDetector::GetLoadGroup(nsILoadGroup** aLoadGroup) {
929 *aLoadGroup = nullptr;
930 return NS_OK;
931}
932
933NS_IMETHODIMPnsresult
934StopDetector::SetLoadGroup(nsILoadGroup* aLoadGroup) { return NS_OK; }
935
936NS_IMETHODIMPnsresult
937StopDetector::GetLoadFlags(nsLoadFlags* aLoadFlags) {
938 *aLoadFlags = nsIRequest::LOAD_NORMAL;
939 return NS_OK;
940}
941
942NS_IMETHODIMPnsresult
943StopDetector::GetTRRMode(nsIRequest::TRRMode* aTRRMode) {
944 return GetTRRModeImpl(aTRRMode);
945}
946
947NS_IMETHODIMPnsresult
948StopDetector::SetTRRMode(nsIRequest::TRRMode aTRRMode) {
949 return SetTRRModeImpl(aTRRMode);
950}
951
952NS_IMETHODIMPnsresult
953StopDetector::SetLoadFlags(nsLoadFlags aLoadFlags) { return NS_OK; }
954
955bool nsDocShell::MaybeHandleSubframeHistory(
956 nsDocShellLoadState* aLoadState, bool aContinueHandlingSubframeHistory) {
957 // First, verify if this is a subframe.
958 // Note, it is ok to rely on docshell here and not browsing context since when
959 // an iframe is created, it has first in-process docshell.
960 nsCOMPtr<nsIDocShellTreeItem> parentAsItem;
961 GetInProcessSameTypeParent(getter_AddRefs(parentAsItem));
962 nsCOMPtr<nsIDocShell> parentDS(do_QueryInterface(parentAsItem));
963
964 if (!parentDS || parentDS == static_cast<nsIDocShell*>(this)) {
965 if (mBrowsingContext && mBrowsingContext->IsTop()) {
966 // This is the root docshell. If we got here while
967 // executing an onLoad Handler,this load will not go
968 // into session history.
969 // XXX Why is this code in a method which deals with iframes!
970 if (aLoadState->IsFormSubmission()) {
971#ifdef DEBUG1
972 if (!mEODForCurrentDocument) {
973 const MaybeDiscarded<BrowsingContext>& targetBC =
974 aLoadState->TargetBrowsingContext();
975 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"
, 976); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->LoadType() == LOAD_NORMAL_REPLACE"
")"); do { *((volatile int*)__null) = 976; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
976 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"
, 976); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->LoadType() == LOAD_NORMAL_REPLACE"
")"); do { *((volatile int*)__null) = 976; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
977 }
978#endif
979 } else {
980 bool inOnLoadHandler = false;
981 GetIsExecutingOnLoadHandler(&inOnLoadHandler);
982 if (inOnLoadHandler) {
983 aLoadState->SetLoadType(LOAD_NORMAL_REPLACE);
984 }
985 }
986 }
987 return false;
988 }
989
990 /* OK. It is a subframe. Checkout the parent's loadtype. If the parent was
991 * loaded through a history mechanism, then get the SH entry for the child
992 * from the parent. This is done to restore frameset navigation while going
993 * back/forward. If the parent was loaded through any other loadType, set the
994 * child's loadType too accordingly, so that session history does not get
995 * confused.
996 */
997
998 // Get the parent's load type
999 uint32_t parentLoadType;
1000 parentDS->GetLoadType(&parentLoadType);
1001
1002 if (!aContinueHandlingSubframeHistory) {
1003 if (mozilla::SessionHistoryInParent()) {
1004 if (nsDocShell::Cast(parentDS.get())->IsLoadingFromSessionHistory() &&
1005 !GetCreatedDynamically()) {
1006 if (XRE_IsContentProcess()) {
1007 dom::ContentChild* contentChild = dom::ContentChild::GetSingleton();
1008 nsCOMPtr<nsILoadGroup> loadGroup;
1009 GetLoadGroup(getter_AddRefs(loadGroup));
1010 if (contentChild && loadGroup && !mCheckingSessionHistory) {
1011 RefPtr<Document> parentDoc = parentDS->GetDocument();
1012 parentDoc->BlockOnload();
1013 RefPtr<BrowsingContext> browsingContext = mBrowsingContext;
1014 Maybe<uint64_t> currentLoadIdentifier =
1015 mBrowsingContext->GetCurrentLoadIdentifier();
1016 RefPtr<nsDocShellLoadState> loadState = aLoadState;
1017 bool isNavigating = mIsNavigating;
1018 RefPtr<StopDetector> stopDetector = new StopDetector();
1019 loadGroup->AddRequest(stopDetector, nullptr);
1020 // Need to set mCheckingSessionHistory so that
1021 // GetIsAttemptingToNavigate() returns true.
1022 mCheckingSessionHistory = true;
1023
1024 auto resolve =
1025 [currentLoadIdentifier, browsingContext, parentDoc, loadState,
1026 isNavigating, loadGroup, stopDetector](
1027 mozilla::Maybe<LoadingSessionHistoryInfo>&& aResult) {
1028 RefPtr<nsDocShell> docShell =
1029 static_cast<nsDocShell*>(browsingContext->GetDocShell());
1030 auto unblockParent = MakeScopeExit(
1031 [loadGroup, stopDetector, parentDoc, docShell]() {
1032 if (docShell) {
1033 docShell->mCheckingSessionHistory = false;
1034 }
1035 loadGroup->RemoveRequest(stopDetector, nullptr, NS_OK);
1036 parentDoc->UnblockOnload(false);
1037 });
1038
1039 if (!docShell || !docShell->mCheckingSessionHistory) {
1040 return;
1041 }
1042
1043 if (stopDetector->Canceled()) {
1044 return;
1045 }
1046 if (currentLoadIdentifier ==
1047 browsingContext->GetCurrentLoadIdentifier() &&
1048 aResult.isSome()) {
1049 loadState->SetLoadingSessionHistoryInfo(aResult.value());
1050 // This is an initial subframe load from the session
1051 // history, index doesn't need to be updated.
1052 loadState->SetLoadIsFromSessionHistory(0, false);
1053 }
1054
1055 // We got the results back from the parent process, call
1056 // LoadURI again with the possibly updated data.
1057 docShell->LoadURI(loadState, isNavigating, true);
1058 };
1059 auto reject = [loadGroup, stopDetector, browsingContext,
1060 parentDoc](mozilla::ipc::ResponseRejectReason) {
1061 RefPtr<nsDocShell> docShell =
1062 static_cast<nsDocShell*>(browsingContext->GetDocShell());
1063 if (docShell) {
1064 docShell->mCheckingSessionHistory = false;
1065 }
1066 // In practise reject shouldn't be called ever.
1067 loadGroup->RemoveRequest(stopDetector, nullptr, NS_OK);
1068 parentDoc->UnblockOnload(false);
1069 };
1070 contentChild->SendGetLoadingSessionHistoryInfoFromParent(
1071 mBrowsingContext, std::move(resolve), std::move(reject));
1072 return true;
1073 }
1074 } else {
1075 Maybe<LoadingSessionHistoryInfo> info;
1076 mBrowsingContext->Canonical()->GetLoadingSessionHistoryInfoFromParent(
1077 info);
1078 if (info.isSome()) {
1079 aLoadState->SetLoadingSessionHistoryInfo(info.value());
1080 // This is an initial subframe load from the session
1081 // history, index doesn't need to be updated.
1082 aLoadState->SetLoadIsFromSessionHistory(0, false);
1083 }
1084 }
1085 }
1086 } else {
1087 // Get the ShEntry for the child from the parent
1088 nsCOMPtr<nsISHEntry> currentSH;
1089 bool oshe = false;
1090 parentDS->GetCurrentSHEntry(getter_AddRefs(currentSH), &oshe);
1091 bool dynamicallyAddedChild = GetCreatedDynamically();
1092
1093 if (!dynamicallyAddedChild && !oshe && currentSH) {
1094 // Only use the old SHEntry, if we're sure enough that
1095 // it wasn't originally for some other frame.
1096 nsCOMPtr<nsISHEntry> shEntry;
1097 currentSH->GetChildSHEntryIfHasNoDynamicallyAddedChild(
1098 mBrowsingContext->ChildOffset(), getter_AddRefs(shEntry));
1099 if (shEntry) {
1100 aLoadState->SetSHEntry(shEntry);
1101 }
1102 }
1103 }
1104 }
1105
1106 // Make some decisions on the child frame's loadType based on the
1107 // parent's loadType, if the subframe hasn't loaded anything into it.
1108 //
1109 // In some cases privileged scripts may try to get the DOMWindow
1110 // reference of this docshell before the loading starts, causing the
1111 // initial about:blank content viewer being created and mCurrentURI being
1112 // set. To handle this case we check if mCurrentURI is about:blank and
1113 // currentSHEntry is null.
1114 bool oshe = false;
1115 nsCOMPtr<nsISHEntry> currentChildEntry;
1116 GetCurrentSHEntry(getter_AddRefs(currentChildEntry), &oshe);
1117
1118 if (mCurrentURI && (!NS_IsAboutBlank(mCurrentURI) || currentChildEntry ||
1119 mLoadingEntry || mActiveEntry)) {
1120 // This is a pre-existing subframe. If
1121 // 1. The load of this frame was not originally initiated by session
1122 // history directly (i.e. (!shEntry) condition succeeded, but it can
1123 // still be a history load on parent which causes this frame being
1124 // loaded), which we checked with the above assert, and
1125 // 2. mCurrentURI is not null, nor the initial about:blank,
1126 // it is possible that a parent's onLoadHandler or even self's
1127 // onLoadHandler is loading a new page in this child. Check parent's and
1128 // self's busy flag and if it is set, we don't want this onLoadHandler
1129 // load to get in to session history.
1130 BusyFlags parentBusy = parentDS->GetBusyFlags();
1131 BusyFlags selfBusy = GetBusyFlags();
1132
1133 if (parentBusy & BUSY_FLAGS_BUSY || selfBusy & BUSY_FLAGS_BUSY) {
1134 aLoadState->SetLoadType(LOAD_NORMAL_REPLACE);
1135 aLoadState->ClearLoadIsFromSessionHistory();
1136 }
1137 return false;
1138 }
1139
1140 // This is a newly created frame. Check for exception cases first.
1141 // By default the subframe will inherit the parent's loadType.
1142 if (aLoadState->LoadIsFromSessionHistory() &&
1143 (parentLoadType == LOAD_NORMAL || parentLoadType == LOAD_LINK)) {
1144 // The parent was loaded normally. In this case, this *brand new*
1145 // child really shouldn't have a SHEntry. If it does, it could be
1146 // because the parent is replacing an existing frame with a new frame,
1147 // in the onLoadHandler. We don't want this url to get into session
1148 // history. Clear off shEntry, and set load type to
1149 // LOAD_BYPASS_HISTORY.
1150 bool inOnLoadHandler = false;
1151 parentDS->GetIsExecutingOnLoadHandler(&inOnLoadHandler);
1152 if (inOnLoadHandler) {
1153 aLoadState->SetLoadType(LOAD_NORMAL_REPLACE);
1154 aLoadState->ClearLoadIsFromSessionHistory();
1155 }
1156 } else if (parentLoadType == LOAD_REFRESH) {
1157 // Clear shEntry. For refresh loads, we have to load
1158 // what comes through the pipe, not what's in history.
1159 aLoadState->ClearLoadIsFromSessionHistory();
1160 } else if ((parentLoadType == LOAD_BYPASS_HISTORY) ||
1161 (aLoadState->LoadIsFromSessionHistory() &&
1162 ((parentLoadType & LOAD_CMD_HISTORY) ||
1163 (parentLoadType == LOAD_RELOAD_NORMAL) ||
1164 (parentLoadType == LOAD_RELOAD_CHARSET_CHANGE) ||
1165 (parentLoadType == LOAD_RELOAD_CHARSET_CHANGE_BYPASS_CACHE) ||
1166 (parentLoadType ==
1167 LOAD_RELOAD_CHARSET_CHANGE_BYPASS_PROXY_AND_CACHE)))) {
1168 // If the parent url, bypassed history or was loaded from
1169 // history, pass on the parent's loadType to the new child
1170 // frame too, so that the child frame will also
1171 // avoid getting into history.
1172 aLoadState->SetLoadType(parentLoadType);
1173 } else if (parentLoadType == LOAD_ERROR_PAGE) {
1174 // If the parent document is an error page, we don't
1175 // want to update global/session history. However,
1176 // this child frame is not an error page.
1177 aLoadState->SetLoadType(LOAD_BYPASS_HISTORY);
1178 } else if ((parentLoadType == LOAD_RELOAD_BYPASS_CACHE) ||
1179 (parentLoadType == LOAD_RELOAD_BYPASS_PROXY) ||
1180 (parentLoadType == LOAD_RELOAD_BYPASS_PROXY_AND_CACHE)) {
1181 // the new frame should inherit the parent's load type so that it also
1182 // bypasses the cache and/or proxy
1183 aLoadState->SetLoadType(parentLoadType);
1184 }
1185
1186 return false;
1187}
1188
1189/*
1190 * Reset state to a new content model within the current document and the
1191 * document viewer. Called by the document before initiating an out of band
1192 * document.write().
1193 */
1194NS_IMETHODIMPnsresult
1195nsDocShell::PrepareForNewContentModel() {
1196 // Clear out our form control state, because the state of controls
1197 // in the pre-open() document should not affect the state of
1198 // controls that are now going to be written.
1199 SetLayoutHistoryState(nullptr);
1200 mEODForCurrentDocument = false;
1201 return NS_OK;
1202}
1203
1204NS_IMETHODIMPnsresult
1205nsDocShell::FirePageHideNotification(bool aIsUnload) {
1206 FirePageHideNotificationInternal(aIsUnload, false);
1207 return NS_OK;
1208}
1209
1210void nsDocShell::FirePageHideNotificationInternal(
1211 bool aIsUnload, bool aSkipCheckingDynEntries) {
1212 if (mDocumentViewer && !mFiredUnloadEvent) {
1213 // Keep an explicit reference since calling PageHide could release
1214 // mDocumentViewer
1215 nsCOMPtr<nsIDocumentViewer> viewer(mDocumentViewer);
1216 mFiredUnloadEvent = true;
1217
1218 if (mTiming) {
1219 mTiming->NotifyUnloadEventStart();
1220 }
1221
1222 viewer->PageHide(aIsUnload);
1223
1224 if (mTiming) {
1225 mTiming->NotifyUnloadEventEnd();
1226 }
1227
1228 AutoTArray<nsCOMPtr<nsIDocShell>, 8> kids;
1229 uint32_t n = mChildList.Length();
1230 kids.SetCapacity(n);
1231 for (uint32_t i = 0; i < n; i++) {
1232 kids.AppendElement(do_QueryInterface(ChildAt(i)));
1233 }
1234
1235 n = kids.Length();
1236 for (uint32_t i = 0; i < n; ++i) {
1237 RefPtr<nsDocShell> child = static_cast<nsDocShell*>(kids[i].get());
1238 if (child) {
1239 // Skip checking dynamic subframe entries in our children.
1240 child->FirePageHideNotificationInternal(aIsUnload, true);
1241 }
1242 }
1243
1244 // If the document is unloading, remove all dynamic subframe entries.
1245 if (aIsUnload && !aSkipCheckingDynEntries) {
1246 RefPtr<ChildSHistory> rootSH = GetRootSessionHistory();
1247 if (rootSH) {
1248 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)
1249 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)
1250 ("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)
;
1251 if (mozilla::SessionHistoryInParent()) {
1252 if (mActiveEntry) {
1253 mBrowsingContext->RemoveDynEntriesFromActiveSessionHistoryEntry();
1254 }
1255 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)
1256 ("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)
;
1257 } else if (mOSHE) {
1258 int32_t index = rootSH->Index();
1259 rootSH->LegacySHistory()->RemoveDynEntries(index, mOSHE);
1260 }
1261 }
1262 }
1263
1264 // Now make sure our editor, if any, is detached before we go
1265 // any farther.
1266 DetachEditorFromWindow();
1267 }
1268}
1269
1270void nsDocShell::ThawFreezeNonRecursive(bool aThaw) {
1271 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"
, 1271); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mozilla::BFCacheInParent()"
")"); do { *((volatile int*)__null) = 1271; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1272
1273 if (!mScriptGlobal) {
1274 return;
1275 }
1276
1277 if (RefPtr<nsGlobalWindowInner> inner =
1278 nsGlobalWindowInner::Cast(mScriptGlobal->GetCurrentInnerWindow())) {
1279 if (aThaw) {
1280 inner->Thaw(false);
1281 } else {
1282 inner->Freeze(false);
1283 }
1284 }
1285}
1286
1287void nsDocShell::FirePageHideShowNonRecursive(bool aShow) {
1288 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"
, 1288); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mozilla::BFCacheInParent()"
")"); do { *((volatile int*)__null) = 1288; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1289
1290 if (!mDocumentViewer) {
1291 return;
1292 }
1293
1294 // Emulate what non-SHIP BFCache does too. In pageshow case
1295 // add and remove a request and before that call SetCurrentURI to get
1296 // the location change notification.
1297 // For pagehide, set mFiredUnloadEvent to true, so that unload doesn't fire.
1298 nsCOMPtr<nsIDocumentViewer> viewer(mDocumentViewer);
1299 if (aShow) {
1300 viewer->SetIsHidden(false);
1301 mRefreshURIList = std::move(mBFCachedRefreshURIList);
1302 RefreshURIFromQueue();
1303 mFiredUnloadEvent = false;
1304 RefPtr<Document> doc = viewer->GetDocument();
1305 if (doc) {
1306 doc->NotifyActivityChanged();
1307 nsCOMPtr<nsPIDOMWindowInner> inner =
1308 mScriptGlobal ? mScriptGlobal->GetCurrentInnerWindow() : nullptr;
1309 if (mBrowsingContext->IsTop()) {
1310 doc->NotifyPossibleTitleChange(false);
1311 doc->SetLoadingOrRestoredFromBFCacheTimeStampToNow();
1312 if (inner) {
1313 // Now that we have found the inner window of the page restored
1314 // from the history, we have to make sure that
1315 // performance.navigation.type is 2.
1316 // Traditionally this type change has been done to the top level page
1317 // only.
1318 Performance* performance = inner->GetPerformance();
1319 if (performance) {
1320 performance->GetDOMTiming()->NotifyRestoreStart();
1321 }
1322 }
1323 }
1324
1325 nsCOMPtr<nsIChannel> channel = doc->GetChannel();
1326 if (channel) {
1327 SetLoadType(LOAD_HISTORY);
1328 mEODForCurrentDocument = false;
1329 mIsRestoringDocument = true;
1330 mLoadGroup->AddRequest(channel, nullptr);
1331 SetCurrentURI(doc->GetDocumentURI(), channel,
1332 /* aFireOnLocationChange */ true,
1333 /* aIsInitialAboutBlank */ false,
1334 /* aLocationFlags */ 0);
1335 mLoadGroup->RemoveRequest(channel, nullptr, NS_OK);
1336 mIsRestoringDocument = false;
1337 }
1338 RefPtr<PresShell> presShell = GetPresShell();
1339 if (presShell) {
1340 presShell->Thaw(false);
1341 }
1342
1343 if (inner) {
1344 inner->FireDelayedDOMEvents(false);
1345 }
1346 }
1347 } else if (!mFiredUnloadEvent) {
1348 // XXXBFCache check again that the page can enter bfcache.
1349 // XXXBFCache should mTiming->NotifyUnloadEventStart()/End() be called here?
1350
1351 if (mRefreshURIList) {
1352 RefreshURIToQueue();
1353 mBFCachedRefreshURIList = std::move(mRefreshURIList);
1354 } else {
1355 // If Stop was called, the list was moved to mSavedRefreshURIList after
1356 // calling SuspendRefreshURIs, which calls RefreshURIToQueue.
1357 mBFCachedRefreshURIList = std::move(mSavedRefreshURIList);
1358 }
1359
1360 mFiredUnloadEvent = true;
1361 viewer->PageHide(false);
1362
1363 RefPtr<PresShell> presShell = GetPresShell();
1364 if (presShell) {
1365 presShell->Freeze(false);
1366 }
1367 }
1368}
1369
1370nsresult nsDocShell::Dispatch(already_AddRefed<nsIRunnable>&& aRunnable) {
1371 nsCOMPtr<nsIRunnable> runnable(aRunnable);
1372 if (NS_WARN_IF(!GetWindow())NS_warn_if_impl(!GetWindow(), "!GetWindow()", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 1372)
) {
1373 // Window should only be unavailable after destroyed.
1374 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"
, 1374); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mIsBeingDestroyed"
")"); do { *((volatile int*)__null) = 1374; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1375 return NS_ERROR_FAILURE;
1376 }
1377 return SchedulerGroup::Dispatch(runnable.forget());
1378}
1379
1380NS_IMETHODIMPnsresult
1381nsDocShell::DispatchLocationChangeEvent() {
1382 return Dispatch(NewRunnableMethod("nsDocShell::FireDummyOnLocationChange",
1383 this,
1384 &nsDocShell::FireDummyOnLocationChange));
1385}
1386
1387NS_IMETHODIMPnsresult
1388nsDocShell::StartDelayedAutoplayMediaComponents() {
1389 RefPtr<nsPIDOMWindowOuter> outerWindow = GetWindow();
1390 if (outerWindow) {
1391 outerWindow->ActivateMediaComponents();
1392 }
1393 return NS_OK;
1394}
1395
1396bool nsDocShell::MaybeInitTiming() {
1397 if (mTiming && !mBlankTiming) {
1398 return false;
1399 }
1400
1401 bool canBeReset = false;
1402
1403 if (mScriptGlobal && mBlankTiming) {
1404 nsPIDOMWindowInner* innerWin = mScriptGlobal->GetCurrentInnerWindow();
1405 if (innerWin && innerWin->GetPerformance()) {
1406 mTiming = innerWin->GetPerformance()->GetDOMTiming();
1407 mBlankTiming = false;
1408 }
1409 }
1410
1411 if (!mTiming) {
1412 mTiming = new nsDOMNavigationTiming(this);
1413 canBeReset = true;
1414 }
1415
1416 mTiming->NotifyNavigationStart(
1417 mBrowsingContext->IsActive()
1418 ? nsDOMNavigationTiming::DocShellState::eActive
1419 : nsDOMNavigationTiming::DocShellState::eInactive);
1420
1421 return canBeReset;
1422}
1423
1424void nsDocShell::MaybeResetInitTiming(bool aReset) {
1425 if (aReset) {
1426 mTiming = nullptr;
1427 }
1428}
1429
1430nsDOMNavigationTiming* nsDocShell::GetNavigationTiming() const {
1431 return mTiming;
1432}
1433
1434nsPresContext* nsDocShell::GetEldestPresContext() {
1435 nsIDocumentViewer* viewer = mDocumentViewer;
1436 while (viewer) {
1437 nsIDocumentViewer* prevViewer = viewer->GetPreviousViewer();
1438 if (!prevViewer) {
1439 return viewer->GetPresContext();
1440 }
1441 viewer = prevViewer;
1442 }
1443
1444 return nullptr;
1445}
1446
1447nsPresContext* nsDocShell::GetPresContext() {
1448 if (!mDocumentViewer) {
1449 return nullptr;
1450 }
1451
1452 return mDocumentViewer->GetPresContext();
1453}
1454
1455PresShell* nsDocShell::GetPresShell() {
1456 nsPresContext* presContext = GetPresContext();
1457 return presContext ? presContext->GetPresShell() : nullptr;
1458}
1459
1460PresShell* nsDocShell::GetEldestPresShell() {
1461 nsPresContext* presContext = GetEldestPresContext();
1462
1463 if (presContext) {
1464 return presContext->GetPresShell();
1465 }
1466
1467 return nullptr;
1468}
1469
1470NS_IMETHODIMPnsresult
1471nsDocShell::GetDocViewer(nsIDocumentViewer** aDocumentViewer) {
1472 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"
, 1472); return NS_ERROR_INVALID_POINTER; } } while (false)
;
1473
1474 *aDocumentViewer = mDocumentViewer;
1475 NS_IF_ADDREF(*aDocumentViewer)ns_if_addref(*aDocumentViewer);
1476 return NS_OK;
1477}
1478
1479NS_IMETHODIMPnsresult
1480nsDocShell::GetOuterWindowID(uint64_t* aWindowID) {
1481 *aWindowID = mContentWindowID;
1482 return NS_OK;
1483}
1484
1485NS_IMETHODIMPnsresult
1486nsDocShell::SetChromeEventHandler(EventTarget* aChromeEventHandler) {
1487 mChromeEventHandler = aChromeEventHandler;
1488
1489 if (mScriptGlobal) {
1490 mScriptGlobal->SetChromeEventHandler(mChromeEventHandler);
1491 }
1492
1493 return NS_OK;
1494}
1495
1496NS_IMETHODIMPnsresult
1497nsDocShell::GetChromeEventHandler(EventTarget** aChromeEventHandler) {
1498 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"
, 1498); return NS_ERROR_INVALID_POINTER; } } while (false)
;
1499 RefPtr<EventTarget> handler = mChromeEventHandler;
1500 handler.forget(aChromeEventHandler);
1501 return NS_OK;
1502}
1503
1504NS_IMETHODIMPnsresult
1505nsDocShell::SetCurrentURIForSessionStore(nsIURI* aURI) {
1506 // Note that securityUI will set STATE_IS_INSECURE, even if
1507 // the scheme of |aURI| is "https".
1508 SetCurrentURI(aURI, nullptr,
1509 /* aFireOnLocationChange */
1510 true,
1511 /* aIsInitialAboutBlank */
1512 false,
1513 /* aLocationFlags */
1514 nsIWebProgressListener::LOCATION_CHANGE_SESSION_STORE);
1515 return NS_OK;
1516}
1517
1518bool nsDocShell::SetCurrentURI(nsIURI* aURI, nsIRequest* aRequest,
1519 bool aFireOnLocationChange,
1520 bool aIsInitialAboutBlank,
1521 uint32_t aLocationFlags) {
1522 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"
, 1522); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mIsBeingDestroyed"
")"); do { *((volatile int*)__null) = 1522; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1523
1524 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)
1525 ("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)
1526 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)
;
1527
1528 // We don't want to send a location change when we're displaying an error
1529 // page, and we don't want to change our idea of "current URI" either
1530 if (mLoadType == LOAD_ERROR_PAGE) {
1531 return false;
1532 }
1533
1534 bool uriIsEqual = false;
1535 if (!mCurrentURI || !aURI ||
1536 NS_FAILED(mCurrentURI->Equals(aURI, &uriIsEqual))((bool)(__builtin_expect(!!(NS_FAILED_impl(mCurrentURI->Equals
(aURI, &uriIsEqual))), 0)))
|| !uriIsEqual) {
1537 mTitleValidForCurrentURI = false;
1538 }
1539
1540 SetCurrentURIInternal(aURI);
1541
1542#ifdef DEBUG1
1543 mLastOpenedURI = aURI;
1544#endif
1545
1546 if (!NS_IsAboutBlank(mCurrentURI)) {
1547 mHasLoadedNonBlankURI = true;
1548 }
1549
1550 // Don't fire onLocationChange when creating a subframe's initial about:blank
1551 // document, as this can happen when it's not safe for us to run script.
1552 if (aIsInitialAboutBlank && !mHasLoadedNonBlankURI &&
1553 !mBrowsingContext->IsTop()) {
1554 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"
, 1554); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aRequest && aLocationFlags == 0"
")"); do { *((volatile int*)__null) = 1554; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1555 return false;
1556 }
1557
1558 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"
, 1558); AnnotateMozCrashReason("MOZ_ASSERT" "(" "nsContentUtils::IsSafeToRunScript()"
")"); do { *((volatile int*)__null) = 1558; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1559
1560 if (aFireOnLocationChange) {
1561 FireOnLocationChange(this, aRequest, aURI, aLocationFlags);
1562 }
1563 return !aFireOnLocationChange;
1564}
1565
1566void nsDocShell::SetCurrentURIInternal(nsIURI* aURI) {
1567 mCurrentURI = aURI;
1568 if (mBrowsingContext) {
1569 mBrowsingContext->ClearCachedValuesOfLocations();
1570 }
1571}
1572
1573NS_IMETHODIMPnsresult
1574nsDocShell::GetCharset(nsACString& aCharset) {
1575 aCharset.Truncate();
1576
1577 PresShell* presShell = GetPresShell();
1578 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"
, 1578); return NS_ERROR_FAILURE; } } while (false)
;
1579 Document* doc = presShell->GetDocument();
1580 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"
, 1580); return NS_ERROR_FAILURE; } } while (false)
;
1581 doc->GetDocumentCharacterSet()->Name(aCharset);
1582 return NS_OK;
1583}
1584
1585NS_IMETHODIMPnsresult
1586nsDocShell::ForceEncodingDetection() {
1587 nsCOMPtr<nsIDocumentViewer> viewer;
1588 GetDocViewer(getter_AddRefs(viewer));
1589 if (!viewer) {
1590 return NS_OK;
1591 }
1592
1593 Document* doc = viewer->GetDocument();
1594 if (!doc || doc->WillIgnoreCharsetOverride()) {
1595 return NS_OK;
1596 }
1597
1598 mForcedAutodetection = true;
1599
1600 nsIURI* url = doc->GetOriginalURI();
1601 bool isFileURL = url && SchemeIsFile(url);
1602
1603 int32_t charsetSource = doc->GetDocumentCharacterSetSource();
1604 auto encoding = doc->GetDocumentCharacterSet();
1605 // AsHTMLDocument is valid, because we called
1606 // WillIgnoreCharsetOverride() above.
1607 if (doc->AsHTMLDocument()->IsPlainText()) {
1608 switch (charsetSource) {
1609 case kCharsetFromInitialAutoDetectionASCII:
1610 // Deliberately no final version
1611 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)
;
1612 Telemetry::AccumulateCategorical(
1613 Telemetry::LABELS_ENCODING_OVERRIDE_SITUATION_TEXT::UnlabeledAscii);
1614 break;
1615 case kCharsetFromInitialAutoDetectionWouldNotHaveBeenUTF8Generic:
1616 case kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8Generic:
1617 case kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8GenericInitialWasASCII:
1618 case kCharsetFromInitialAutoDetectionWouldNotHaveBeenUTF8Content:
1619 case kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8Content:
1620 case kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8ContentInitialWasASCII:
1621 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)
;
1622 Telemetry::AccumulateCategorical(
1623 Telemetry::LABELS_ENCODING_OVERRIDE_SITUATION_TEXT::
1624 UnlabeledNonUtf8);
1625 break;
1626 case kCharsetFromInitialAutoDetectionWouldNotHaveBeenUTF8DependedOnTLD:
1627 case kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8DependedOnTLD:
1628 case kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8DependedOnTLDInitialWasASCII:
1629 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)
;
1630 Telemetry::AccumulateCategorical(
1631 Telemetry::LABELS_ENCODING_OVERRIDE_SITUATION_TEXT::
1632 UnlabeledNonUtf8TLD);
1633 break;
1634 case kCharsetFromInitialAutoDetectionWouldHaveBeenUTF8:
1635 case kCharsetFromFinalAutoDetectionWouldHaveBeenUTF8InitialWasASCII:
1636 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)
;
1637 Telemetry::AccumulateCategorical(
1638 Telemetry::LABELS_ENCODING_OVERRIDE_SITUATION_TEXT::UnlabeledUtf8);
1639 break;
1640 case kCharsetFromChannel:
1641 if (encoding == UTF_8_ENCODING) {
1642 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)
;
1643 Telemetry::AccumulateCategorical(
1644 Telemetry::LABELS_ENCODING_OVERRIDE_SITUATION_TEXT::ChannelUtf8);
1645 } else {
1646 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)
;
1647 Telemetry::AccumulateCategorical(
1648 Telemetry::LABELS_ENCODING_OVERRIDE_SITUATION_TEXT::
1649 ChannelNonUtf8);
1650 }
1651 break;
1652 default:
1653 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)
;
1654 Telemetry::AccumulateCategorical(
1655 Telemetry::LABELS_ENCODING_OVERRIDE_SITUATION_TEXT::Bug);
1656 break;
1657 }
1658 } else {
1659 switch (charsetSource) {
1660 case kCharsetFromInitialAutoDetectionASCII:
1661 // Deliberately no final version
1662 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)
;
1663 Telemetry::AccumulateCategorical(
1664 Telemetry::LABELS_ENCODING_OVERRIDE_SITUATION_HTML::UnlabeledAscii);
1665 break;
1666 case kCharsetFromInitialAutoDetectionWouldNotHaveBeenUTF8Generic:
1667 case kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8Generic:
1668 case kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8GenericInitialWasASCII:
1669 case kCharsetFromInitialAutoDetectionWouldNotHaveBeenUTF8Content:
1670 case kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8Content:
1671 case kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8ContentInitialWasASCII:
1672 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)
;
1673 Telemetry::AccumulateCategorical(
1674 Telemetry::LABELS_ENCODING_OVERRIDE_SITUATION_HTML::
1675 UnlabeledNonUtf8);
1676 break;
1677 case kCharsetFromInitialAutoDetectionWouldNotHaveBeenUTF8DependedOnTLD:
1678 case kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8DependedOnTLD:
1679 case kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8DependedOnTLDInitialWasASCII:
1680 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)
;
1681 Telemetry::AccumulateCategorical(
1682 Telemetry::LABELS_ENCODING_OVERRIDE_SITUATION_HTML::
1683 UnlabeledNonUtf8TLD);
1684 break;
1685 case kCharsetFromInitialAutoDetectionWouldHaveBeenUTF8:
1686 case kCharsetFromFinalAutoDetectionWouldHaveBeenUTF8InitialWasASCII:
1687 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)
;
1688 Telemetry::AccumulateCategorical(
1689 Telemetry::LABELS_ENCODING_OVERRIDE_SITUATION_HTML::UnlabeledUtf8);
1690 break;
1691 case kCharsetFromChannel:
1692 if (encoding == UTF_8_ENCODING) {
1693 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)
;
1694 Telemetry::AccumulateCategorical(
1695 Telemetry::LABELS_ENCODING_OVERRIDE_SITUATION_HTML::ChannelUtf8);
1696 } else {
1697 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)
;
1698 Telemetry::AccumulateCategorical(
1699 Telemetry::LABELS_ENCODING_OVERRIDE_SITUATION_HTML::
1700 ChannelNonUtf8);
1701 }
1702 break;
1703 case kCharsetFromXmlDeclaration:
1704 case kCharsetFromMetaTag:
1705 if (isFileURL) {
1706 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)
;
1707 Telemetry::AccumulateCategorical(
1708 Telemetry::LABELS_ENCODING_OVERRIDE_SITUATION_HTML::LocalLabeled);
1709 } else if (encoding == UTF_8_ENCODING) {
1710 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)
;
1711 Telemetry::AccumulateCategorical(
1712 Telemetry::LABELS_ENCODING_OVERRIDE_SITUATION_HTML::InternalUtf8);
1713 } else {
1714 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)
;
1715 Telemetry::AccumulateCategorical(
1716 Telemetry::LABELS_ENCODING_OVERRIDE_SITUATION_HTML::
1717 InternalNonUtf8);
1718 }
1719 break;
1720 default:
1721 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)
;
1722 Telemetry::AccumulateCategorical(
1723 Telemetry::LABELS_ENCODING_OVERRIDE_SITUATION_HTML::Bug);
1724 break;
1725 }
1726 }
1727 return NS_OK;
1728}
1729
1730void nsDocShell::SetParentCharset(const Encoding*& aCharset,
1731 int32_t aCharsetSource,
1732 nsIPrincipal* aPrincipal) {
1733 mParentCharset = aCharset;
1734 mParentCharsetSource = aCharsetSource;
1735 mParentCharsetPrincipal = aPrincipal;
1736}
1737
1738void nsDocShell::GetParentCharset(const Encoding*& aCharset,
1739 int32_t* aCharsetSource,
1740 nsIPrincipal** aPrincipal) {
1741 aCharset = mParentCharset;
1742 *aCharsetSource = mParentCharsetSource;
1743 NS_IF_ADDREF(*aPrincipal = mParentCharsetPrincipal)ns_if_addref(*aPrincipal = mParentCharsetPrincipal);
1744}
1745
1746NS_IMETHODIMPnsresult
1747nsDocShell::GetHasTrackingContentBlocked(Promise** aPromise) {
1748 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"
, 1748); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPromise" ")"
); do { *((volatile int*)__null) = 1748; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1749
1750 ErrorResult rv;
1751 RefPtr<Document> doc(GetDocument());
1752 RefPtr<Promise> retPromise = Promise::Create(doc->GetOwnerGlobal(), rv);
1753 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"
, 1753)
) {
1754 return rv.StealNSResult();
1755 }
1756
1757 // Retrieve the document's content blocking events from the parent process.
1758 RefPtr<Document::GetContentBlockingEventsPromise> promise =
1759 doc->GetContentBlockingEvents();
1760 if (promise) {
1761 promise->Then(
1762 GetCurrentSerialEventTarget(), __func__,
1763 [retPromise](const Document::GetContentBlockingEventsPromise::
1764 ResolveOrRejectValue& aValue) {
1765 if (aValue.IsResolve()) {
1766 bool has = aValue.ResolveValue() &
1767 nsIWebProgressListener::STATE_BLOCKED_TRACKING_CONTENT;
1768 retPromise->MaybeResolve(has);
1769 } else {
1770 retPromise->MaybeResolve(false);
1771 }
1772 });
1773 } else {
1774 retPromise->MaybeResolve(false);
1775 }
1776
1777 retPromise.forget(aPromise);
1778 return NS_OK;
1779}
1780
1781NS_IMETHODIMPnsresult
1782nsDocShell::GetAllowPlugins(bool* aAllowPlugins) {
1783 NS_ENSURE_ARG_POINTER(aAllowPlugins)do { if ((__builtin_expect(!!(!(aAllowPlugins)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aAllowPlugins" ") failed"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 1783); return NS_ERROR_INVALID_POINTER; } } while (false)
;
1784
1785 *aAllowPlugins = mBrowsingContext->GetAllowPlugins();
1786 return NS_OK;
1787}
1788
1789NS_IMETHODIMPnsresult
1790nsDocShell::SetAllowPlugins(bool aAllowPlugins) {
1791 // XXX should enable or disable a plugin host
1792 return mBrowsingContext->SetAllowPlugins(aAllowPlugins);
1793}
1794
1795NS_IMETHODIMPnsresult
1796nsDocShell::GetCssErrorReportingEnabled(bool* aEnabled) {
1797 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"
, 1797); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aEnabled" ")"
); do { *((volatile int*)__null) = 1797; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1798 *aEnabled = mCSSErrorReportingEnabled;
1799 return NS_OK;
1800}
1801
1802NS_IMETHODIMPnsresult
1803nsDocShell::SetCssErrorReportingEnabled(bool aEnabled) {
1804 mCSSErrorReportingEnabled = aEnabled;
1805 return NS_OK;
1806}
1807
1808NS_IMETHODIMPnsresult
1809nsDocShell::GetUsePrivateBrowsing(bool* aUsePrivateBrowsing) {
1810 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"
, 1810); return NS_ERROR_INVALID_POINTER; } } while (false)
;
1811 return mBrowsingContext->GetUsePrivateBrowsing(aUsePrivateBrowsing);
1812}
1813
1814void nsDocShell::NotifyPrivateBrowsingChanged() {
1815 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"
, 1815); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mIsBeingDestroyed"
")"); do { *((volatile int*)__null) = 1815; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1816
1817 nsTObserverArray<nsWeakPtr>::ForwardIterator iter(mPrivacyObservers);
1818 while (iter.HasMore()) {
1819 nsWeakPtr ref = iter.GetNext();
1820 nsCOMPtr<nsIPrivacyTransitionObserver> obs = do_QueryReferent(ref);
1821 if (!obs) {
1822 iter.Remove();
1823 } else {
1824 obs->PrivateModeChanged(UsePrivateBrowsing());
1825 }
1826 }
1827}
1828
1829NS_IMETHODIMPnsresult
1830nsDocShell::SetUsePrivateBrowsing(bool aUsePrivateBrowsing) {
1831 return mBrowsingContext->SetUsePrivateBrowsing(aUsePrivateBrowsing);
1832}
1833
1834NS_IMETHODIMPnsresult
1835nsDocShell::SetPrivateBrowsing(bool aUsePrivateBrowsing) {
1836 return mBrowsingContext->SetPrivateBrowsing(aUsePrivateBrowsing);
1837}
1838
1839NS_IMETHODIMPnsresult
1840nsDocShell::GetHasLoadedNonBlankURI(bool* aResult) {
1841 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"
, 1841); return NS_ERROR_INVALID_POINTER; } } while (false)
;
1842
1843 *aResult = mHasLoadedNonBlankURI;
1844 return NS_OK;
1845}
1846
1847NS_IMETHODIMPnsresult
1848nsDocShell::GetUseRemoteTabs(bool* aUseRemoteTabs) {
1849 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"
, 1849); return NS_ERROR_INVALID_POINTER; } } while (false)
;
1850 return mBrowsingContext->GetUseRemoteTabs(aUseRemoteTabs);
1851}
1852
1853NS_IMETHODIMPnsresult
1854nsDocShell::SetRemoteTabs(bool aUseRemoteTabs) {
1855 return mBrowsingContext->SetRemoteTabs(aUseRemoteTabs);
1856}
1857
1858NS_IMETHODIMPnsresult
1859nsDocShell::GetUseRemoteSubframes(bool* aUseRemoteSubframes) {
1860 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"
, 1860); return NS_ERROR_INVALID_POINTER; } } while (false)
;
1861 return mBrowsingContext->GetUseRemoteSubframes(aUseRemoteSubframes);
1862}
1863
1864NS_IMETHODIMPnsresult
1865nsDocShell::SetRemoteSubframes(bool aUseRemoteSubframes) {
1866 return mBrowsingContext->SetRemoteSubframes(aUseRemoteSubframes);
1867}
1868
1869NS_IMETHODIMPnsresult
1870nsDocShell::AddWeakPrivacyTransitionObserver(
1871 nsIPrivacyTransitionObserver* aObserver) {
1872 nsWeakPtr weakObs = do_GetWeakReference(aObserver);
1873 if (!weakObs) {
1874 return NS_ERROR_NOT_AVAILABLE;
1875 }
1876 mPrivacyObservers.AppendElement(weakObs);
1877 return NS_OK;
1878}
1879
1880NS_IMETHODIMPnsresult
1881nsDocShell::AddWeakReflowObserver(nsIReflowObserver* aObserver) {
1882 nsWeakPtr weakObs = do_GetWeakReference(aObserver);
1883 if (!weakObs) {
1884 return NS_ERROR_FAILURE;
1885 }
1886 mReflowObservers.AppendElement(weakObs);
1887 return NS_OK;
1888}
1889
1890NS_IMETHODIMPnsresult
1891nsDocShell::RemoveWeakReflowObserver(nsIReflowObserver* aObserver) {
1892 nsWeakPtr obs = do_GetWeakReference(aObserver);
1893 return mReflowObservers.RemoveElement(obs) ? NS_OK : NS_ERROR_FAILURE;
1894}
1895
1896NS_IMETHODIMPnsresult
1897nsDocShell::NotifyReflowObservers(bool aInterruptible,
1898 DOMHighResTimeStamp aStart,
1899 DOMHighResTimeStamp aEnd) {
1900 nsTObserverArray<nsWeakPtr>::ForwardIterator iter(mReflowObservers);
1901 while (iter.HasMore()) {
1902 nsWeakPtr ref = iter.GetNext();
1903 nsCOMPtr<nsIReflowObserver> obs = do_QueryReferent(ref);
1904 if (!obs) {
1905 iter.Remove();
1906 } else if (aInterruptible) {
1907 obs->ReflowInterruptible(aStart, aEnd);
1908 } else {
1909 obs->Reflow(aStart, aEnd);
1910 }
1911 }
1912 return NS_OK;
1913}
1914
1915NS_IMETHODIMPnsresult
1916nsDocShell::GetAllowMetaRedirects(bool* aReturn) {
1917 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"
, 1917); return NS_ERROR_INVALID_POINTER; } } while (false)
;
1918
1919 *aReturn = mAllowMetaRedirects;
1920 return NS_OK;
1921}
1922
1923NS_IMETHODIMPnsresult
1924nsDocShell::SetAllowMetaRedirects(bool aValue) {
1925 mAllowMetaRedirects = aValue;
1926 return NS_OK;
1927}
1928
1929NS_IMETHODIMPnsresult
1930nsDocShell::GetAllowSubframes(bool* aAllowSubframes) {
1931 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"
, 1931); return NS_ERROR_INVALID_POINTER; } } while (false)
;
1932
1933 *aAllowSubframes = mAllowSubframes;
1934 return NS_OK;
1935}
1936
1937NS_IMETHODIMPnsresult
1938nsDocShell::SetAllowSubframes(bool aAllowSubframes) {
1939 mAllowSubframes = aAllowSubframes;
1940 return NS_OK;
1941}
1942
1943NS_IMETHODIMPnsresult
1944nsDocShell::GetAllowImages(bool* aAllowImages) {
1945 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"
, 1945); return NS_ERROR_INVALID_POINTER; } } while (false)
;
1946
1947 *aAllowImages = mAllowImages;
1948 return NS_OK;
1949}
1950
1951NS_IMETHODIMPnsresult
1952nsDocShell::SetAllowImages(bool aAllowImages) {
1953 mAllowImages = aAllowImages;
1954 return NS_OK;
1955}
1956
1957NS_IMETHODIMPnsresult
1958nsDocShell::GetAllowMedia(bool* aAllowMedia) {
1959 *aAllowMedia = mAllowMedia;
1960 return NS_OK;
1961}
1962
1963NS_IMETHODIMPnsresult
1964nsDocShell::SetAllowMedia(bool aAllowMedia) {
1965 mAllowMedia = aAllowMedia;
1966
1967 // Mute or unmute audio contexts attached to the inner window.
1968 if (mScriptGlobal) {
1969 if (nsPIDOMWindowInner* innerWin = mScriptGlobal->GetCurrentInnerWindow()) {
1970 if (aAllowMedia) {
1971 innerWin->UnmuteAudioContexts();
1972 } else {
1973 innerWin->MuteAudioContexts();
1974 }
1975 }
1976 }
1977
1978 return NS_OK;
1979}
1980
1981NS_IMETHODIMPnsresult
1982nsDocShell::GetAllowDNSPrefetch(bool* aAllowDNSPrefetch) {
1983 *aAllowDNSPrefetch = mAllowDNSPrefetch;
1984 return NS_OK;
1985}
1986
1987NS_IMETHODIMPnsresult
1988nsDocShell::SetAllowDNSPrefetch(bool aAllowDNSPrefetch) {
1989 mAllowDNSPrefetch = aAllowDNSPrefetch;
1990 return NS_OK;
1991}
1992
1993NS_IMETHODIMPnsresult
1994nsDocShell::GetAllowWindowControl(bool* aAllowWindowControl) {
1995 *aAllowWindowControl = mAllowWindowControl;
1996 return NS_OK;
1997}
1998
1999NS_IMETHODIMPnsresult
2000nsDocShell::SetAllowWindowControl(bool aAllowWindowControl) {
2001 mAllowWindowControl = aAllowWindowControl;
2002 return NS_OK;
2003}
2004
2005NS_IMETHODIMPnsresult
2006nsDocShell::GetAllowContentRetargeting(bool* aAllowContentRetargeting) {
2007 *aAllowContentRetargeting = mBrowsingContext->GetAllowContentRetargeting();
2008 return NS_OK;
2009}
2010
2011NS_IMETHODIMPnsresult
2012nsDocShell::SetAllowContentRetargeting(bool aAllowContentRetargeting) {
2013 BrowsingContext::Transaction txn;
2014 txn.SetAllowContentRetargeting(aAllowContentRetargeting);
2015 txn.SetAllowContentRetargetingOnChildren(aAllowContentRetargeting);
2016 return txn.Commit(mBrowsingContext);
2017}
2018
2019NS_IMETHODIMPnsresult
2020nsDocShell::GetAllowContentRetargetingOnChildren(
2021 bool* aAllowContentRetargetingOnChildren) {
2022 *aAllowContentRetargetingOnChildren =
2023 mBrowsingContext->GetAllowContentRetargetingOnChildren();
2024 return NS_OK;
2025}
2026
2027NS_IMETHODIMPnsresult
2028nsDocShell::SetAllowContentRetargetingOnChildren(
2029 bool aAllowContentRetargetingOnChildren) {
2030 return mBrowsingContext->SetAllowContentRetargetingOnChildren(
2031 aAllowContentRetargetingOnChildren);
2032}
2033
2034NS_IMETHODIMPnsresult
2035nsDocShell::GetMayEnableCharacterEncodingMenu(
2036 bool* aMayEnableCharacterEncodingMenu) {
2037 *aMayEnableCharacterEncodingMenu = false;
2038 if (!mDocumentViewer) {
2039 return NS_OK;
2040 }
2041 Document* doc = mDocumentViewer->GetDocument();
2042 if (!doc) {
2043 return NS_OK;
2044 }
2045 if (doc->WillIgnoreCharsetOverride()) {
2046 return NS_OK;
2047 }
2048
2049 *aMayEnableCharacterEncodingMenu = true;
2050 return NS_OK;
2051}
2052
2053NS_IMETHODIMPnsresult
2054nsDocShell::GetAllDocShellsInSubtree(int32_t aItemType,
2055 DocShellEnumeratorDirection aDirection,
2056 nsTArray<RefPtr<nsIDocShell>>& aResult) {
2057 aResult.Clear();
2058
2059 nsDocShellEnumerator docShellEnum(
2060 (aDirection == ENUMERATE_FORWARDS)
2061 ? nsDocShellEnumerator::EnumerationDirection::Forwards
2062 : nsDocShellEnumerator::EnumerationDirection::Backwards,
2063 aItemType, *this);
2064
2065 nsresult rv = docShellEnum.BuildDocShellArray(aResult);
2066 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2067 return rv;
2068 }
2069
2070 return NS_OK;
2071}
2072
2073NS_IMETHODIMPnsresult
2074nsDocShell::GetAppType(AppType* aAppType) {
2075 *aAppType = mAppType;
2076 return NS_OK;
2077}
2078
2079NS_IMETHODIMPnsresult
2080nsDocShell::SetAppType(AppType aAppType) {
2081 mAppType = aAppType;
2082 return NS_OK;
2083}
2084
2085NS_IMETHODIMPnsresult
2086nsDocShell::GetAllowAuth(bool* aAllowAuth) {
2087 *aAllowAuth = mAllowAuth;
2088 return NS_OK;
2089}
2090
2091NS_IMETHODIMPnsresult
2092nsDocShell::SetAllowAuth(bool aAllowAuth) {
2093 mAllowAuth = aAllowAuth;
2094 return NS_OK;
2095}
2096
2097NS_IMETHODIMPnsresult
2098nsDocShell::GetZoom(float* aZoom) {
2099 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"
, 2099); return NS_ERROR_INVALID_POINTER; } } while (false)
;
2100 *aZoom = 1.0f;
2101 return NS_OK;
2102}
2103
2104NS_IMETHODIMPnsresult
2105nsDocShell::SetZoom(float aZoom) { return NS_ERROR_NOT_IMPLEMENTED; }
2106
2107NS_IMETHODIMPnsresult
2108nsDocShell::GetBusyFlags(BusyFlags* aBusyFlags) {
2109 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"
, 2109); return NS_ERROR_INVALID_POINTER; } } while (false)
;
2110
2111 *aBusyFlags = mBusyFlags;
2112 return NS_OK;
2113}
2114
2115NS_IMETHODIMPnsresult
2116nsDocShell::TabToTreeOwner(bool aForward, bool aForDocumentNavigation,
2117 bool* aTookFocus) {
2118 NS_ENSURE_ARG_POINTER(aTookFocus)do { if ((__builtin_expect(!!(!(aTookFocus)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aTookFocus" ") failed",
nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 2118); return NS_ERROR_INVALID_POINTER; } } while (false)
;
2119
2120 nsCOMPtr<nsIWebBrowserChromeFocus> chromeFocus = do_GetInterface(mTreeOwner);
2121 if (chromeFocus) {
2122 if (aForward) {
2123 *aTookFocus =
2124 NS_SUCCEEDED(chromeFocus->FocusNextElement(aForDocumentNavigation))((bool)(__builtin_expect(!!(!NS_FAILED_impl(chromeFocus->FocusNextElement
(aForDocumentNavigation))), 1)))
;
2125 } else {
2126 *aTookFocus =
2127 NS_SUCCEEDED(chromeFocus->FocusPrevElement(aForDocumentNavigation))((bool)(__builtin_expect(!!(!NS_FAILED_impl(chromeFocus->FocusPrevElement
(aForDocumentNavigation))), 1)))
;
2128 }
2129 } else {
2130 *aTookFocus = false;
2131 }
2132
2133 return NS_OK;
2134}
2135
2136NS_IMETHODIMPnsresult
2137nsDocShell::GetLoadURIDelegate(nsILoadURIDelegate** aLoadURIDelegate) {
2138 nsCOMPtr<nsILoadURIDelegate> delegate = GetLoadURIDelegate();
2139 delegate.forget(aLoadURIDelegate);
2140 return NS_OK;
2141}
2142
2143already_AddRefed<nsILoadURIDelegate> nsDocShell::GetLoadURIDelegate() {
2144 if (nsCOMPtr<nsILoadURIDelegate> result =
2145 do_QueryActor("LoadURIDelegate", GetDocument())) {
2146 return result.forget();
2147 }
2148
2149 return nullptr;
2150}
2151
2152NS_IMETHODIMPnsresult
2153nsDocShell::GetUseErrorPages(bool* aUseErrorPages) {
2154 *aUseErrorPages = mBrowsingContext->GetUseErrorPages();
2155 return NS_OK;
2156}
2157
2158NS_IMETHODIMPnsresult
2159nsDocShell::SetUseErrorPages(bool aUseErrorPages) {
2160 return mBrowsingContext->SetUseErrorPages(aUseErrorPages);
2161}
2162
2163NS_IMETHODIMPnsresult
2164nsDocShell::GetPreviousEntryIndex(int32_t* aPreviousEntryIndex) {
2165 *aPreviousEntryIndex = mPreviousEntryIndex;
2166 return NS_OK;
2167}
2168
2169NS_IMETHODIMPnsresult
2170nsDocShell::GetLoadedEntryIndex(int32_t* aLoadedEntryIndex) {
2171 *aLoadedEntryIndex = mLoadedEntryIndex;
2172 return NS_OK;
2173}
2174
2175NS_IMETHODIMPnsresult
2176nsDocShell::HistoryPurged(int32_t aNumEntries) {
2177 // These indices are used for fastback cache eviction, to determine
2178 // which session history entries are candidates for content viewer
2179 // eviction. We need to adjust by the number of entries that we
2180 // just purged from history, so that we look at the right session history
2181 // entries during eviction.
2182 mPreviousEntryIndex = std::max(-1, mPreviousEntryIndex - aNumEntries);
2183 mLoadedEntryIndex = std::max(0, mLoadedEntryIndex - aNumEntries);
2184
2185 for (auto* child : mChildList.ForwardRange()) {
2186 nsCOMPtr<nsIDocShell> shell = do_QueryObject(child);
2187 if (shell) {
2188 shell->HistoryPurged(aNumEntries);
2189 }
2190 }
2191
2192 return NS_OK;
2193}
2194
2195void nsDocShell::TriggerParentCheckDocShellIsEmpty() {
2196 if (RefPtr<nsDocShell> parent = GetInProcessParentDocshell()) {
2197 parent->DocLoaderIsEmpty(true);
2198 }
2199 if (GetBrowsingContext()->IsContentSubframe() &&
2200 !GetBrowsingContext()->GetParent()->IsInProcess()) {
2201 if (BrowserChild* browserChild = BrowserChild::GetFrom(this)) {
2202 mozilla::Unused << browserChild->SendMaybeFireEmbedderLoadEvents(
2203 EmbedderElementEventType::NoEvent);
2204 }
2205 }
2206}
2207
2208nsresult nsDocShell::HistoryEntryRemoved(int32_t aIndex) {
2209 // These indices are used for fastback cache eviction, to determine
2210 // which session history entries are candidates for content viewer
2211 // eviction. We need to adjust by the number of entries that we
2212 // just purged from history, so that we look at the right session history
2213 // entries during eviction.
2214 if (aIndex == mPreviousEntryIndex) {
2215 mPreviousEntryIndex = -1;
2216 } else if (aIndex < mPreviousEntryIndex) {
2217 --mPreviousEntryIndex;
2218 }
2219 if (mLoadedEntryIndex == aIndex) {
2220 mLoadedEntryIndex = 0;
2221 } else if (aIndex < mLoadedEntryIndex) {
2222 --mLoadedEntryIndex;
2223 }
2224
2225 for (auto* child : mChildList.ForwardRange()) {
2226 nsCOMPtr<nsIDocShell> shell = do_QueryObject(child);
2227 if (shell) {
2228 static_cast<nsDocShell*>(shell.get())->HistoryEntryRemoved(aIndex);
2229 }
2230 }
2231
2232 return NS_OK;
2233}
2234
2235nsresult nsDocShell::Now(DOMHighResTimeStamp* aWhen) {
2236 *aWhen = (TimeStamp::Now() - TimeStamp::ProcessCreation()).ToMilliseconds();
2237 return NS_OK;
2238}
2239
2240NS_IMETHODIMPnsresult
2241nsDocShell::SetWindowDraggingAllowed(bool aValue) {
2242 RefPtr<nsDocShell> parent = GetInProcessParentDocshell();
2243 if (!aValue && mItemType == typeChrome && !parent) {
2244 // Window dragging is always allowed for top level
2245 // chrome docshells.
2246 return NS_ERROR_FAILURE;
2247 }
2248 mWindowDraggingAllowed = aValue;
2249 return NS_OK;
2250}
2251
2252NS_IMETHODIMPnsresult
2253nsDocShell::GetWindowDraggingAllowed(bool* aValue) {
2254 // window dragging regions in CSS (-moz-window-drag:drag)
2255 // can be slow. Default behavior is to only allow it for
2256 // chrome top level windows.
2257 RefPtr<nsDocShell> parent = GetInProcessParentDocshell();
2258 if (mItemType == typeChrome && !parent) {
2259 // Top level chrome window
2260 *aValue = true;
2261 } else {
2262 *aValue = mWindowDraggingAllowed;
2263 }
2264 return NS_OK;
2265}
2266
2267NS_IMETHODIMPnsresult
2268nsDocShell::GetCurrentDocumentChannel(nsIChannel** aResult) {
2269 NS_IF_ADDREF(*aResult = GetCurrentDocChannel())ns_if_addref(*aResult = GetCurrentDocChannel());
2270 return NS_OK;
2271}
2272
2273nsIChannel* nsDocShell::GetCurrentDocChannel() {
2274 if (mDocumentViewer) {
2275 Document* doc = mDocumentViewer->GetDocument();
2276 if (doc) {
2277 return doc->GetChannel();
2278 }
2279 }
2280 return nullptr;
2281}
2282
2283NS_IMETHODIMPnsresult
2284nsDocShell::AddWeakScrollObserver(nsIScrollObserver* aObserver) {
2285 nsWeakPtr weakObs = do_GetWeakReference(aObserver);
2286 if (!weakObs) {
2287 return NS_ERROR_FAILURE;
2288 }
2289 mScrollObservers.AppendElement(weakObs);
2290 return NS_OK;
2291}
2292
2293NS_IMETHODIMPnsresult
2294nsDocShell::RemoveWeakScrollObserver(nsIScrollObserver* aObserver) {
2295 nsWeakPtr obs = do_GetWeakReference(aObserver);
2296 return mScrollObservers.RemoveElement(obs) ? NS_OK : NS_ERROR_FAILURE;
2297}
2298
2299void nsDocShell::NotifyAsyncPanZoomStarted() {
2300 nsTObserverArray<nsWeakPtr>::ForwardIterator iter(mScrollObservers);
2301 while (iter.HasMore()) {
2302 nsWeakPtr ref = iter.GetNext();
2303 nsCOMPtr<nsIScrollObserver> obs = do_QueryReferent(ref);
2304 if (obs) {
2305 obs->AsyncPanZoomStarted();
2306 } else {
2307 iter.Remove();
2308 }
2309 }
2310}
2311
2312void nsDocShell::NotifyAsyncPanZoomStopped() {
2313 nsTObserverArray<nsWeakPtr>::ForwardIterator iter(mScrollObservers);
2314 while (iter.HasMore()) {
2315 nsWeakPtr ref = iter.GetNext();
2316 nsCOMPtr<nsIScrollObserver> obs = do_QueryReferent(ref);
2317 if (obs) {
2318 obs->AsyncPanZoomStopped();
2319 } else {
2320 iter.Remove();
2321 }
2322 }
2323}
2324
2325NS_IMETHODIMPnsresult
2326nsDocShell::NotifyScrollObservers() {
2327 nsTObserverArray<nsWeakPtr>::ForwardIterator iter(mScrollObservers);
2328 while (iter.HasMore()) {
2329 nsWeakPtr ref = iter.GetNext();
2330 nsCOMPtr<nsIScrollObserver> obs = do_QueryReferent(ref);
2331 if (obs) {
2332 obs->ScrollPositionChanged();
2333 } else {
2334 iter.Remove();
2335 }
2336 }
2337 return NS_OK;
2338}
2339
2340//*****************************************************************************
2341// nsDocShell::nsIDocShellTreeItem
2342//*****************************************************************************
2343
2344NS_IMETHODIMPnsresult
2345nsDocShell::GetName(nsAString& aName) {
2346 aName = mBrowsingContext->Name();
2347 return NS_OK;
2348}
2349
2350NS_IMETHODIMPnsresult
2351nsDocShell::SetName(const nsAString& aName) {
2352 return mBrowsingContext->SetName(aName);
2353}
2354
2355NS_IMETHODIMPnsresult
2356nsDocShell::NameEquals(const nsAString& aName, bool* aResult) {
2357 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"
, 2357); return NS_ERROR_INVALID_POINTER; } } while (false)
;
2358 *aResult = mBrowsingContext->NameEquals(aName);
2359 return NS_OK;
2360}
2361
2362NS_IMETHODIMPnsresult
2363nsDocShell::GetCustomUserAgent(nsAString& aCustomUserAgent) {
2364 mBrowsingContext->GetCustomUserAgent(aCustomUserAgent);
2365 return NS_OK;
2366}
2367
2368NS_IMETHODIMPnsresult
2369nsDocShell::SetCustomUserAgent(const nsAString& aCustomUserAgent) {
2370 if (mWillChangeProcess) {
2371 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"
, 2371)
;
2372 return NS_ERROR_FAILURE;
2373 }
2374
2375 return mBrowsingContext->SetCustomUserAgent(aCustomUserAgent);
2376}
2377
2378NS_IMETHODIMPnsresult
2379nsDocShell::ClearCachedPlatform() {
2380 nsCOMPtr<nsPIDOMWindowInner> win =
2381 mScriptGlobal ? mScriptGlobal->GetCurrentInnerWindow() : nullptr;
2382 if (win) {
2383 Navigator* navigator = win->Navigator();
2384 if (navigator) {
2385 navigator->ClearPlatformCache();
2386 }
2387 }
2388
2389 return NS_OK;
2390}
2391
2392NS_IMETHODIMPnsresult
2393nsDocShell::ClearCachedUserAgent() {
2394 nsCOMPtr<nsPIDOMWindowInner> win =
2395 mScriptGlobal ? mScriptGlobal->GetCurrentInnerWindow() : nullptr;
2396 if (win) {
2397 Navigator* navigator = win->Navigator();
2398 if (navigator) {
2399 navigator->ClearUserAgentCache();
2400 }
2401 }
2402
2403 return NS_OK;
2404}
2405
2406NS_IMETHODIMPnsresult
2407nsDocShell::GetMetaViewportOverride(
2408 MetaViewportOverride* aMetaViewportOverride) {
2409 NS_ENSURE_ARG_POINTER(aMetaViewportOverride)do { if ((__builtin_expect(!!(!(aMetaViewportOverride)), 0)))
{ NS_DebugBreak(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aMetaViewportOverride"
") failed", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 2409); return NS_ERROR_INVALID_POINTER; } } while (false)
;
2410
2411 *aMetaViewportOverride = mMetaViewportOverride;
2412 return NS_OK;
2413}
2414
2415NS_IMETHODIMPnsresult
2416nsDocShell::SetMetaViewportOverride(
2417 MetaViewportOverride aMetaViewportOverride) {
2418 // We don't have a way to verify this coming from Javascript, so this check is
2419 // still needed.
2420 if (!(aMetaViewportOverride == META_VIEWPORT_OVERRIDE_NONE ||
2421 aMetaViewportOverride == META_VIEWPORT_OVERRIDE_ENABLED ||
2422 aMetaViewportOverride == META_VIEWPORT_OVERRIDE_DISABLED)) {
2423 return NS_ERROR_INVALID_ARG;
2424 }
2425
2426 mMetaViewportOverride = aMetaViewportOverride;
2427
2428 // Inform our presShell that it needs to re-check its need for a viewport
2429 // override.
2430 if (RefPtr<PresShell> presShell = GetPresShell()) {
2431 presShell->MaybeRecreateMobileViewportManager(true);
2432 }
2433
2434 return NS_OK;
2435}
2436
2437/* virtual */
2438int32_t nsDocShell::ItemType() { return mItemType; }
2439
2440NS_IMETHODIMPnsresult
2441nsDocShell::GetItemType(int32_t* aItemType) {
2442 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"
, 2442); return NS_ERROR_INVALID_POINTER; } } while (false)
;
2443
2444 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"
, 2445); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "(mBrowsingContext->IsContent() ? typeContent : typeChrome) == mItemType"
")"); do { *((volatile int*)__null) = 2445; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2445 (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"
, 2445); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "(mBrowsingContext->IsContent() ? typeContent : typeChrome) == mItemType"
")"); do { *((volatile int*)__null) = 2445; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2446 *aItemType = mItemType;
2447 return NS_OK;
2448}
2449
2450NS_IMETHODIMPnsresult
2451nsDocShell::GetInProcessParent(nsIDocShellTreeItem** aParent) {
2452 if (!mParent) {
2453 *aParent = nullptr;
2454 } else {
2455 CallQueryInterface(mParent, aParent);
2456 }
2457 // Note that in the case when the parent is not an nsIDocShellTreeItem we
2458 // don't want to throw; we just want to return null.
2459 return NS_OK;
2460}
2461
2462// With Fission, related nsDocShell objects may exist in a different process. In
2463// that case, this method will return `nullptr`, despite a parent nsDocShell
2464// object existing.
2465//
2466// Prefer using `BrowsingContext::Parent()`, which will succeed even if the
2467// parent entry is not in the current process, and handle the case where the
2468// parent nsDocShell is inaccessible.
2469already_AddRefed<nsDocShell> nsDocShell::GetInProcessParentDocshell() {
2470 nsCOMPtr<nsIDocShell> docshell = do_QueryInterface(GetAsSupports(mParent));
2471 return docshell.forget().downcast<nsDocShell>();
2472}
2473
2474void nsDocShell::MaybeCreateInitialClientSource(nsIPrincipal* aPrincipal) {
2475 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"
, 2475); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mIsBeingDestroyed"
")"); do { *((volatile int*)__null) = 2475; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2476
2477 // If there is an existing document then there is no need to create
2478 // a client for a future initial about:blank document.
2479 if (mScriptGlobal && mScriptGlobal->GetCurrentInnerWindow() &&
2480 mScriptGlobal->GetCurrentInnerWindow()->GetExtantDoc()) {
2481 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"
, 2482); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "mScriptGlobal->GetCurrentInnerWindow()->GetClientInfo().isSome()"
")"); do { *((volatile int*)__null) = 2482; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2482 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"
, 2482); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "mScriptGlobal->GetCurrentInnerWindow()->GetClientInfo().isSome()"
")"); do { *((volatile int*)__null) = 2482; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2483 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"
, 2483); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "!mInitialClientSource"
")"); do { *((volatile int*)__null) = 2483; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2484 return;
2485 }
2486
2487 // Don't recreate the initial client source. We call this multiple times
2488 // when DoChannelLoad() is called before CreateAboutBlankDocumentViewer.
2489 if (mInitialClientSource) {
2490 return;
2491 }
2492
2493 // Don't pre-allocate the client when we are sandboxed. The inherited
2494 // principal does not take sandboxing into account.
2495 // TODO: Refactor sandboxing principal code out so we can use it here.
2496 if (!aPrincipal && mBrowsingContext->GetSandboxFlags()) {
2497 return;
2498 }
2499
2500 // We cannot get inherited foreign partitioned principal here. Instead, we
2501 // directly check which principal we want to inherit for the service worker.
2502 nsIPrincipal* principal =
2503 aPrincipal
2504 ? aPrincipal
2505 : GetInheritedPrincipal(
2506 false, StoragePrincipalHelper::
2507 ShouldUsePartitionPrincipalForServiceWorker(this));
2508
2509 // Sometimes there is no principal available when we are called from
2510 // CreateAboutBlankDocumentViewer. For example, sometimes the principal
2511 // is only extracted from the load context after the document is created
2512 // in Document::ResetToURI(). Ideally we would do something similar
2513 // here, but for now lets just avoid the issue by not preallocating the
2514 // client.
2515 if (!principal) {
2516 return;
2517 }
2518
2519 nsCOMPtr<nsPIDOMWindowOuter> win = GetWindow();
2520 if (!win) {
2521 return;
2522 }
2523
2524 mInitialClientSource = ClientManager::CreateSource(
2525 ClientType::Window, GetMainThreadSerialEventTarget(), principal);
2526 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"
, 2526); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "mInitialClientSource"
")"); do { *((volatile int*)__null) = 2526; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2527
2528 // Mark the initial client as execution ready, but owned by the docshell.
2529 // If the client is actually used this will cause ClientSource to force
2530 // the creation of the initial about:blank by calling
2531 // nsDocShell::GetDocument().
2532 mInitialClientSource->DocShellExecutionReady(this);
2533
2534 // Next, check to see if the parent is controlled.
2535 nsCOMPtr<nsIDocShell> parent = GetInProcessParentDocshell();
2536 nsPIDOMWindowOuter* parentOuter = parent ? parent->GetWindow() : nullptr;
2537 nsPIDOMWindowInner* parentInner =
2538 parentOuter ? parentOuter->GetCurrentInnerWindow() : nullptr;
2539 if (!parentInner) {
2540 return;
2541 }
2542
2543 nsCOMPtr<nsIURI> uri;
2544 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"
, 2544); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "false"
") (" "NS_SUCCEEDED(NS_NewURI(getter_AddRefs(uri), \"about:blank\"_ns))"
")"); do { *((volatile int*)__null) = 2544; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
2545
2546 // We're done if there is no parent controller or if this docshell
2547 // is not permitted to control for some reason.
2548 Maybe<ServiceWorkerDescriptor> controller(parentInner->GetController());
2549 if (controller.isNothing() ||
2550 !ServiceWorkerAllowedToControlWindow(principal, uri)) {
2551 return;
2552 }
2553
2554 mInitialClientSource->InheritController(controller.ref());
2555}
2556
2557Maybe<ClientInfo> nsDocShell::GetInitialClientInfo() const {
2558 if (mInitialClientSource) {
2559 Maybe<ClientInfo> result;
2560 result.emplace(mInitialClientSource->Info());
2561 return result;
2562 }
2563
2564 nsPIDOMWindowInner* innerWindow =
2565 mScriptGlobal ? mScriptGlobal->GetCurrentInnerWindow() : nullptr;
2566 Document* doc = innerWindow ? innerWindow->GetExtantDoc() : nullptr;
2567
2568 if (!doc || !doc->IsInitialDocument()) {
2569 return Maybe<ClientInfo>();
2570 }
2571
2572 return innerWindow->GetClientInfo();
2573}
2574
2575nsresult nsDocShell::SetDocLoaderParent(nsDocLoader* aParent) {
2576 bool wasFrame = IsSubframe();
2577
2578 nsresult rv = nsDocLoader::SetDocLoaderParent(aParent);
2579 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"
, 2579); return rv; } } while (false)
;
2580
2581 nsCOMPtr<nsISupportsPriority> priorityGroup = do_QueryInterface(mLoadGroup);
2582 if (wasFrame != IsSubframe() && priorityGroup) {
2583 priorityGroup->AdjustPriority(wasFrame ? -1 : 1);
2584 }
2585
2586 // Curse ambiguous nsISupports inheritance!
2587 nsISupports* parent = GetAsSupports(aParent);
2588
2589 // If parent is another docshell, we inherit all their flags for
2590 // allowing plugins, scripting etc.
2591 bool value;
2592 nsCOMPtr<nsIDocShell> parentAsDocShell(do_QueryInterface(parent));
2593
2594 if (parentAsDocShell) {
2595 if (mAllowMetaRedirects &&
2596 NS_SUCCEEDED(parentAsDocShell->GetAllowMetaRedirects(&value))((bool)(__builtin_expect(!!(!NS_FAILED_impl(parentAsDocShell->
GetAllowMetaRedirects(&value))), 1)))
) {
2597 SetAllowMetaRedirects(value);
2598 }
2599 if (mAllowSubframes &&
2600 NS_SUCCEEDED(parentAsDocShell->GetAllowSubframes(&value))((bool)(__builtin_expect(!!(!NS_FAILED_impl(parentAsDocShell->
GetAllowSubframes(&value))), 1)))
) {
2601 SetAllowSubframes(value);
2602 }
2603 if (mAllowImages &&
2604 NS_SUCCEEDED(parentAsDocShell->GetAllowImages(&value))((bool)(__builtin_expect(!!(!NS_FAILED_impl(parentAsDocShell->
GetAllowImages(&value))), 1)))
) {
2605 SetAllowImages(value);
2606 }
2607 SetAllowMedia(parentAsDocShell->GetAllowMedia() && mAllowMedia);
2608 if (mAllowWindowControl &&
2609 NS_SUCCEEDED(parentAsDocShell->GetAllowWindowControl(&value))((bool)(__builtin_expect(!!(!NS_FAILED_impl(parentAsDocShell->
GetAllowWindowControl(&value))), 1)))
) {
2610 SetAllowWindowControl(value);
2611 }
2612 if (NS_FAILED(parentAsDocShell->GetAllowDNSPrefetch(&value))((bool)(__builtin_expect(!!(NS_FAILED_impl(parentAsDocShell->
GetAllowDNSPrefetch(&value))), 0)))
) {
2613 value = false;
2614 }
2615 SetAllowDNSPrefetch(mAllowDNSPrefetch && value);
2616
2617 // We don't need to inherit metaViewportOverride, because the viewport
2618 // is only relevant for the outermost nsDocShell, not for any iframes
2619 // like this that might be embedded within it.
2620 }
2621
2622 nsCOMPtr<nsIURIContentListener> parentURIListener(do_GetInterface(parent));
2623 if (parentURIListener) {
2624 mContentListener->SetParentContentListener(parentURIListener);
2625 }
2626
2627 return NS_OK;
2628}
2629
2630void nsDocShell::MaybeRestoreWindowName() {
2631 if (!StaticPrefs::privacy_window_name_update_enabled()) {
2632 return;
2633 }
2634
2635 // We only restore window.name for the top-level content.
2636 if (!mBrowsingContext->IsTopContent()) {
2637 return;
2638 }
2639
2640 nsAutoString name;
2641
2642 // Following implements https://html.spec.whatwg.org/#history-traversal:
2643 // Step 4.4. Check if the loading entry has a name.
2644
2645 if (mLSHE) {
2646 mLSHE->GetName(name);
2647 }
2648
2649 if (mLoadingEntry) {
2650 name = mLoadingEntry->mInfo.GetName();
2651 }
2652
2653 if (name.IsEmpty()) {
2654 return;
2655 }
2656
2657 // Step 4.4.1. Set the name to the browsing context.
2658 Unused << mBrowsingContext->SetName(name);
2659
2660 // Step 4.4.2. Clear the name of all entries that are contiguous and
2661 // same-origin with the loading entry.
2662 if (mLSHE) {
2663 nsSHistory::WalkContiguousEntries(
2664 mLSHE, [](nsISHEntry* aEntry) { aEntry->SetName(EmptyString()); });
2665 }
2666
2667 if (mLoadingEntry) {
2668 // Clear the name of the session entry in the child side. For parent side,
2669 // the clearing will be done when we commit the history to the parent.
2670 mLoadingEntry->mInfo.SetName(EmptyString());
2671 }
2672}
2673
2674void nsDocShell::StoreWindowNameToSHEntries() {
2675 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"
, 2675); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mBrowsingContext->IsTopContent()"
")"); do { *((volatile int*)__null) = 2675; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2676
2677 nsAutoString name;
2678 mBrowsingContext->GetName(name);
2679
2680 if (mOSHE) {
2681 nsSHistory::WalkContiguousEntries(
2682 mOSHE, [&](nsISHEntry* aEntry) { aEntry->SetName(name); });
2683 }
2684
2685 if (mozilla::SessionHistoryInParent()) {
2686 if (XRE_IsParentProcess()) {
2687 SessionHistoryEntry* entry =
2688 mBrowsingContext->Canonical()->GetActiveSessionHistoryEntry();
2689 if (entry) {
2690 nsSHistory::WalkContiguousEntries(
2691 entry, [&](nsISHEntry* aEntry) { aEntry->SetName(name); });
2692 }
2693 } else {
2694 // Ask parent process to store the name in entries.
2695 mozilla::Unused
2696 << ContentChild::GetSingleton()
2697 ->SendSessionHistoryEntryStoreWindowNameInContiguousEntries(
2698 mBrowsingContext, name);
2699 }
2700 }
2701}
2702
2703NS_IMETHODIMPnsresult
2704nsDocShell::GetInProcessSameTypeParent(nsIDocShellTreeItem** aParent) {
2705 if (BrowsingContext* parentBC = mBrowsingContext->GetParent()) {
2706 *aParent = do_AddRef(parentBC->GetDocShell()).take();
2707 }
2708 return NS_OK;
2709}
2710
2711NS_IMETHODIMPnsresult
2712nsDocShell::GetInProcessRootTreeItem(nsIDocShellTreeItem** aRootTreeItem) {
2713 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"
, 2713); return NS_ERROR_INVALID_POINTER; } } while (false)
;
2714
2715 RefPtr<nsDocShell> root = this;
2716 RefPtr<nsDocShell> parent = root->GetInProcessParentDocshell();
2717 while (parent) {
2718 root = parent;
2719 parent = root->GetInProcessParentDocshell();
2720 }
2721
2722 root.forget(aRootTreeItem);
2723 return NS_OK;
2724}
2725
2726NS_IMETHODIMPnsresult
2727nsDocShell::GetInProcessSameTypeRootTreeItem(
2728 nsIDocShellTreeItem** aRootTreeItem) {
2729 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"
, 2729); return NS_ERROR_INVALID_POINTER; } } while (false)
;
2730 *aRootTreeItem = static_cast<nsIDocShellTreeItem*>(this);
2731
2732 nsCOMPtr<nsIDocShellTreeItem> parent;
2733 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"
, 2734); return NS_ERROR_FAILURE; } } while (false)
2734 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"
, 2734); return NS_ERROR_FAILURE; } } while (false)
;
2735 while (parent) {
2736 *aRootTreeItem = parent;
2737 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"
, 2739); return NS_ERROR_FAILURE; } } while (false)
2738 (*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"
, 2739); return NS_ERROR_FAILURE; } } while (false)
2739 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"
, 2739); return NS_ERROR_FAILURE; } } while (false)
;
2740 }
2741 NS_ADDREF(*aRootTreeItem)(*aRootTreeItem)->AddRef();
2742 return NS_OK;
2743}
2744
2745NS_IMETHODIMPnsresult
2746nsDocShell::GetTreeOwner(nsIDocShellTreeOwner** aTreeOwner) {
2747 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"
, 2747); return NS_ERROR_INVALID_POINTER; } } while (false)
;
2748
2749 *aTreeOwner = mTreeOwner;
2750 NS_IF_ADDREF(*aTreeOwner)ns_if_addref(*aTreeOwner);
2751 return NS_OK;
2752}
2753
2754NS_IMETHODIMPnsresult
2755nsDocShell::SetTreeOwner(nsIDocShellTreeOwner* aTreeOwner) {
2756 if (mIsBeingDestroyed && aTreeOwner) {
2757 return NS_ERROR_FAILURE;
2758 }
2759
2760 // Don't automatically set the progress based on the tree owner for frames
2761 if (!IsSubframe()) {
2762 nsCOMPtr<nsIWebProgress> webProgress =
2763 do_QueryInterface(GetAsSupports(this));
2764
2765 if (webProgress) {
2766 nsCOMPtr<nsIWebProgressListener> oldListener =
2767 do_QueryInterface(mTreeOwner);
2768 nsCOMPtr<nsIWebProgressListener> newListener =
2769 do_QueryInterface(aTreeOwner);
2770
2771 if (oldListener) {
2772 webProgress->RemoveProgressListener(oldListener);
2773 }
2774
2775 if (newListener) {
2776 webProgress->AddProgressListener(newListener,
2777 nsIWebProgress::NOTIFY_ALL);
2778 }
2779 }
2780 }
2781
2782 mTreeOwner = aTreeOwner; // Weak reference per API
2783
2784 for (auto* childDocLoader : mChildList.ForwardRange()) {
2785 nsCOMPtr<nsIDocShellTreeItem> child = do_QueryObject(childDocLoader);
2786 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"
, 2786); return NS_ERROR_FAILURE; } } while (false)
;
2787
2788 if (child->ItemType() == mItemType) {
2789 child->SetTreeOwner(aTreeOwner);
2790 }
2791 }
2792
2793 // If we're in the content process and have had a TreeOwner set on us, extract
2794 // our BrowserChild actor. If we've already had our BrowserChild set, assert
2795 // that it hasn't changed.
2796 if (mTreeOwner && XRE_IsContentProcess()) {
2797 nsCOMPtr<nsIBrowserChild> newBrowserChild = do_GetInterface(mTreeOwner);
2798 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"
, 2799); AnnotateMozCrashReason("MOZ_ASSERT" "(" "newBrowserChild"
") (" "No BrowserChild actor for tree owner in Content!" ")"
); do { *((volatile int*)__null) = 2799; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2799 "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"
, 2799); AnnotateMozCrashReason("MOZ_ASSERT" "(" "newBrowserChild"
") (" "No BrowserChild actor for tree owner in Content!" ")"
); do { *((volatile int*)__null) = 2799; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2800
2801 if (mBrowserChild) {
2802 nsCOMPtr<nsIBrowserChild> oldBrowserChild =
2803 do_QueryReferent(mBrowserChild);
2804 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"
, 2806); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "oldBrowserChild == newBrowserChild"
") (" "Cannot change BrowserChild during nsDocShell lifetime!"
")"); do { *((volatile int*)__null) = 2806; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2805 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"
, 2806); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "oldBrowserChild == newBrowserChild"
") (" "Cannot change BrowserChild during nsDocShell lifetime!"
")"); do { *((volatile int*)__null) = 2806; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2806 "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"
, 2806); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "oldBrowserChild == newBrowserChild"
") (" "Cannot change BrowserChild during nsDocShell lifetime!"
")"); do { *((volatile int*)__null) = 2806; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2807 } else {
2808 mBrowserChild = do_GetWeakReference(newBrowserChild);
2809 }
2810 }
2811
2812 return NS_OK;
2813}
2814
2815NS_IMETHODIMPnsresult
2816nsDocShell::GetHistoryID(nsID& aID) {
2817 aID = mBrowsingContext->GetHistoryID();
2818 return NS_OK;
2819}
2820
2821const nsID& nsDocShell::HistoryID() { return mBrowsingContext->GetHistoryID(); }
2822
2823NS_IMETHODIMPnsresult
2824nsDocShell::GetIsInUnload(bool* aIsInUnload) {
2825 *aIsInUnload = mFiredUnloadEvent;
2826 return NS_OK;
2827}
2828
2829NS_IMETHODIMPnsresult
2830nsDocShell::GetInProcessChildCount(int32_t* aChildCount) {
2831 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"
, 2831); return NS_ERROR_INVALID_POINTER; } } while (false)
;
2832 *aChildCount = mChildList.Length();
2833 return NS_OK;
2834}
2835
2836NS_IMETHODIMPnsresult
2837nsDocShell::AddChild(nsIDocShellTreeItem* aChild) {
2838 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"
, 2838); return NS_ERROR_INVALID_POINTER; } } while (false)
;
2839
2840 RefPtr<nsDocLoader> childAsDocLoader = GetAsDocLoader(aChild);
2841 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"
, 2841); return NS_ERROR_UNEXPECTED; } } while (false)
;
2842
2843 // Make sure we're not creating a loop in the docshell tree
2844 nsDocLoader* ancestor = this;
2845 do {
2846 if (childAsDocLoader == ancestor) {
2847 return NS_ERROR_ILLEGAL_VALUE;
2848 }
2849 ancestor = ancestor->GetParent();
2850 } while (ancestor);
2851
2852 // Make sure to remove the child from its current parent.
2853 nsDocLoader* childsParent = childAsDocLoader->GetParent();
2854 if (childsParent) {
2855 nsresult rv = childsParent->RemoveChildLoader(childAsDocLoader);
2856 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"
, 2856); return rv; } } while (false)
;
2857 }
2858
2859 // Make sure to clear the treeowner in case this child is a different type
2860 // from us.
2861 aChild->SetTreeOwner(nullptr);
2862
2863 nsresult res = AddChildLoader(childAsDocLoader);
2864 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"
, 2864); return res; } } while (false)
;
2865 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"
, 2866); MOZ_PretendNoReturn(); } } while (0)
2866 "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"
, 2866); MOZ_PretendNoReturn(); } } while (0)
;
2867
2868 /* Set the child's global history if the parent has one */
2869 if (mBrowsingContext->GetUseGlobalHistory()) {
2870 // childDocShell->SetUseGlobalHistory(true);
2871 // this should be set through BC inherit
2872 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"
, 2872); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aChild->GetBrowsingContext()->GetUseGlobalHistory()"
")"); do { *((volatile int*)__null) = 2872; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2873 }
2874
2875 if (aChild->ItemType() != mItemType) {
2876 return NS_OK;
2877 }
2878
2879 aChild->SetTreeOwner(mTreeOwner);
2880
2881 nsCOMPtr<nsIDocShell> childAsDocShell(do_QueryInterface(aChild));
2882 if (!childAsDocShell) {
2883 return NS_OK;
2884 }
2885
2886 // charset, style-disabling, and zoom will be inherited in SetupNewViewer()
2887
2888 // Now take this document's charset and set the child's parentCharset field
2889 // to it. We'll later use that field, in the loading process, for the
2890 // charset choosing algorithm.
2891 // If we fail, at any point, we just return NS_OK.
2892 // This code has some performance impact. But this will be reduced when
2893 // the current charset will finally be stored as an Atom, avoiding the
2894 // alias resolution extra look-up.
2895
2896 // we are NOT going to propagate the charset is this Chrome's docshell
2897 if (mItemType == nsIDocShellTreeItem::typeChrome) {
2898 return NS_OK;
2899 }
2900
2901 // get the parent's current charset
2902 if (!mDocumentViewer) {
2903 return NS_OK;
2904 }
2905 Document* doc = mDocumentViewer->GetDocument();
2906 if (!doc) {
2907 return NS_OK;
2908 }
2909
2910 const Encoding* parentCS = doc->GetDocumentCharacterSet();
2911 int32_t charsetSource = doc->GetDocumentCharacterSetSource();
2912 // set the child's parentCharset
2913 childAsDocShell->SetParentCharset(parentCS, charsetSource,
2914 doc->NodePrincipal());
2915
2916 // printf("### 1 >>> Adding child. Parent CS = %s. ItemType = %d.\n",
2917 // NS_LossyConvertUTF16toASCII(parentCS).get(), mItemType);
2918
2919 return NS_OK;
2920}
2921
2922NS_IMETHODIMPnsresult
2923nsDocShell::RemoveChild(nsIDocShellTreeItem* aChild) {
2924 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"
, 2924); return NS_ERROR_INVALID_POINTER; } } while (false)
;
2925
2926 RefPtr<nsDocLoader> childAsDocLoader = GetAsDocLoader(aChild);
2927 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"
, 2927); return NS_ERROR_UNEXPECTED; } } while (false)
;
2928
2929 nsresult rv = RemoveChildLoader(childAsDocLoader);
2930 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"
, 2930); return rv; } } while (false)
;
2931
2932 aChild->SetTreeOwner(nullptr);
2933
2934 return nsDocLoader::AddDocLoaderAsChildOfRoot(childAsDocLoader);
2935}
2936
2937NS_IMETHODIMPnsresult
2938nsDocShell::GetInProcessChildAt(int32_t aIndex, nsIDocShellTreeItem** aChild) {
2939 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"
, 2939); return NS_ERROR_INVALID_POINTER; } } while (false)
;
2940
2941 RefPtr<nsDocShell> child = GetInProcessChildAt(aIndex);
2942 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"
, 2942); return NS_ERROR_UNEXPECTED; } } while (false)
;
2943
2944 child.forget(aChild);
2945
2946 return NS_OK;
2947}
2948
2949nsDocShell* nsDocShell::GetInProcessChildAt(int32_t aIndex) {
2950#ifdef DEBUG1
2951 if (aIndex < 0) {
2952 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"
, 2952)
;
2953 } else if (static_cast<uint32_t>(aIndex) >= mChildList.Length()) {
2954 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"
, 2954)
;
2955 }
2956#endif
2957
2958 nsIDocumentLoader* child = ChildAt(aIndex);
2959
2960 // child may be nullptr here.
2961 return static_cast<nsDocShell*>(child);
2962}
2963
2964nsresult nsDocShell::AddChildSHEntry(nsISHEntry* aCloneRef,
2965 nsISHEntry* aNewEntry,
2966 int32_t aChildOffset, uint32_t aLoadType,
2967 bool aCloneChildren) {
2968 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"
, 2968); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mozilla::SessionHistoryInParent()"
")"); do { *((volatile int*)__null) = 2968; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2969 nsresult rv = NS_OK;
2970
2971 if (mLSHE && aLoadType != LOAD_PUSHSTATE) {
2972 /* You get here if you are currently building a
2973 * hierarchy ie.,you just visited a frameset page
2974 */
2975 if (NS_FAILED(mLSHE->ReplaceChild(aNewEntry))((bool)(__builtin_expect(!!(NS_FAILED_impl(mLSHE->ReplaceChild
(aNewEntry))), 0)))
) {
2976 rv = mLSHE->AddChild(aNewEntry, aChildOffset);
2977 }
2978 } else if (!aCloneRef) {
2979 /* This is an initial load in some subframe. Just append it if we can */
2980 if (mOSHE) {
2981 rv = mOSHE->AddChild(aNewEntry, aChildOffset, UseRemoteSubframes());
2982 }
2983 } else {
2984 RefPtr<ChildSHistory> shistory = GetRootSessionHistory();
2985 if (shistory) {
2986 rv = shistory->LegacySHistory()->AddChildSHEntryHelper(
2987 aCloneRef, aNewEntry, mBrowsingContext->Top(), aCloneChildren);
2988 }
2989 }
2990 return rv;
2991}
2992
2993nsresult nsDocShell::AddChildSHEntryToParent(nsISHEntry* aNewEntry,
2994 int32_t aChildOffset,
2995 bool aCloneChildren) {
2996 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"
, 2996); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mozilla::SessionHistoryInParent()"
")"); do { *((volatile int*)__null) = 2996; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2997 /* You will get here when you are in a subframe and
2998 * a new url has been loaded on you.
2999 * The mOSHE in this subframe will be the previous url's
3000 * mOSHE. This mOSHE will be used as the identification
3001 * for this subframe in the CloneAndReplace function.
3002 */
3003
3004 // In this case, we will end up calling AddEntry, which increases the
3005 // current index by 1
3006 RefPtr<ChildSHistory> rootSH = GetRootSessionHistory();
3007 if (rootSH) {
3008 mPreviousEntryIndex = rootSH->Index();
3009 }
3010
3011 nsresult rv;
3012 // XXX(farre): this is not Fission safe, expect errors. This never
3013 // get's executed once session history in the parent is enabled.
3014 nsCOMPtr<nsIDocShell> parent = do_QueryInterface(GetAsSupports(mParent), &rv);
3015 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"
, 3018); } } while (false)
3016 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"
, 3018); } } while (false)
3017 "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"
, 3018); } } while (false)
3018 "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"
, 3018); } } while (false)
;
3019 if (parent) {
3020 rv = nsDocShell::Cast(parent)->AddChildSHEntry(
3021 mOSHE, aNewEntry, aChildOffset, mLoadType, aCloneChildren);
3022 }
3023
3024 if (rootSH) {
3025 mLoadedEntryIndex = rootSH->Index();
3026
3027 if (MOZ_UNLIKELY(MOZ_LOG_TEST(gPageCacheLog, LogLevel::Verbose))(__builtin_expect(!!((__builtin_expect(!!(mozilla::detail::log_test
(gPageCacheLog, LogLevel::Verbose)), 0))), 0))
) {
3028 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)
3029 ("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)
3030 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)
;
3031 }
3032 }
3033
3034 return rv;
3035}
3036
3037NS_IMETHODIMPnsresult
3038nsDocShell::GetCurrentSHEntry(nsISHEntry** aEntry, bool* aOSHE) {
3039 *aOSHE = false;
3040 *aEntry = nullptr;
3041 if (mLSHE) {
3042 NS_ADDREF(*aEntry = mLSHE)(*aEntry = mLSHE)->AddRef();
3043 } else if (mOSHE) {
3044 NS_ADDREF(*aEntry = mOSHE)(*aEntry = mOSHE)->AddRef();
3045 *aOSHE = true;
3046 }
3047 return NS_OK;
3048}
3049
3050NS_IMETHODIMPnsresult nsDocShell::SynchronizeLayoutHistoryState() {
3051 if (mActiveEntry && mActiveEntry->GetLayoutHistoryState() &&
3052 mBrowsingContext) {
3053 if (XRE_IsContentProcess()) {
3054 dom::ContentChild* contentChild = dom::ContentChild::GetSingleton();
3055 if (contentChild) {
3056 contentChild->SendSynchronizeLayoutHistoryState(
3057 mBrowsingContext, mActiveEntry->GetLayoutHistoryState());
3058 }
3059 } else {
3060 SessionHistoryEntry* entry =
3061 mBrowsingContext->Canonical()->GetActiveSessionHistoryEntry();
3062 if (entry) {
3063 entry->SetLayoutHistoryState(mActiveEntry->GetLayoutHistoryState());
3064 }
3065 }
3066 if (mLoadingEntry &&
3067 mLoadingEntry->mInfo.SharedId() == mActiveEntry->SharedId()) {
3068 mLoadingEntry->mInfo.SetLayoutHistoryState(
3069 mActiveEntry->GetLayoutHistoryState());
3070 }
3071 }
3072
3073 return NS_OK;
3074}
3075
3076void nsDocShell::SetLoadGroupDefaultLoadFlags(nsLoadFlags aLoadFlags) {
3077 if (mLoadGroup) {
3078 mLoadGroup->SetDefaultLoadFlags(aLoadFlags);
3079 } else {
3080 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"
, 3082)
3081 "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"
, 3082)
3082 "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"
, 3082)
;
3083 }
3084}
3085
3086nsIScriptGlobalObject* nsDocShell::GetScriptGlobalObject() {
3087 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"
, 3087); return nullptr; } } while (false)
;
3088 return mScriptGlobal;
3089}
3090
3091Document* nsDocShell::GetDocument() {
3092 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"
, 3092); return nullptr; } } while (false)
;
3093 return mDocumentViewer->GetDocument();
3094}
3095
3096Document* nsDocShell::GetExtantDocument() {
3097 return mDocumentViewer ? mDocumentViewer->GetDocument() : nullptr;
3098}
3099
3100nsPIDOMWindowOuter* nsDocShell::GetWindow() {
3101 if (NS_FAILED(EnsureScriptEnvironment())((bool)(__builtin_expect(!!(NS_FAILED_impl(EnsureScriptEnvironment
())), 0)))
) {
3102 return nullptr;
3103 }
3104 return mScriptGlobal;
3105}
3106
3107NS_IMETHODIMPnsresult
3108nsDocShell::GetDomWindow(mozIDOMWindowProxy** aWindow) {
3109 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"
, 3109); return NS_ERROR_INVALID_POINTER; } } while (false)
;
3110
3111 nsresult rv = EnsureScriptEnvironment();
3112 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"
, 3112); return rv; } } while (false)
;
3113
3114 RefPtr<nsGlobalWindowOuter> window = mScriptGlobal;
3115 window.forget(aWindow);
3116 return NS_OK;
3117}
3118
3119NS_IMETHODIMPnsresult
3120nsDocShell::GetMessageManager(ContentFrameMessageManager** aMessageManager) {
3121 RefPtr<ContentFrameMessageManager> mm;
3122 if (RefPtr<BrowserChild> browserChild = BrowserChild::GetFrom(this)) {
3123 mm = browserChild->GetMessageManager();
3124 } else if (nsPIDOMWindowOuter* win = GetWindow()) {
3125 mm = win->GetMessageManager();
3126 }
3127 mm.forget(aMessageManager);
3128 return NS_OK;
3129}
3130
3131NS_IMETHODIMPnsresult
3132nsDocShell::GetIsNavigating(bool* aOut) {
3133 *aOut = mIsNavigating;
3134 return NS_OK;
3135}
3136
3137void nsDocShell::ClearFrameHistory(nsISHEntry* aEntry) {
3138 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"
, 3138); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mozilla::SessionHistoryInParent()"
")"); do { *((volatile int*)__null) = 3138; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3139 RefPtr<ChildSHistory> rootSH = GetRootSessionHistory();
3140 if (!rootSH || !aEntry) {
3141 return;
3142 }
3143
3144 rootSH->LegacySHistory()->RemoveFrameEntries(aEntry);
3145}
3146
3147//-------------------------------------
3148//-- Helper Method for Print discovery
3149//-------------------------------------
3150bool nsDocShell::NavigationBlockedByPrinting(bool aDisplayErrorDialog) {
3151 if (!mBrowsingContext->Top()->GetIsPrinting()) {
3152 return false;
3153 }
3154 if (aDisplayErrorDialog) {
3155 DisplayLoadError(NS_ERROR_DOCUMENT_IS_PRINTMODE, nullptr, nullptr, nullptr);
3156 }
3157 return true;
3158}
3159
3160bool nsDocShell::IsNavigationAllowed(bool aDisplayPrintErrorDialog,
3161 bool aCheckIfUnloadFired) {
3162 bool isAllowed = !NavigationBlockedByPrinting(aDisplayPrintErrorDialog) &&
3163 (!aCheckIfUnloadFired || !mFiredUnloadEvent);
3164 if (!isAllowed) {
3165 return false;
3166 }
3167 if (!mDocumentViewer) {
3168 return true;
3169 }
3170 bool firingBeforeUnload;
3171 mDocumentViewer->GetBeforeUnloadFiring(&firingBeforeUnload);
3172 return !firingBeforeUnload;
3173}
3174
3175//*****************************************************************************
3176// nsDocShell::nsIWebNavigation
3177//*****************************************************************************
3178
3179NS_IMETHODIMPnsresult
3180nsDocShell::GetCanGoBack(bool* aCanGoBack) {
3181 *aCanGoBack = false;
3182 if (!IsNavigationAllowed(false)) {
3183 return NS_OK; // JS may not handle returning of an error code
3184 }
3185 RefPtr<ChildSHistory> rootSH = GetRootSessionHistory();
3186 if (rootSH) {
3187 *aCanGoBack = rootSH->CanGo(-1);
3188 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)
3189 ("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)
;
3190
3191 return NS_OK;
3192 }
3193 return NS_ERROR_FAILURE;
3194}
3195
3196NS_IMETHODIMPnsresult
3197nsDocShell::GetCanGoForward(bool* aCanGoForward) {
3198 *aCanGoForward = false;
3199 if (!IsNavigationAllowed(false)) {
3200 return NS_OK; // JS may not handle returning of an error code
3201 }
3202 RefPtr<ChildSHistory> rootSH = GetRootSessionHistory();
3203 if (rootSH) {
3204 *aCanGoForward = rootSH->CanGo(1);
3205 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)
3206 ("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)
;
3207 return NS_OK;
3208 }
3209 return NS_ERROR_FAILURE;
3210}
3211
3212NS_IMETHODIMPnsresult
3213nsDocShell::GoBack(bool aRequireUserInteraction, bool aUserActivation) {
3214 if (!IsNavigationAllowed()) {
3215 return NS_OK; // JS may not handle returning of an error code
3216 }
3217
3218 auto cleanupIsNavigating = MakeScopeExit([&]() { mIsNavigating = false; });
3219 mIsNavigating = true;
3220
3221 RefPtr<ChildSHistory> rootSH = GetRootSessionHistory();
3222 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"
, 3222); return NS_ERROR_FAILURE; } } while (false)
;
3223 ErrorResult rv;
3224 rootSH->Go(-1, aRequireUserInteraction, aUserActivation, rv);
3225 return rv.StealNSResult();
3226}
3227
3228NS_IMETHODIMPnsresult
3229nsDocShell::GoForward(bool aRequireUserInteraction, bool aUserActivation) {
3230 if (!IsNavigationAllowed()) {
3231 return NS_OK; // JS may not handle returning of an error code
3232 }
3233
3234 auto cleanupIsNavigating = MakeScopeExit([&]() { mIsNavigating = false; });
3235 mIsNavigating = true;
3236
3237 RefPtr<ChildSHistory> rootSH = GetRootSessionHistory();
3238 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"
, 3238); return NS_ERROR_FAILURE; } } while (false)
;
3239 ErrorResult rv;
3240 rootSH->Go(1, aRequireUserInteraction, aUserActivation, rv);
3241 return rv.StealNSResult();
3242}
3243
3244// XXX(nika): We may want to stop exposing this API in the child process? Going
3245// to a specific index from multiple different processes could definitely race.
3246NS_IMETHODIMPnsresult
3247nsDocShell::GotoIndex(int32_t aIndex, bool aUserActivation) {
3248 if (!IsNavigationAllowed()) {
3249 return NS_OK; // JS may not handle returning of an error code
3250 }
3251
3252 auto cleanupIsNavigating = MakeScopeExit([&]() { mIsNavigating = false; });
3253 mIsNavigating = true;
3254
3255 RefPtr<ChildSHistory> rootSH = GetRootSessionHistory();
3256 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"
, 3256); return NS_ERROR_FAILURE; } } while (false)
;
3257
3258 ErrorResult rv;
3259 rootSH->GotoIndex(aIndex, aIndex - rootSH->Index(), false, aUserActivation,
3260 rv);
3261 return rv.StealNSResult();
3262}
3263
3264nsresult nsDocShell::LoadURI(nsIURI* aURI,
3265 const LoadURIOptions& aLoadURIOptions) {
3266 if (!IsNavigationAllowed()) {
3267 return NS_OK; // JS may not handle returning of an error code
3268 }
3269 RefPtr<nsDocShellLoadState> loadState;
3270 nsresult rv = nsDocShellLoadState::CreateFromLoadURIOptions(
3271 mBrowsingContext, aURI, aLoadURIOptions, getter_AddRefs(loadState));
3272 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"
, 3272); AnnotateMozCrashReason("MOZ_ASSERT" "(" "rv != NS_ERROR_MALFORMED_URI"
")"); do { *((volatile int*)__null) = 3272; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3273 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) || !loadState) {
3274 return NS_ERROR_FAILURE;
3275 }
3276
3277 return LoadURI(loadState, true);
3278}
3279
3280NS_IMETHODIMPnsresult
3281nsDocShell::LoadURIFromScript(nsIURI* aURI,
3282 JS::Handle<JS::Value> aLoadURIOptions,
3283 JSContext* aCx) {
3284 // generate dictionary for aLoadURIOptions and forward call
3285 LoadURIOptions loadURIOptions;
3286 if (!loadURIOptions.Init(aCx, aLoadURIOptions)) {
3287 return NS_ERROR_INVALID_ARG;
3288 }
3289 return LoadURI(aURI, loadURIOptions);
3290}
3291
3292nsresult nsDocShell::FixupAndLoadURIString(
3293 const nsAString& aURIString, const LoadURIOptions& aLoadURIOptions) {
3294 if (!IsNavigationAllowed()) {
3295 return NS_OK; // JS may not handle returning of an error code
3296 }
3297
3298 RefPtr<nsDocShellLoadState> loadState;
3299 nsresult rv = nsDocShellLoadState::CreateFromLoadURIOptions(
3300 mBrowsingContext, aURIString, aLoadURIOptions, getter_AddRefs(loadState));
3301
3302 uint32_t loadFlags = aLoadURIOptions.mLoadFlags;
3303 if (NS_ERROR_MALFORMED_URI == rv) {
3304 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)
3305 ("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)
3306 "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)
3307 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)
;
3308
3309 // We need to store a session history entry. We don't have a valid URI, so
3310 // we use about:blank instead.
3311 nsCOMPtr<nsIURI> uri;
3312 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"
, 3312); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "false"
") (" "NS_SUCCEEDED(NS_NewURI(getter_AddRefs(uri), \"about:blank\"_ns))"
")"); do { *((volatile int*)__null) = 3312; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
3313 nsCOMPtr<nsIPrincipal> triggeringPrincipal;
3314 if (aLoadURIOptions.mTriggeringPrincipal) {
3315 triggeringPrincipal = aLoadURIOptions.mTriggeringPrincipal;
3316 } else {
3317 triggeringPrincipal = nsContentUtils::GetSystemPrincipal();
3318 }
3319 if (mozilla::SessionHistoryInParent()) {
3320 mActiveEntry = MakeUnique<SessionHistoryInfo>(
3321 uri, triggeringPrincipal, nullptr, nullptr, nullptr,
3322 nsLiteralCString("text/html"));
3323 mBrowsingContext->SetActiveSessionHistoryEntry(
3324 Nothing(), mActiveEntry.get(), MAKE_LOAD_TYPE(LOAD_NORMAL, loadFlags)((LOAD_NORMAL) | ((loadFlags) << 16)),
3325 /* aUpdatedCacheKey = */ 0);
3326 }
3327 if (DisplayLoadError(rv, nullptr, PromiseFlatStringTPromiseFlatString<char16_t>(aURIString).get(),
3328 nullptr) &&
3329 (loadFlags & LOAD_FLAGS_ERROR_LOAD_CHANGES_RV) != 0) {
3330 return NS_ERROR_LOAD_SHOWED_ERRORPAGE;
3331 }
3332 }
3333
3334 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) || !loadState) {
3335 return NS_ERROR_FAILURE;
3336 }
3337
3338 return LoadURI(loadState, true);
3339}
3340
3341NS_IMETHODIMPnsresult
3342nsDocShell::FixupAndLoadURIStringFromScript(
3343 const nsAString& aURIString, JS::Handle<JS::Value> aLoadURIOptions,
3344 JSContext* aCx) {
3345 // generate dictionary for aLoadURIOptions and forward call
3346 LoadURIOptions loadURIOptions;
3347 if (!loadURIOptions.Init(aCx, aLoadURIOptions)) {
3348 return NS_ERROR_INVALID_ARG;
3349 }
3350 return FixupAndLoadURIString(aURIString, loadURIOptions);
3351}
3352
3353void nsDocShell::UnblockEmbedderLoadEventForFailure(bool aFireFrameErrorEvent) {
3354 // If we're not in a content frame, or are at a BrowsingContext tree boundary,
3355 // such as the content-chrome boundary, don't fire the error event.
3356 if (mBrowsingContext->IsTopContent() || mBrowsingContext->IsChrome()) {
3357 return;
3358 }
3359
3360 // If embedder is same-process, then unblocking the load event is already
3361 // handled by nsDocLoader. Fire the error event on our embedder element if
3362 // requested.
3363 //
3364 // XXX: Bug 1440212 is looking into potentially changing this behaviour to act
3365 // more like the remote case when in-process.
3366 RefPtr<Element> element = mBrowsingContext->GetEmbedderElement();
3367 if (element) {
3368 if (aFireFrameErrorEvent) {
3369 if (RefPtr<nsFrameLoaderOwner> flo = do_QueryObject(element)) {
3370 if (RefPtr<nsFrameLoader> fl = flo->GetFrameLoader()) {
3371 fl->FireErrorEvent();
3372 }
3373 }
3374 }
3375 return;
3376 }
3377
3378 // If we have a cross-process parent document, we must notify it that we no
3379 // longer block its load event. This is necessary for OOP sub-documents
3380 // because error documents do not result in a call to
3381 // SendMaybeFireEmbedderLoadEvents via any of the normal call paths.
3382 // (Obviously, we must do this before any of the returns below.)
3383 RefPtr<BrowserChild> browserChild = BrowserChild::GetFrom(this);
3384 if (browserChild) {
3385 mozilla::Unused << browserChild->SendMaybeFireEmbedderLoadEvents(
3386 aFireFrameErrorEvent ? EmbedderElementEventType::ErrorEvent
3387 : EmbedderElementEventType::NoEvent);
3388 }
3389}
3390
3391NS_IMETHODIMPnsresult
3392nsDocShell::DisplayLoadError(nsresult aError, nsIURI* aURI,
3393 const char16_t* aURL, nsIChannel* aFailedChannel,
3394 bool* aDisplayedErrorPage) {
3395 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
)
3396 ("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
)
3397 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
)
;
3398
3399 *aDisplayedErrorPage = false;
3400 // Get prompt and string bundle services
3401 nsCOMPtr<nsIPrompt> prompter;
3402 nsCOMPtr<nsIStringBundle> stringBundle;
3403 GetPromptAndStringBundle(getter_AddRefs(prompter),
3404 getter_AddRefs(stringBundle));
3405
3406 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"
, 3406); return NS_ERROR_FAILURE; } } while (false)
;
3407 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"
, 3407); return NS_ERROR_FAILURE; } } while (false)
;
3408
3409 const char* error = nullptr;
3410 // The key used to select the appropriate error message from the properties
3411 // file.
3412 const char* errorDescriptionID = nullptr;
3413 AutoTArray<nsString, 3> formatStrs;
3414 bool addHostPort = false;
3415 bool isBadStsCertError = false;
3416 nsresult rv = NS_OK;
3417 nsAutoString messageStr;
3418 nsAutoCString cssClass;
3419 nsAutoCString errorPage;
3420
3421 errorPage.AssignLiteral("neterror");
3422
3423 // Turn the error code into a human readable error message.
3424 if (NS_ERROR_UNKNOWN_PROTOCOL == aError) {
3425 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"
, 3425); return NS_ERROR_INVALID_POINTER; } } while (false)
;
3426
3427 // Extract the schemes into a comma delimited list.
3428 nsAutoCString scheme;
3429 aURI->GetScheme(scheme);
3430 CopyASCIItoUTF16(scheme, *formatStrs.AppendElement());
3431 nsCOMPtr<nsINestedURI> nestedURI = do_QueryInterface(aURI);
3432 while (nestedURI) {
3433 nsCOMPtr<nsIURI> tempURI;
3434 nsresult rv2;
3435 rv2 = nestedURI->GetInnerURI(getter_AddRefs(tempURI));
3436 if (NS_SUCCEEDED(rv2)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv2)), 1))) && tempURI) {
3437 tempURI->GetScheme(scheme);
3438 formatStrs[0].AppendLiteral(", ");
3439 AppendASCIItoUTF16(scheme, formatStrs[0]);
3440 }
3441 nestedURI = do_QueryInterface(tempURI);
3442 }
3443 error = "unknownProtocolFound";
3444 } else if (NS_ERROR_FILE_NOT_FOUND == aError) {
3445 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"
, 3445); return NS_ERROR_INVALID_POINTER; } } while (false)
;
3446 error = "fileNotFound";
3447 } else if (NS_ERROR_FILE_ACCESS_DENIED == aError) {
3448 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"
, 3448); return NS_ERROR_INVALID_POINTER; } } while (false)
;
3449 error = "fileAccessDenied";
3450 } else if (NS_ERROR_UNKNOWN_HOST == aError) {
3451 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"
, 3451); return NS_ERROR_INVALID_POINTER; } } while (false)
;
3452 // Get the host
3453 nsAutoCString host;
3454 nsCOMPtr<nsIURI> innermostURI = NS_GetInnermostURI(aURI);
3455 innermostURI->GetHost(host);
3456 CopyUTF8toUTF16(host, *formatStrs.AppendElement());
3457 errorDescriptionID = "dnsNotFound2";
3458 error = "dnsNotFound";
3459 } else if (NS_ERROR_CONNECTION_REFUSED == aError ||
3460 NS_ERROR_PROXY_BAD_GATEWAY == aError) {
3461 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"
, 3461); return NS_ERROR_INVALID_POINTER; } } while (false)
;
3462 addHostPort = true;
3463 error = "connectionFailure";
3464 } else if (NS_ERROR_NET_INTERRUPT == aError) {
3465 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"
, 3465); return NS_ERROR_INVALID_POINTER; } } while (false)
;
3466 addHostPort = true;
3467 error = "netInterrupt";
3468 } else if (NS_ERROR_NET_TIMEOUT == aError ||
3469 NS_ERROR_PROXY_GATEWAY_TIMEOUT == aError ||
3470 NS_ERROR_NET_TIMEOUT_EXTERNAL == aError) {
3471 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"
, 3471); return NS_ERROR_INVALID_POINTER; } } while (false)
;
3472 // Get the host
3473 nsAutoCString host;
3474 aURI->GetHost(host);
3475 CopyUTF8toUTF16(host, *formatStrs.AppendElement());
3476 error = "netTimeout";
3477 } else if (NS_ERROR_CSP_FRAME_ANCESTOR_VIOLATION == aError ||
3478 NS_ERROR_CSP_FORM_ACTION_VIOLATION == aError ||
3479 NS_ERROR_CSP_NAVIGATE_TO_VIOLATION == aError) {
3480 // CSP error
3481 cssClass.AssignLiteral("neterror");
3482 error = "cspBlocked";
3483 } else if (NS_ERROR_XFO_VIOLATION == aError) {
3484 // XFO error
3485 cssClass.AssignLiteral("neterror");
3486 error = "xfoBlocked";
3487 } else if (NS_ERROR_GET_MODULE(aError) == NS_ERROR_MODULE_SECURITY21) {
3488 nsCOMPtr<nsINSSErrorsService> nsserr =
3489 do_GetService(NS_NSS_ERRORS_SERVICE_CONTRACTID"@mozilla.org/nss_errors_service;1");
3490
3491 uint32_t errorClass;
3492 if (!nsserr || NS_FAILED(nsserr->GetErrorClass(aError, &errorClass))((bool)(__builtin_expect(!!(NS_FAILED_impl(nsserr->GetErrorClass
(aError, &errorClass))), 0)))
) {
3493 errorClass = nsINSSErrorsService::ERROR_CLASS_SSL_PROTOCOL;
3494 }
3495
3496 nsCOMPtr<nsITransportSecurityInfo> tsi;
3497 if (aFailedChannel) {
3498 aFailedChannel->GetSecurityInfo(getter_AddRefs(tsi));
3499 }
3500 if (tsi) {
3501 uint32_t securityState;
3502 tsi->GetSecurityState(&securityState);
3503 if (securityState & nsIWebProgressListener::STATE_USES_SSL_3) {
3504 error = "sslv3Used";
Value stored to 'error' is never read
3505 addHostPort = true;
3506 } else if (securityState &
3507 nsIWebProgressListener::STATE_USES_WEAK_CRYPTO) {
3508 error = "weakCryptoUsed";
3509 addHostPort = true;
3510 }
3511 } else {
3512 // No channel, let's obtain the generic error message
3513 if (nsserr) {
3514 nsserr->GetErrorMessage(aError, messageStr);
3515 }
3516 }
3517 // We don't have a message string here anymore but DisplayLoadError
3518 // requires a non-empty messageStr.
3519 messageStr.Truncate();
3520 messageStr.AssignLiteral(u" ");
3521 if (errorClass == nsINSSErrorsService::ERROR_CLASS_BAD_CERT) {
3522 error = "nssBadCert";
3523
3524 // If this is an HTTP Strict Transport Security host or a pinned host
3525 // and the certificate is bad, don't allow overrides (RFC 6797 section
3526 // 12.1).
3527 bool isStsHost = false;
3528 bool isPinnedHost = false;
3529 OriginAttributes attrsForHSTS;
3530 if (aFailedChannel) {
3531 StoragePrincipalHelper::GetOriginAttributesForHSTS(aFailedChannel,
3532 attrsForHSTS);
3533 } else {
3534 attrsForHSTS = GetOriginAttributes();
3535 }
3536
3537 if (XRE_IsParentProcess()) {
3538 nsCOMPtr<nsISiteSecurityService> sss =
3539 do_GetService(NS_SSSERVICE_CONTRACTID"@mozilla.org/ssservice;1", &rv);
3540 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"
, 3540); return rv; } } while (false)
;
3541 rv = sss->IsSecureURI(aURI, attrsForHSTS, &isStsHost);
3542 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"
, 3542); return rv; } } while (false)
;
3543 } else {
3544 mozilla::dom::ContentChild* cc =
3545 mozilla::dom::ContentChild::GetSingleton();
3546 cc->SendIsSecureURI(aURI, attrsForHSTS, &isStsHost);
3547 }
3548 nsCOMPtr<nsIPublicKeyPinningService> pkps =
3549 do_GetService(NS_PKPSERVICE_CONTRACTID"@mozilla.org/security/publickeypinningservice;1", &rv);
3550 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"
, 3550); return rv; } } while (false)
;
3551 rv = pkps->HostHasPins(aURI, &isPinnedHost);
3552
3553 if (Preferences::GetBool("browser.xul.error_pages.expert_bad_cert",
3554 false)) {
3555 cssClass.AssignLiteral("expertBadCert");
3556 }
3557
3558 // HSTS/pinning takes precedence over the expert bad cert pref. We
3559 // never want to show the "Add Exception" button for these sites.
3560 // In the future we should differentiate between an HSTS host and a
3561 // pinned host and display a more informative message to the user.
3562 if (isStsHost || isPinnedHost) {
3563 isBadStsCertError = true;
3564 cssClass.AssignLiteral("badStsCert");
3565 }
3566
3567 errorPage.Assign("certerror");
3568 } else {
3569 error = "nssFailure2";
3570 }
3571 } else if (NS_ERROR_PHISHING_URI == aError ||
3572 NS_ERROR_MALWARE_URI == aError ||
3573 NS_ERROR_UNWANTED_URI == aError ||
3574 NS_ERROR_HARMFUL_URI == aError) {
3575 nsAutoCString host;
3576 aURI->GetHost(host);
3577 CopyUTF8toUTF16(host, *formatStrs.AppendElement());
3578
3579 // Malware and phishing detectors may want to use an alternate error
3580 // page, but if the pref's not set, we'll fall back on the standard page
3581 nsAutoCString alternateErrorPage;
3582 nsresult rv = Preferences::GetCString("urlclassifier.alternate_error_page",
3583 alternateErrorPage);
3584 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
3585 errorPage.Assign(alternateErrorPage);
3586 }
3587
3588 if (NS_ERROR_PHISHING_URI == aError) {
3589 error = "deceptiveBlocked";
3590 } else if (NS_ERROR_MALWARE_URI == aError) {
3591 error = "malwareBlocked";
3592 } else if (NS_ERROR_UNWANTED_URI == aError) {
3593 error = "unwantedBlocked";
3594 } else if (NS_ERROR_HARMFUL_URI == aError) {
3595 error = "harmfulBlocked";
3596 }
3597
3598 cssClass.AssignLiteral("blacklist");
3599 } else if (NS_ERROR_CONTENT_CRASHED == aError) {
3600 errorPage.AssignLiteral("tabcrashed");
3601 error = "tabcrashed";
3602
3603 RefPtr<EventTarget> handler = mChromeEventHandler;
3604 if (handler) {
3605 nsCOMPtr<Element> element = do_QueryInterface(handler);
3606 element->GetAttribute(u"crashedPageTitle"_ns, messageStr);
3607 }
3608
3609 // DisplayLoadError requires a non-empty messageStr to proceed and call
3610 // LoadErrorPage. If the page doesn't have a title, we will use a blank
3611 // space which will be trimmed and thus treated as empty by the front-end.
3612 if (messageStr.IsEmpty()) {
3613 messageStr.AssignLiteral(u" ");
3614 }
3615 } else if (NS_ERROR_FRAME_CRASHED == aError) {
3616 errorPage.AssignLiteral("framecrashed");
3617 error = "framecrashed";
3618 messageStr.AssignLiteral(u" ");
3619 } else if (NS_ERROR_BUILDID_MISMATCH == aError) {
3620 errorPage.AssignLiteral("restartrequired");
3621 error = "restartrequired";
3622
3623 // DisplayLoadError requires a non-empty messageStr to proceed and call
3624 // LoadErrorPage. If the page doesn't have a title, we will use a blank
3625 // space which will be trimmed and thus treated as empty by the front-end.
3626 if (messageStr.IsEmpty()) {
3627 messageStr.AssignLiteral(u" ");
3628 }
3629 } else {
3630 // Errors requiring simple formatting
3631 switch (aError) {
3632 case NS_ERROR_MALFORMED_URI:
3633 // URI is malformed
3634 error = "malformedURI";
3635 errorDescriptionID = "malformedURI2";
3636 break;
3637 case NS_ERROR_REDIRECT_LOOP:
3638 // Doc failed to load because the server generated too many redirects
3639 error = "redirectLoop";
3640 break;
3641 case NS_ERROR_UNKNOWN_SOCKET_TYPE:
3642 // Doc failed to load because PSM is not installed
3643 error = "unknownSocketType";
3644 break;
3645 case NS_ERROR_NET_RESET:
3646 // Doc failed to load because the server kept reseting the connection
3647 // before we could read any data from it
3648 error = "netReset";
3649 break;
3650 case NS_ERROR_DOCUMENT_NOT_CACHED:
3651 // Doc failed to load because the cache does not contain a copy of
3652 // the document.
3653 error = "notCached";
3654 break;
3655 case NS_ERROR_OFFLINE:
3656 // Doc failed to load because we are offline.
3657 error = "netOffline";
3658 break;
3659 case NS_ERROR_DOCUMENT_IS_PRINTMODE:
3660 // Doc navigation attempted while Printing or Print Preview
3661 error = "isprinting";
3662 break;
3663 case NS_ERROR_PORT_ACCESS_NOT_ALLOWED:
3664 // Port blocked for security reasons
3665 addHostPort = true;
3666 error = "deniedPortAccess";
3667 break;
3668 case NS_ERROR_UNKNOWN_PROXY_HOST:
3669 // Proxy hostname could not be resolved.
3670 error = "proxyResolveFailure";
3671 break;
3672 case NS_ERROR_PROXY_CONNECTION_REFUSED:
3673 case NS_ERROR_PROXY_FORBIDDEN:
3674 case NS_ERROR_PROXY_NOT_IMPLEMENTED:
3675 case NS_ERROR_PROXY_AUTHENTICATION_FAILED:
3676 case NS_ERROR_PROXY_TOO_MANY_REQUESTS:
3677 // Proxy connection was refused.
3678 error = "proxyConnectFailure";
3679 break;
3680 case NS_ERROR_INVALID_CONTENT_ENCODING:
3681 // Bad Content Encoding.
3682 error = "contentEncodingError";
3683 break;
3684 case NS_ERROR_UNSAFE_CONTENT_TYPE:
3685 // Channel refused to load from an unrecognized content type.
3686 error = "unsafeContentType";
3687 break;
3688 case NS_ERROR_CORRUPTED_CONTENT:
3689 // Broken Content Detected. e.g. Content-MD5 check failure.
3690 error = "corruptedContentErrorv2";
3691 break;
3692 case NS_ERROR_INTERCEPTION_FAILED:
3693 // ServiceWorker intercepted request, but something went wrong.
3694 error = "corruptedContentErrorv2";
3695 break;
3696 case NS_ERROR_NET_INADEQUATE_SECURITY:
3697 // Server negotiated bad TLS for HTTP/2.
3698 error = "inadequateSecurityError";
3699 addHostPort = true;
3700 break;
3701 case NS_ERROR_BLOCKED_BY_POLICY:
3702 case NS_ERROR_DOM_COOP_FAILED:
3703 case NS_ERROR_DOM_COEP_FAILED:
3704 // Page blocked by policy
3705 error = "blockedByPolicy";
3706 break;
3707 case NS_ERROR_NET_HTTP2_SENT_GOAWAY:
3708 case NS_ERROR_NET_HTTP3_PROTOCOL_ERROR:
3709 // HTTP/2 or HTTP/3 stack detected a protocol error
3710 error = "networkProtocolError";
3711 break;
3712
3713 default:
3714 break;
3715 }
3716 }
3717
3718 nsresult delegateErrorCode = aError;
3719 // If the HTTPS-Only Mode upgraded this request and the upgrade might have
3720 // caused this error, we replace the error-page with about:httpsonlyerror
3721 if (nsHTTPSOnlyUtils::CouldBeHttpsOnlyError(aFailedChannel, aError)) {
3722 errorPage.AssignLiteral("httpsonlyerror");
3723 delegateErrorCode = NS_ERROR_HTTPS_ONLY;
3724 } else if (isBadStsCertError) {
3725 delegateErrorCode = NS_ERROR_BAD_HSTS_CERT;
3726 }
3727
3728 if (nsCOMPtr<nsILoadURIDelegate> loadURIDelegate = GetLoadURIDelegate()) {
3729 nsCOMPtr<nsIURI> errorPageURI;
3730 rv = loadURIDelegate->HandleLoadError(
3731 aURI, delegateErrorCode, NS_ERROR_GET_MODULE(delegateErrorCode),
3732 getter_AddRefs(errorPageURI));
3733 // If the docshell is going away there's no point in showing an error page.
3734 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) || mIsBeingDestroyed) {
3735 *aDisplayedErrorPage = false;
3736 return NS_OK;
3737 }
3738
3739 if (errorPageURI) {
3740 *aDisplayedErrorPage =
3741 NS_SUCCEEDED(LoadErrorPage(errorPageURI, aURI, aFailedChannel))((bool)(__builtin_expect(!!(!NS_FAILED_impl(LoadErrorPage(errorPageURI
, aURI, aFailedChannel))), 1)))
;
3742 return NS_OK;
3743 }
3744 }
3745
3746 // Test if the error should be displayed
3747 if (!error) {
3748 return NS_OK;
3749 }
3750
3751 if (!errorDescriptionID) {
3752 errorDescriptionID = error;
3753 }
3754
3755 Telemetry::AccumulateCategoricalKeyed(
3756 IsSubframe() ? "frame"_ns : "top"_ns,
3757 mozilla::dom::LoadErrorToTelemetryLabel(aError));
3758
3759 // Test if the error needs to be formatted
3760 if (!messageStr.IsEmpty()) {
3761 // already obtained message
3762 } else {
3763 if (addHostPort) {
3764 // Build up the host:port string.
3765 nsAutoCString hostport;
3766 if (aURI) {
3767 aURI->GetHostPort(hostport);
3768 } else {
3769 hostport.Assign('?');
3770 }
3771 CopyUTF8toUTF16(hostport, *formatStrs.AppendElement());
3772 }
3773
3774 nsAutoCString spec;
3775 rv = NS_ERROR_NOT_AVAILABLE;
3776 auto& nextFormatStr = *formatStrs.AppendElement();
3777 if (aURI) {
3778 // displaying "file://" is aesthetically unpleasing and could even be
3779 // confusing to the user
3780 if (SchemeIsFile(aURI)) {
3781 aURI->GetPathQueryRef(spec);
3782 } else {
3783 aURI->GetSpec(spec);
3784 }
3785
3786 nsCOMPtr<nsITextToSubURI> textToSubURI(
3787 do_GetService(NS_ITEXTTOSUBURI_CONTRACTID"@mozilla.org/intl/texttosuburi;1", &rv));
3788 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
3789 rv = textToSubURI->UnEscapeURIForUI(spec, nextFormatStr);
3790 }
3791 } else {
3792 spec.Assign('?');
3793 }
3794 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3795 CopyUTF8toUTF16(spec, nextFormatStr);
3796 }
3797 rv = NS_OK;
3798
3799 nsAutoString str;
3800 rv =
3801 stringBundle->FormatStringFromName(errorDescriptionID, formatStrs, str);
3802 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"
, 3802); return rv; } } while (false)
;
3803 messageStr.Assign(str);
3804 }
3805
3806 // Display the error as a page or an alert prompt
3807 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"
, 3807); return NS_ERROR_FAILURE; } } while (false)
;
3808
3809 if ((NS_ERROR_NET_INTERRUPT == aError || NS_ERROR_NET_RESET == aError) &&
3810 SchemeIsHTTPS(aURI)) {
3811 // Maybe TLS intolerant. Treat this as an SSL error.
3812 error = "nssFailure2";
3813 }
3814
3815 if (mBrowsingContext->GetUseErrorPages()) {
3816 // Display an error page
3817 nsresult loadedPage =
3818 LoadErrorPage(aURI, aURL, errorPage.get(), error, messageStr.get(),
3819 cssClass.get(), aFailedChannel);
3820 *aDisplayedErrorPage = NS_SUCCEEDED(loadedPage)((bool)(__builtin_expect(!!(!NS_FAILED_impl(loadedPage)), 1))
)
;
3821 } else {
3822 // The prompter reqires that our private window has a document (or it
3823 // asserts). Satisfy that assertion now since GetDoc will force
3824 // creation of one if it hasn't already been created.
3825 if (mScriptGlobal) {
3826 Unused << mScriptGlobal->GetDoc();
3827 }
3828
3829 // Display a message box
3830 prompter->Alert(nullptr, messageStr.get());
3831 }
3832
3833 return NS_OK;
3834}
3835
3836#define PREF_SAFEBROWSING_ALLOWOVERRIDE"browser.safebrowsing.allowOverride" "browser.safebrowsing.allowOverride"
3837
3838nsresult nsDocShell::LoadErrorPage(nsIURI* aURI, const char16_t* aURL,
3839 const char* aErrorPage,
3840 const char* aErrorType,
3841 const char16_t* aDescription,
3842 const char* aCSSClass,
3843 nsIChannel* aFailedChannel) {
3844 if (mIsBeingDestroyed) {
3845 return NS_ERROR_NOT_AVAILABLE;
3846 }
3847
3848#if defined(DEBUG1)
3849 if (MOZ_LOG_TEST(gDocShellLog, LogLevel::Debug)(__builtin_expect(!!(mozilla::detail::log_test(gDocShellLog, LogLevel
::Debug)), 0))
) {
3850 nsAutoCString chanName;
3851 if (aFailedChannel) {
3852 aFailedChannel->GetName(chanName);
3853 } else {
3854 chanName.AssignLiteral("<no channel>");
3855 }
3856
3857 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)
3858 ("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)
3859 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)
3860 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)
;
3861 }
3862#endif
3863
3864 nsAutoCString url;
3865 if (aURI) {
3866 nsresult rv = aURI->GetSpec(url);
3867 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"
, 3867); return rv; } } while (false)
;
3868 } else if (aURL) {
3869 CopyUTF16toUTF8(MakeStringSpan(aURL), url);
3870 } else {
3871 return NS_ERROR_INVALID_POINTER;
3872 }
3873
3874 // Create a URL to pass all the error information through to the page.
3875
3876#undef SAFE_ESCAPE
3877#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"
, 3877)) { return NS_ERROR_OUT_OF_MEMORY; }
\
3878 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"
, 3878)
) { \
3879 return NS_ERROR_OUT_OF_MEMORY; \
3880 }
3881
3882 nsCString escapedUrl, escapedError, escapedDescription, escapedCSSClass;
3883 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"
, 3883)) { return NS_ERROR_OUT_OF_MEMORY; }
;
3884 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"
, 3884)) { return NS_ERROR_OUT_OF_MEMORY; }
;
3885 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"
, 3886)) { return NS_ERROR_OUT_OF_MEMORY; }
3886 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"
, 3886)) { return NS_ERROR_OUT_OF_MEMORY; }
;
3887 if (aCSSClass) {
3888 nsCString cssClass(aCSSClass);
3889 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"
, 3889)) { return NS_ERROR_OUT_OF_MEMORY; }
;
3890 }
3891 nsCString errorPageUrl("about:");
3892 errorPageUrl.AppendASCII(aErrorPage);
3893 errorPageUrl.AppendLiteral("?e=");
3894
3895 errorPageUrl.AppendASCII(escapedError.get());
3896 errorPageUrl.AppendLiteral("&u=");
3897 errorPageUrl.AppendASCII(escapedUrl.get());
3898 if ((strcmp(aErrorPage, "blocked") == 0) &&
3899 Preferences::GetBool(PREF_SAFEBROWSING_ALLOWOVERRIDE"browser.safebrowsing.allowOverride", true)) {
3900 errorPageUrl.AppendLiteral("&o=1");
3901 }
3902 if (!escapedCSSClass.IsEmpty()) {
3903 errorPageUrl.AppendLiteral("&s=");
3904 errorPageUrl.AppendASCII(escapedCSSClass.get());
3905 }
3906 errorPageUrl.AppendLiteral("&c=UTF-8");
3907
3908 nsCOMPtr<nsICaptivePortalService> cps = do_GetService(NS_CAPTIVEPORTAL_CID{ 0xbdbe0555, 0xfc3d, 0x4f7b, { 0x92, 0x05, 0xc3, 0x09, 0xce,
0xb2, 0xd6, 0x41 } }
);
3909 int32_t cpsState;
3910 if (cps && NS_SUCCEEDED(cps->GetState(&cpsState))((bool)(__builtin_expect(!!(!NS_FAILED_impl(cps->GetState(
&cpsState))), 1)))
&&
3911 cpsState == nsICaptivePortalService::LOCKED_PORTAL) {
3912 errorPageUrl.AppendLiteral("&captive=true");
3913 }
3914
3915 errorPageUrl.AppendLiteral("&d=");
3916 errorPageUrl.AppendASCII(escapedDescription.get());
3917
3918 nsCOMPtr<nsIURI> errorPageURI;
3919 nsresult rv = NS_NewURI(getter_AddRefs(errorPageURI), errorPageUrl);
3920 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"
, 3920); return rv; } } while (false)
;
3921
3922 return LoadErrorPage(errorPageURI, aURI, aFailedChannel);
3923}
3924
3925nsresult nsDocShell::LoadErrorPage(nsIURI* aErrorURI, nsIURI* aFailedURI,
3926 nsIChannel* aFailedChannel) {
3927 mFailedChannel = aFailedChannel;
3928 mFailedURI = aFailedURI;
3929 mFailedLoadType = mLoadType;
3930
3931 if (mLSHE) {
3932 // Abandon mLSHE's BFCache entry and create a new one. This way, if
3933 // we go back or forward to another SHEntry with the same doc
3934 // identifier, the error page won't persist.
3935 mLSHE->AbandonBFCacheEntry();
3936 }
3937
3938 RefPtr<nsDocShellLoadState> loadState = new nsDocShellLoadState(aErrorURI);
3939 loadState->SetTriggeringPrincipal(nsContentUtils::GetSystemPrincipal());
3940 if (mBrowsingContext) {
3941 loadState->SetTriggeringSandboxFlags(mBrowsingContext->GetSandboxFlags());
3942 loadState->SetTriggeringWindowId(
3943 mBrowsingContext->GetCurrentInnerWindowId());
3944 nsPIDOMWindowInner* innerWin = mScriptGlobal->GetCurrentInnerWindow();
3945 if (innerWin) {
3946 loadState->SetTriggeringStorageAccess(innerWin->UsingStorageAccess());
3947 }
3948 }
3949 loadState->SetLoadType(LOAD_ERROR_PAGE);
3950 loadState->SetFirstParty(true);
3951 loadState->SetSourceBrowsingContext(mBrowsingContext);
3952 if (mozilla::SessionHistoryInParent() && mLoadingEntry) {
3953 // We keep the loading entry for the load that failed here. If the user
3954 // reloads we want to try to reload the original load, not the error page.
3955 loadState->SetLoadingSessionHistoryInfo(
3956 MakeUnique<LoadingSessionHistoryInfo>(*mLoadingEntry));
3957 }
3958 return InternalLoad(loadState);
3959}
3960
3961NS_IMETHODIMPnsresult
3962nsDocShell::Reload(uint32_t aReloadFlags) {
3963 if (!IsNavigationAllowed()) {
3964 return NS_OK; // JS may not handle returning of an error code
3965 }
3966
3967 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"
, 3968); MOZ_PretendNoReturn(); } } while (0)
3968 "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"
, 3968); MOZ_PretendNoReturn(); } } while (0)
;
3969 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"
, 3970); MOZ_PretendNoReturn(); } } while (0)
3970 "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"
, 3970); MOZ_PretendNoReturn(); } } while (0)
;
3971
3972 uint32_t loadType = MAKE_LOAD_TYPE(LOAD_RELOAD_NORMAL, aReloadFlags)((LOAD_RELOAD_NORMAL) | ((aReloadFlags) << 16));
3973 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"
, 3973); return NS_ERROR_INVALID_ARG; } } while (false)
;
3974
3975 // Send notifications to the HistoryListener if any, about the impending
3976 // reload
3977 RefPtr<ChildSHistory> rootSH = GetRootSessionHistory();
3978 if (mozilla::SessionHistoryInParent()) {
3979 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)
;
3980 bool forceReload = IsForceReloadType(loadType);
3981 if (!XRE_IsParentProcess()) {
3982 ++mPendingReloadCount;
3983 RefPtr<nsDocShell> docShell(this);
3984 nsCOMPtr<nsIDocumentViewer> viewer(mDocumentViewer);
3985 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"
, 3985); return NS_ERROR_UNEXPECTED; } } while (false)
;
3986
3987 bool okToUnload = true;
3988 MOZ_TRY(viewer->PermitUnload(&okToUnload))do { auto mozTryTempResult_ = ::mozilla::ToResult(viewer->
PermitUnload(&okToUnload)); if ((__builtin_expect(!!(mozTryTempResult_
.isErr()), 0))) { return mozTryTempResult_.propagateErr(); } }
while (0)
;
3989 if (!okToUnload) {
3990 return NS_OK;
3991 }
3992
3993 RefPtr<Document> doc(GetDocument());
3994 RefPtr<BrowsingContext> browsingContext(mBrowsingContext);
3995 nsCOMPtr<nsIURI> currentURI(mCurrentURI);
3996 nsCOMPtr<nsIReferrerInfo> referrerInfo(mReferrerInfo);
3997 RefPtr<StopDetector> stopDetector = new StopDetector();
3998 nsCOMPtr<nsILoadGroup> loadGroup;
3999 GetLoadGroup(getter_AddRefs(loadGroup));
4000 if (loadGroup) {
4001 // loadGroup may be null in theory. In that case stopDetector just
4002 // doesn't do anything.
4003 loadGroup->AddRequest(stopDetector, nullptr);
4004 }
4005
4006 ContentChild::GetSingleton()->SendNotifyOnHistoryReload(
4007 mBrowsingContext, forceReload,
4008 [docShell, doc, loadType, browsingContext, currentURI, referrerInfo,
4009 loadGroup, stopDetector](
4010 std::tuple<bool, Maybe<NotNull<RefPtr<nsDocShellLoadState>>>,
4011 Maybe<bool>>&& aResult) {
4012 auto scopeExit = MakeScopeExit([loadGroup, stopDetector]() {
4013 if (loadGroup) {
4014 loadGroup->RemoveRequest(stopDetector, nullptr, NS_OK);
4015 }
4016 });
4017
4018 // Decrease mPendingReloadCount before any other early returns!
4019 if (--(docShell->mPendingReloadCount) > 0) {
4020 return;
4021 }
4022
4023 if (stopDetector->Canceled()) {
4024 return;
4025 }
4026 bool canReload;
4027 Maybe<NotNull<RefPtr<nsDocShellLoadState>>> loadState;
4028 Maybe<bool> reloadingActiveEntry;
4029
4030 std::tie(canReload, loadState, reloadingActiveEntry) = aResult;
4031
4032 if (!canReload) {
4033 return;
4034 }
4035
4036 if (loadState.isSome()) {
4037 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)
4038 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)
4039 ("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)
;
4040 loadState.ref()->SetNotifiedBeforeUnloadListeners(true);
4041 docShell->LoadHistoryEntry(loadState.ref(), loadType,
4042 reloadingActiveEntry.ref());
4043 } else {
4044 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)
4045 ("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)
;
4046 ReloadDocument(docShell, doc, loadType, browsingContext,
4047 currentURI, referrerInfo,
4048 /* aNotifiedBeforeUnloadListeners */ true);
4049 }
4050 },
4051 [](mozilla::ipc::ResponseRejectReason) {});
4052 } else {
4053 // Parent process
4054 bool canReload = false;
4055 Maybe<NotNull<RefPtr<nsDocShellLoadState>>> loadState;
4056 Maybe<bool> reloadingActiveEntry;
4057 if (!mBrowsingContext->IsDiscarded()) {
4058 mBrowsingContext->Canonical()->NotifyOnHistoryReload(
4059 forceReload, canReload, loadState, reloadingActiveEntry);
4060 }
4061 if (canReload) {
4062 if (loadState.isSome()) {
4063 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)
4064 ("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)
;
4065 LoadHistoryEntry(loadState.ref(), loadType,
4066 reloadingActiveEntry.ref());
4067 } else {
4068 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)
4069 ("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)
;
4070 RefPtr<Document> doc = GetDocument();
4071 RefPtr<BrowsingContext> bc = mBrowsingContext;
4072 nsCOMPtr<nsIURI> currentURI = mCurrentURI;
4073 nsCOMPtr<nsIReferrerInfo> referrerInfo = mReferrerInfo;
4074 ReloadDocument(this, doc, loadType, bc, currentURI, referrerInfo);
4075 }
4076 }
4077 }
4078 return NS_OK;
4079 }
4080
4081 bool canReload = true;
4082 if (rootSH) {
4083 rootSH->LegacySHistory()->NotifyOnHistoryReload(&canReload);
4084 }
4085
4086 if (!canReload) {
4087 return NS_OK;
4088 }
4089
4090 /* If you change this part of code, make sure bug 45297 does not re-occur */
4091 if (mOSHE) {
4092 nsCOMPtr<nsISHEntry> oshe = mOSHE;
4093 return LoadHistoryEntry(
4094 oshe, loadType,
4095 aReloadFlags & nsIWebNavigation::LOAD_FLAGS_USER_ACTIVATION);
4096 }
4097
4098 if (mLSHE) { // In case a reload happened before the current load is done
4099 nsCOMPtr<nsISHEntry> lshe = mLSHE;
4100 return LoadHistoryEntry(
4101 lshe, loadType,
4102 aReloadFlags & nsIWebNavigation::LOAD_FLAGS_USER_ACTIVATION);
4103 }
4104
4105 RefPtr<Document> doc = GetDocument();
4106 RefPtr<BrowsingContext> bc = mBrowsingContext;
4107 nsCOMPtr<nsIURI> currentURI = mCurrentURI;
4108 nsCOMPtr<nsIReferrerInfo> referrerInfo = mReferrerInfo;
4109 return ReloadDocument(this, doc, loadType, bc, currentURI, referrerInfo);
4110}
4111
4112/* static */
4113nsresult nsDocShell::ReloadDocument(nsDocShell* aDocShell, Document* aDocument,
4114 uint32_t aLoadType,
4115 BrowsingContext* aBrowsingContext,
4116 nsIURI* aCurrentURI,
4117 nsIReferrerInfo* aReferrerInfo,
4118 bool aNotifiedBeforeUnloadListeners) {
4119 if (!aDocument) {
4120 return NS_OK;
4121 }
4122
4123 // Do not inherit owner from document
4124 uint32_t flags = INTERNAL_LOAD_FLAGS_NONE;
4125 nsAutoString srcdoc;
4126 nsIURI* baseURI = nullptr;
4127 nsCOMPtr<nsIURI> originalURI;
4128 nsCOMPtr<nsIURI> resultPrincipalURI;
4129 bool loadReplace = false;
4130
4131 nsIPrincipal* triggeringPrincipal = aDocument->NodePrincipal();
4132 nsCOMPtr<nsIContentSecurityPolicy> csp = aDocument->GetCsp();
4133 uint32_t triggeringSandboxFlags = aDocument->GetSandboxFlags();
4134 uint64_t triggeringWindowId = aDocument->InnerWindowID();
4135 bool triggeringStorageAccess = aDocument->UsingStorageAccess();
4136
4137 nsAutoString contentTypeHint;
4138 aDocument->GetContentType(contentTypeHint);
4139
4140 if (aDocument->IsSrcdocDocument()) {
4141 aDocument->GetSrcdocData(srcdoc);
4142 flags |= INTERNAL_LOAD_FLAGS_IS_SRCDOC;
4143 baseURI = aDocument->GetBaseURI();
4144 } else {
4145 srcdoc = VoidString();
4146 }
4147 nsCOMPtr<nsIChannel> chan = aDocument->GetChannel();
4148 if (chan) {
4149 uint32_t loadFlags;
4150 chan->GetLoadFlags(&loadFlags);
4151 loadReplace = loadFlags & nsIChannel::LOAD_REPLACE;
4152 nsCOMPtr<nsIHttpChannel> httpChan(do_QueryInterface(chan));
4153 if (httpChan) {
4154 httpChan->GetOriginalURI(getter_AddRefs(originalURI));
4155 }
4156
4157 nsCOMPtr<nsILoadInfo> loadInfo = chan->LoadInfo();
4158 loadInfo->GetResultPrincipalURI(getter_AddRefs(resultPrincipalURI));
4159 }
4160
4161 if (!triggeringPrincipal) {
4162 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"
, 4162); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"Reload needs a valid triggeringPrincipal" ")"); do { *((volatile
int*)__null) = 4162; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
4163 return NS_ERROR_FAILURE;
4164 }
4165
4166 // Stack variables to ensure changes to the member variables don't affect to
4167 // the call.
4168 nsCOMPtr<nsIURI> currentURI = aCurrentURI;
4169
4170 // Reload always rewrites result principal URI.
4171 Maybe<nsCOMPtr<nsIURI>> emplacedResultPrincipalURI;
4172 emplacedResultPrincipalURI.emplace(std::move(resultPrincipalURI));
4173
4174 RefPtr<WindowContext> context = aBrowsingContext->GetCurrentWindowContext();
4175 RefPtr<nsDocShellLoadState> loadState = new nsDocShellLoadState(currentURI);
4176 loadState->SetReferrerInfo(aReferrerInfo);
4177 loadState->SetOriginalURI(originalURI);
4178 loadState->SetMaybeResultPrincipalURI(emplacedResultPrincipalURI);
4179 loadState->SetLoadReplace(loadReplace);
4180 loadState->SetTriggeringPrincipal(triggeringPrincipal);
4181 loadState->SetTriggeringSandboxFlags(triggeringSandboxFlags);
4182 loadState->SetTriggeringWindowId(triggeringWindowId);
4183 loadState->SetTriggeringStorageAccess(triggeringStorageAccess);
4184 loadState->SetPrincipalToInherit(triggeringPrincipal);
4185 loadState->SetCsp(csp);
4186 loadState->SetInternalLoadFlags(flags);
4187 loadState->SetTypeHint(NS_ConvertUTF16toUTF8(contentTypeHint));
4188 loadState->SetLoadType(aLoadType);
4189 loadState->SetFirstParty(true);
4190 loadState->SetSrcdocData(srcdoc);
4191 loadState->SetSourceBrowsingContext(aBrowsingContext);
4192 loadState->SetBaseURI(baseURI);
4193 loadState->SetHasValidUserGestureActivation(
4194 context && context->HasValidTransientUserGestureActivation());
4195 loadState->SetNotifiedBeforeUnloadListeners(aNotifiedBeforeUnloadListeners);
4196 return aDocShell->InternalLoad(loadState);
4197}
4198
4199NS_IMETHODIMPnsresult
4200nsDocShell::Stop(uint32_t aStopFlags) {
4201 // Revoke any pending event related to content viewer restoration
4202 mRestorePresentationEvent.Revoke();
4203
4204 if (mLoadType == LOAD_ERROR_PAGE) {
4205 if (mLSHE) {
4206 // Since error page loads never unset mLSHE, do so now
4207 SetHistoryEntryAndUpdateBC(Some(nullptr), Some<nsISHEntry*>(mLSHE));
4208 }
4209 mActiveEntryIsLoadingFromSessionHistory = false;
4210
4211 mFailedChannel = nullptr;
4212 mFailedURI = nullptr;
4213 }
4214
4215 if (nsIWebNavigation::STOP_CONTENT & aStopFlags) {
4216 // Stop the document loading and animations
4217 if (mDocumentViewer) {
4218 nsCOMPtr<nsIDocumentViewer> viewer = mDocumentViewer;
4219 viewer->Stop();
4220 }
4221 } else if (nsIWebNavigation::STOP_NETWORK & aStopFlags) {
4222 // Stop the document loading only
4223 if (mDocumentViewer) {
4224 RefPtr<Document> doc = mDocumentViewer->GetDocument();
4225 if (doc) {
4226 doc->StopDocumentLoad();
4227 }
4228 }
4229 }
4230
4231 if (nsIWebNavigation::STOP_NETWORK & aStopFlags) {
4232 // Suspend any timers that were set for this loader. We'll clear
4233 // them out for good in CreateDocumentViewer.
4234 if (mRefreshURIList) {
4235 SuspendRefreshURIs();
4236 mSavedRefreshURIList.swap(mRefreshURIList);
4237 mRefreshURIList = nullptr;
4238 }
4239
4240 // XXXbz We could also pass |this| to nsIURILoader::Stop. That will
4241 // just call Stop() on us as an nsIDocumentLoader... We need fewer
4242 // redundant apis!
4243 Stop();
4244
4245 // Clear out mChannelToDisconnectOnPageHide. This page won't go in the
4246 // BFCache now, and the Stop above will have removed the DocumentChannel
4247 // from the loadgroup.
4248 mChannelToDisconnectOnPageHide = 0;
4249 }
4250
4251 for (auto* child : mChildList.ForwardRange()) {
4252 nsCOMPtr<nsIWebNavigation> shellAsNav(do_QueryObject(child));
4253 if (shellAsNav) {
4254 shellAsNav->Stop(aStopFlags);
4255 }
4256 }
4257
4258 return NS_OK;
4259}
4260
4261NS_IMETHODIMPnsresult
4262nsDocShell::GetDocument(Document** aDocument) {
4263 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"
, 4263); return NS_ERROR_INVALID_POINTER; } } while (false)
;
4264 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"
, 4264); return NS_ERROR_FAILURE; } } while (false)
;
4265
4266 RefPtr<Document> doc = mDocumentViewer->GetDocument();
4267 if (!doc) {
4268 return NS_ERROR_NOT_AVAILABLE;
4269 }
4270
4271 doc.forget(aDocument);
4272 return NS_OK;
4273}
4274
4275NS_IMETHODIMPnsresult
4276nsDocShell::GetCurrentURI(nsIURI** aURI) {
4277 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"
, 4277); return NS_ERROR_INVALID_POINTER; } } while (false)
;
4278
4279 nsCOMPtr<nsIURI> uri = mCurrentURI;
4280 uri.forget(aURI);
4281 return NS_OK;
4282}
4283
4284NS_IMETHODIMPnsresult
4285nsDocShell::GetSessionHistoryXPCOM(nsISupports** aSessionHistory) {
4286 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"
, 4286); return NS_ERROR_INVALID_POINTER; } } while (false)
;
4287 RefPtr<ChildSHistory> shistory = GetSessionHistory();
4288 shistory.forget(aSessionHistory);
4289 return NS_OK;
4290}
4291
4292//*****************************************************************************
4293// nsDocShell::nsIWebPageDescriptor
4294//*****************************************************************************
4295
4296NS_IMETHODIMPnsresult
4297nsDocShell::LoadPageAsViewSource(nsIDocShell* aOtherDocShell,
4298 const nsAString& aURI) {
4299 if (!aOtherDocShell) {
4300 return NS_ERROR_INVALID_POINTER;
4301 }
4302 nsCOMPtr<nsIURI> newURI;
4303 nsresult rv = NS_NewURI(getter_AddRefs(newURI), aURI);
4304 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
4305 return rv;
4306 }
4307
4308 RefPtr<nsDocShellLoadState> loadState;
4309 uint32_t cacheKey;
4310 auto* otherDocShell = nsDocShell::Cast(aOtherDocShell);
4311 if (mozilla::SessionHistoryInParent()) {
4312 loadState = new nsDocShellLoadState(newURI);
4313 if (!otherDocShell->FillLoadStateFromCurrentEntry(*loadState)) {
4314 return NS_ERROR_INVALID_POINTER;
4315 }
4316 cacheKey = otherDocShell->GetCacheKeyFromCurrentEntry().valueOr(0);
4317 } else {
4318 nsCOMPtr<nsISHEntry> entry;
4319 bool isOriginalSHE;
4320 otherDocShell->GetCurrentSHEntry(getter_AddRefs(entry), &isOriginalSHE);
4321 if (!entry) {
4322 return NS_ERROR_INVALID_POINTER;
4323 }
4324 rv = entry->CreateLoadInfo(getter_AddRefs(loadState));
4325 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"
, 4325); return rv; } } while (false)
;
4326 entry->GetCacheKey(&cacheKey);
4327 loadState->SetURI(newURI);
4328 loadState->SetSHEntry(nullptr);
4329 }
4330
4331 // We're doing a load of the page, via an API that
4332 // is only exposed to system code. The triggering principal for this load
4333 // should be the system principal.
4334 loadState->SetTriggeringPrincipal(nsContentUtils::GetSystemPrincipal());
4335 loadState->SetOriginalURI(nullptr);
4336 loadState->SetResultPrincipalURI(nullptr);
4337
4338 return InternalLoad(loadState, Some(cacheKey));
4339}
4340
4341NS_IMETHODIMPnsresult
4342nsDocShell::GetCurrentDescriptor(nsISupports** aPageDescriptor) {
4343 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"
, 4343); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPageDescriptor"
") (" "Null out param?" ")"); do { *((volatile int*)__null) =
4343; __attribute__((nomerge)) ::abort(); } while (false); }
} while (false)
;
4344
4345 *aPageDescriptor = nullptr;
4346
4347 nsISHEntry* src = mOSHE ? mOSHE : mLSHE;
4348 if (src) {
4349 nsCOMPtr<nsISHEntry> dest;
4350
4351 nsresult rv = src->Clone(getter_AddRefs(dest));
4352 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
4353 return rv;
4354 }
4355
4356 // null out inappropriate cloned attributes...
4357 dest->SetParent(nullptr);
4358 dest->SetIsSubFrame(false);
4359
4360 return CallQueryInterface(dest, aPageDescriptor);
4361 }
4362
4363 return NS_ERROR_NOT_AVAILABLE;
4364}
4365
4366already_AddRefed<nsIInputStream> nsDocShell::GetPostDataFromCurrentEntry()
4367 const {
4368 nsCOMPtr<nsIInputStream> postData;
4369 if (mozilla::SessionHistoryInParent()) {
4370 if (mActiveEntry) {
4371 postData = mActiveEntry->GetPostData();
4372 } else if (mLoadingEntry) {
4373 postData = mLoadingEntry->mInfo.GetPostData();
4374 }
4375 } else {
4376 if (mOSHE) {
4377 postData = mOSHE->GetPostData();
4378 } else if (mLSHE) {
4379 postData = mLSHE->GetPostData();
4380 }
4381 }
4382
4383 return postData.forget();
4384}
4385
4386Maybe<uint32_t> nsDocShell::GetCacheKeyFromCurrentEntry() const {
4387 if (mozilla::SessionHistoryInParent()) {
4388 if (mActiveEntry) {
4389 return Some(mActiveEntry->GetCacheKey());
4390 }
4391
4392 if (mLoadingEntry) {
4393 return Some(mLoadingEntry->mInfo.GetCacheKey());
4394 }
4395 } else {
4396 if (mOSHE) {
4397 return Some(mOSHE->GetCacheKey());
4398 }
4399
4400 if (mLSHE) {
4401 return Some(mLSHE->GetCacheKey());
4402 }
4403 }
4404
4405 return Nothing();
4406}
4407
4408bool nsDocShell::FillLoadStateFromCurrentEntry(
4409 nsDocShellLoadState& aLoadState) {
4410 if (mLoadingEntry) {
4411 mLoadingEntry->mInfo.FillLoadInfo(aLoadState);
4412 return true;
4413 }
4414 if (mActiveEntry) {
4415 mActiveEntry->FillLoadInfo(aLoadState);
4416 return true;
4417 }
4418 return false;
4419}
4420
4421//*****************************************************************************
4422// nsDocShell::nsIBaseWindow
4423//*****************************************************************************
4424
4425NS_IMETHODIMPnsresult
4426nsDocShell::InitWindow(nativeWindow aParentNativeWindow,
4427 nsIWidget* aParentWidget, int32_t aX, int32_t aY,
4428 int32_t aWidth, int32_t aHeight) {
4429 SetParentWidget(aParentWidget);
4430 SetPositionAndSize(aX, aY, aWidth, aHeight, 0);
4431 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"
, 4431); return NS_ERROR_FAILURE; } } while (false)
;
4432
4433 return NS_OK;
4434}
4435
4436NS_IMETHODIMPnsresult
4437nsDocShell::Destroy() {
4438 // XXX: We allow this function to be called just once. If you are going to
4439 // reset new variables in this function, please make sure the variables will
4440 // never be re-initialized. Adding assertions to check |mIsBeingDestroyed|
4441 // in the setter functions for the variables would be enough.
4442 if (mIsBeingDestroyed) {
4443 return NS_ERROR_DOCSHELL_DYING;
4444 }
4445
4446 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"
, 4447); MOZ_PretendNoReturn(); } } while (0)
4447 "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"
, 4447); MOZ_PretendNoReturn(); } } while (0)
;
4448
4449 nsCOMPtr<nsIObserverService> serv = services::GetObserverService();
4450 if (serv) {
4451 const char* msg = mItemType == typeContent
4452 ? NS_WEBNAVIGATION_DESTROY"webnavigation-destroy"
4453 : NS_CHROME_WEBNAVIGATION_DESTROY"chrome-webnavigation-destroy";
4454 serv->NotifyObservers(GetAsSupports(this), msg, nullptr);
4455 }
4456
4457 mIsBeingDestroyed = true;
4458
4459 // Brak the cycle with the initial client, if present.
4460 mInitialClientSource.reset();
4461
4462 // Make sure to blow away our mLoadingURI just in case. No loads
4463 // from inside this pagehide.
4464 mLoadingURI = nullptr;
4465
4466 // Fire unload event before we blow anything away.
4467 (void)FirePageHideNotification(true);
4468
4469 // Clear pointers to any detached nsEditorData that's lying
4470 // around in shistory entries. Breaks cycle. See bug 430921.
4471 if (mOSHE) {
4472 mOSHE->SetEditorData(nullptr);
4473 }
4474 if (mLSHE) {
4475 mLSHE->SetEditorData(nullptr);
4476 }
4477
4478 // Note: mContentListener can be null if Init() failed and we're being
4479 // called from the destructor.
4480 if (mContentListener) {
4481 mContentListener->DropDocShellReference();
4482 mContentListener->SetParentContentListener(nullptr);
4483 // Note that we do NOT set mContentListener to null here; that
4484 // way if someone tries to do a load in us after this point
4485 // the nsDSURIContentListener will block it. All of which
4486 // means that we should do this before calling Stop(), of
4487 // course.
4488 }
4489
4490 // Stop any URLs that are currently being loaded...
4491 Stop(nsIWebNavigation::STOP_ALL);
4492
4493 mEditorData = nullptr;
4494
4495 // Save the state of the current document, before destroying the window.
4496 // This is needed to capture the state of a frameset when the new document
4497 // causes the frameset to be destroyed...
4498 PersistLayoutHistoryState();
4499
4500 // Remove this docshell from its parent's child list
4501 nsCOMPtr<nsIDocShellTreeItem> docShellParentAsItem =
4502 do_QueryInterface(GetAsSupports(mParent));
4503 if (docShellParentAsItem) {
4504 docShellParentAsItem->RemoveChild(this);
4505 }
4506
4507 if (mDocumentViewer) {
4508 mDocumentViewer->Close(nullptr);
4509 mDocumentViewer->Destroy();
4510 mDocumentViewer = nullptr;
4511 }
4512
4513 nsDocLoader::Destroy();
4514
4515 mParentWidget = nullptr;
4516 SetCurrentURIInternal(nullptr);
4517
4518 if (mScriptGlobal) {
4519 mScriptGlobal->DetachFromDocShell(!mWillChangeProcess);
4520 mScriptGlobal = nullptr;
4521 }
4522
4523 if (GetSessionHistory()) {
4524 // We want to destroy these content viewers now rather than
4525 // letting their destruction wait for the session history
4526 // entries to get garbage collected. (Bug 488394)
4527 GetSessionHistory()->EvictLocalDocumentViewers();
4528 }
4529
4530 if (mWillChangeProcess && !mBrowsingContext->IsDiscarded()) {
4531 mBrowsingContext->PrepareForProcessChange();
4532 }
4533
4534 SetTreeOwner(nullptr);
4535
4536 mBrowserChild = nullptr;
4537
4538 mChromeEventHandler = nullptr;
4539
4540 // Cancel any timers that were set for this docshell; this is needed
4541 // to break the cycle between us and the timers.
4542 CancelRefreshURITimers();
4543
4544 return NS_OK;
4545}
4546
4547double nsDocShell::GetWidgetCSSToDeviceScale() {
4548 if (mParentWidget) {
4549 return mParentWidget->GetDefaultScale().scale;
4550 }
4551 if (nsCOMPtr<nsIBaseWindow> ownerWindow = do_QueryInterface(mTreeOwner)) {
4552 return ownerWindow->GetWidgetCSSToDeviceScale();
4553 }
4554 return 1.0;
4555}
4556
4557NS_IMETHODIMPnsresult
4558nsDocShell::GetDevicePixelsPerDesktopPixel(double* aScale) {
4559 if (mParentWidget) {
4560 *aScale = mParentWidget->GetDesktopToDeviceScale().scale;
4561 return NS_OK;
4562 }
4563
4564 nsCOMPtr<nsIBaseWindow> ownerWindow(do_QueryInterface(mTreeOwner));
4565 if (ownerWindow) {
4566 return ownerWindow->GetDevicePixelsPerDesktopPixel(aScale);
4567 }
4568
4569 *aScale = 1.0;
4570 return NS_OK;
4571}
4572
4573NS_IMETHODIMPnsresult
4574nsDocShell::SetPosition(int32_t aX, int32_t aY) {
4575 mBounds.MoveTo(aX, aY);
4576
4577 if (mDocumentViewer) {
4578 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"
, 4578); return NS_ERROR_FAILURE; } } while (false)
;
4579 }
4580
4581 return NS_OK;
4582}
4583
4584NS_IMETHODIMPnsresult
4585nsDocShell::SetPositionDesktopPix(int32_t aX, int32_t aY) {
4586 nsCOMPtr<nsIBaseWindow> ownerWindow(do_QueryInterface(mTreeOwner));
4587 if (ownerWindow) {
4588 return ownerWindow->SetPositionDesktopPix(aX, aY);
4589 }
4590
4591 double scale = 1.0;
4592 GetDevicePixelsPerDesktopPixel(&scale);
4593 return SetPosition(NSToIntRound(aX * scale), NSToIntRound(aY * scale));
4594}
4595
4596NS_IMETHODIMPnsresult
4597nsDocShell::GetPosition(int32_t* aX, int32_t* aY) {
4598 return GetPositionAndSize(aX, aY, nullptr, nullptr);
4599}
4600
4601NS_IMETHODIMPnsresult
4602nsDocShell::SetSize(int32_t aWidth, int32_t aHeight, bool aRepaint) {
4603 int32_t x = 0, y = 0;
4604 GetPosition(&x, &y);
4605 return SetPositionAndSize(x, y, aWidth, aHeight,
4606 aRepaint ? nsIBaseWindow::eRepaint : 0);
4607}
4608
4609NS_IMETHODIMPnsresult
4610nsDocShell::GetSize(int32_t* aWidth, int32_t* aHeight) {
4611 return GetPositionAndSize(nullptr, nullptr, aWidth, aHeight);
4612}
4613
4614NS_IMETHODIMPnsresult
4615nsDocShell::SetPositionAndSize(int32_t aX, int32_t aY, int32_t aWidth,
4616 int32_t aHeight, uint32_t aFlags) {
4617 mBounds.SetRect(aX, aY, aWidth, aHeight);
4618
4619 // Hold strong ref, since SetBounds can make us null out mDocumentViewer
4620 nsCOMPtr<nsIDocumentViewer> viewer = mDocumentViewer;
4621 if (viewer) {
4622 uint32_t cvflags = (aFlags & nsIBaseWindow::eDelayResize)
4623 ? nsIDocumentViewer::eDelayResize
4624 : 0;
4625 // XXX Border figured in here or is that handled elsewhere?
4626 nsresult rv = viewer->SetBoundsWithFlags(mBounds, cvflags);
4627 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"
, 4627); return NS_ERROR_FAILURE; } } while (false)
;
4628 }
4629
4630 return NS_OK;
4631}
4632
4633NS_IMETHODIMPnsresult
4634nsDocShell::GetPositionAndSize(int32_t* aX, int32_t* aY, int32_t* aWidth,
4635 int32_t* aHeight) {
4636 if (mParentWidget) {
4637 // ensure size is up-to-date if window has changed resolution
4638 LayoutDeviceIntRect r = mParentWidget->GetClientBounds();
4639 SetPositionAndSize(mBounds.X(), mBounds.Y(), r.Width(), r.Height(), 0);
4640 }
4641
4642 // We should really consider just getting this information from
4643 // our window instead of duplicating the storage and code...
4644 if (aWidth || aHeight) {
4645 // Caller wants to know our size; make sure to give them up to
4646 // date information.
4647 RefPtr<Document> doc(do_GetInterface(GetAsSupports(mParent)));
4648 if (doc) {
4649 doc->FlushPendingNotifications(FlushType::Layout);
4650 }
4651 }
4652
4653 DoGetPositionAndSize(aX, aY, aWidth, aHeight);
4654 return NS_OK;
4655}
4656
4657void nsDocShell::DoGetPositionAndSize(int32_t* aX, int32_t* aY, int32_t* aWidth,
4658 int32_t* aHeight) {
4659 if (aX) {
4660 *aX = mBounds.X();
4661 }
4662 if (aY) {
4663 *aY = mBounds.Y();
4664 }
4665 if (aWidth) {
4666 *aWidth = mBounds.Width();
4667 }
4668 if (aHeight) {
4669 *aHeight = mBounds.Height();
4670 }
4671}
4672
4673NS_IMETHODIMPnsresult
4674nsDocShell::SetDimensions(DimensionRequest&& aRequest) {
4675 return NS_ERROR_NOT_IMPLEMENTED;
4676}
4677
4678NS_IMETHODIMPnsresult
4679nsDocShell::GetDimensions(DimensionKind aDimensionKind, int32_t* aX,
4680 int32_t* aY, int32_t* aCX, int32_t* aCY) {
4681 return NS_ERROR_NOT_IMPLEMENTED;
4682}
4683
4684NS_IMETHODIMPnsresult
4685nsDocShell::Repaint(bool aForce) {
4686 PresShell* presShell = GetPresShell();
4687 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"
, 4687); return NS_ERROR_FAILURE; } } while (false)
;
4688
4689 RefPtr<nsViewManager> viewManager = presShell->GetViewManager();
4690 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"
, 4690); return NS_ERROR_FAILURE; } } while (false)
;
4691
4692 viewManager->InvalidateAllViews();
4693 return NS_OK;
4694}
4695
4696NS_IMETHODIMPnsresult
4697nsDocShell::GetParentWidget(nsIWidget** aParentWidget) {
4698 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"
, 4698); return NS_ERROR_INVALID_POINTER; } } while (false)
;
4699
4700 *aParentWidget = mParentWidget;
4701 NS_IF_ADDREF(*aParentWidget)ns_if_addref(*aParentWidget);
4702
4703 return NS_OK;
4704}
4705
4706NS_IMETHODIMPnsresult
4707nsDocShell::SetParentWidget(nsIWidget* aParentWidget) {
4708 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"
, 4708); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mIsBeingDestroyed"
")"); do { *((volatile int*)__null) = 4708; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4709 mParentWidget = aParentWidget;
4710
4711 return NS_OK;
4712}
4713
4714NS_IMETHODIMPnsresult
4715nsDocShell::GetParentNativeWindow(nativeWindow* aParentNativeWindow) {
4716 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"
, 4716); return NS_ERROR_INVALID_POINTER; } } while (false)
;
4717
4718 if (mParentWidget) {
4719 *aParentNativeWindow = mParentWidget->GetNativeData(NS_NATIVE_WIDGET3);
4720 } else {
4721 *aParentNativeWindow = nullptr;
4722 }
4723
4724 return NS_OK;
4725}
4726
4727NS_IMETHODIMPnsresult
4728nsDocShell::SetParentNativeWindow(nativeWindow aParentNativeWindow) {
4729 return NS_ERROR_NOT_IMPLEMENTED;
4730}
4731
4732NS_IMETHODIMPnsresult
4733nsDocShell::GetNativeHandle(nsAString& aNativeHandle) {
4734 // the nativeHandle should be accessed from nsIAppWindow
4735 return NS_ERROR_NOT_IMPLEMENTED;
4736}
4737
4738NS_IMETHODIMPnsresult
4739nsDocShell::GetVisibility(bool* aVisibility) {
4740 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"
, 4740); return NS_ERROR_INVALID_POINTER; } } while (false)
;
4741
4742 *aVisibility = false;
4743
4744 if (!mDocumentViewer) {
4745 return NS_OK;
4746 }
4747
4748 PresShell* presShell = GetPresShell();
4749 if (!presShell) {
4750 return NS_OK;
4751 }
4752
4753 // get the view manager
4754 nsViewManager* vm = presShell->GetViewManager();
4755 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"
, 4755); return NS_ERROR_FAILURE; } } while (false)
;
4756
4757 // get the root view
4758 nsView* view = vm->GetRootView(); // views are not ref counted
4759 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"
, 4759); return NS_ERROR_FAILURE; } } while (false)
;
4760
4761 // if our root view is hidden, we are not visible
4762 if (view->GetVisibility() == ViewVisibility::Hide) {
4763 return NS_OK;
4764 }
4765
4766 // otherwise, we must walk up the document and view trees checking
4767 // for a hidden view, unless we're an off screen browser, which
4768 // would make this test meaningless.
4769
4770 RefPtr<nsDocShell> docShell = this;
4771 RefPtr<nsDocShell> parentItem = docShell->GetInProcessParentDocshell();
4772 while (parentItem) {
4773 // Null-check for crash in bug 267804
4774 if (!parentItem->GetPresShell()) {
4775 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"
, 4775); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "parent docshell has null pres shell"
")"); do { *((volatile int*)__null) = 4775; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4776 return NS_OK;
4777 }
4778
4779 vm = docShell->GetPresShell()->GetViewManager();
4780 if (vm) {
4781 view = vm->GetRootView();
4782 }
4783
4784 if (view) {
4785 view = view->GetParent(); // anonymous inner view
4786 if (view) {
4787 view = view->GetParent(); // subdocumentframe's view
4788 }
4789 }
4790
4791 nsIFrame* frame = view ? view->GetFrame() : nullptr;
4792 if (frame && !frame->IsVisibleConsideringAncestors(
4793 nsIFrame::VISIBILITY_CROSS_CHROME_CONTENT_BOUNDARY)) {
4794 return NS_OK;
4795 }
4796
4797 docShell = parentItem;
4798 parentItem = docShell->GetInProcessParentDocshell();
4799 }
4800
4801 nsCOMPtr<nsIBaseWindow> treeOwnerAsWin(do_QueryInterface(mTreeOwner));
4802 if (!treeOwnerAsWin) {
4803 *aVisibility = true;
4804 return NS_OK;
4805 }
4806
4807 // Check with the tree owner as well to give embedders a chance to
4808 // expose visibility as well.
4809 nsresult rv = treeOwnerAsWin->GetVisibility(aVisibility);
4810 if (rv == NS_ERROR_NOT_IMPLEMENTED) {
4811 // The tree owner had no opinion on our visibility.
4812 *aVisibility = true;
4813 return NS_OK;
4814 }
4815 return rv;
4816}
4817
4818void nsDocShell::ActivenessMaybeChanged() {
4819 const bool isActive = mBrowsingContext->IsActive();
4820 if (RefPtr<PresShell> presShell = GetPresShell()) {
4821 presShell->ActivenessMaybeChanged();
4822 }
4823
4824 // Tell the window about it
4825 if (mScriptGlobal) {
4826 mScriptGlobal->SetIsBackground(!isActive);
4827 if (RefPtr<Document> doc = mScriptGlobal->GetExtantDoc()) {
4828 // Update orientation when the top-level browsing context becomes active.
4829 if (isActive && mBrowsingContext->IsTop()) {
4830 // We only care about the top-level browsing context.
4831 auto orientation = mBrowsingContext->GetOrientationLock();
4832 ScreenOrientation::UpdateActiveOrientationLock(orientation);
4833 }
4834
4835 doc->PostVisibilityUpdateEvent();
4836 }
4837 }
4838
4839 // Tell the nsDOMNavigationTiming about it
4840 RefPtr<nsDOMNavigationTiming> timing = mTiming;
4841 if (!timing && mDocumentViewer) {
4842 if (Document* doc = mDocumentViewer->GetDocument()) {
4843 timing = doc->GetNavigationTiming();
4844 }
4845 }
4846 if (timing) {
4847 timing->NotifyDocShellStateChanged(
4848 isActive ? nsDOMNavigationTiming::DocShellState::eActive
4849 : nsDOMNavigationTiming::DocShellState::eInactive);
4850 }
4851
4852 // Restart or stop meta refresh timers if necessary
4853 if (mDisableMetaRefreshWhenInactive) {
4854 if (isActive) {
4855 ResumeRefreshURIs();
4856 } else {
4857 SuspendRefreshURIs();
4858 }
4859 }
4860
4861 if (InputTaskManager::CanSuspendInputEvent()) {
4862 mBrowsingContext->Group()->UpdateInputTaskManagerIfNeeded(isActive);
4863 }
4864}
4865
4866NS_IMETHODIMPnsresult
4867nsDocShell::SetDefaultLoadFlags(uint32_t aDefaultLoadFlags) {
4868 if (!mWillChangeProcess) {
4869 // Intentionally ignoring handling discarded browsing contexts.
4870 Unused << mBrowsingContext->SetDefaultLoadFlags(aDefaultLoadFlags);
4871 } else {
4872 // Bug 1623565: DevTools tries to clean up defaultLoadFlags on
4873 // shutdown. Sorry DevTools, your DocShell is in another process.
4874 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"
, 4874)
;
4875 }
4876 return NS_OK;
4877}
4878
4879NS_IMETHODIMPnsresult
4880nsDocShell::GetDefaultLoadFlags(uint32_t* aDefaultLoadFlags) {
4881 *aDefaultLoadFlags = mBrowsingContext->GetDefaultLoadFlags();
4882 return NS_OK;
4883}
4884
4885NS_IMETHODIMPnsresult
4886nsDocShell::GetFailedChannel(nsIChannel** aFailedChannel) {
4887 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"
, 4887); return NS_ERROR_INVALID_POINTER; } } while (false)
;
4888 Document* doc = GetDocument();
4889 if (!doc) {
4890 *aFailedChannel = nullptr;
4891 return NS_OK;
4892 }
4893 NS_IF_ADDREF(*aFailedChannel = doc->GetFailedChannel())ns_if_addref(*aFailedChannel = doc->GetFailedChannel());
4894 return NS_OK;
4895}
4896
4897NS_IMETHODIMPnsresult
4898nsDocShell::SetVisibility(bool aVisibility) {
4899 // Show()/Hide() may change mDocumentViewer.
4900 nsCOMPtr<nsIDocumentViewer> viewer = mDocumentViewer;
4901 if (!viewer) {
4902 return NS_OK;
4903 }
4904 if (aVisibility) {
4905 viewer->Show();
4906 } else {
4907 viewer->Hide();
4908 }
4909
4910 return NS_OK;
4911}
4912
4913NS_IMETHODIMPnsresult
4914nsDocShell::GetEnabled(bool* aEnabled) {
4915 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"
, 4915); return NS_ERROR_INVALID_POINTER; } } while (false)
;
4916 *aEnabled = true;
4917 return NS_ERROR_NOT_IMPLEMENTED;
4918}
4919
4920NS_IMETHODIMPnsresult
4921nsDocShell::SetEnabled(bool aEnabled) { return NS_ERROR_NOT_IMPLEMENTED; }
4922
4923NS_IMETHODIMPnsresult
4924nsDocShell::GetMainWidget(nsIWidget** aMainWidget) {
4925 // We don't create our own widget, so simply return the parent one.
4926 return GetParentWidget(aMainWidget);
4927}
4928
4929NS_IMETHODIMPnsresult
4930nsDocShell::GetTitle(nsAString& aTitle) {
4931 aTitle = mTitle;
4932 return NS_OK;
4933}
4934
4935NS_IMETHODIMPnsresult
4936nsDocShell::SetTitle(const nsAString& aTitle) {
4937 // Avoid unnecessary updates of the title if the URI and the title haven't
4938 // changed.
4939 if (mTitleValidForCurrentURI && mTitle == aTitle) {
4940 return NS_OK;
4941 }
4942
4943 // Store local title
4944 mTitle = aTitle;
4945 mTitleValidForCurrentURI = true;
4946
4947 // When title is set on the top object it should then be passed to the
4948 // tree owner.
4949 if (mBrowsingContext->IsTop()) {
4950 nsCOMPtr<nsIBaseWindow> treeOwnerAsWin(do_QueryInterface(mTreeOwner));
4951 if (treeOwnerAsWin) {
4952 treeOwnerAsWin->SetTitle(aTitle);
4953 }
4954 }
4955
4956 if (mCurrentURI && mLoadType != LOAD_ERROR_PAGE) {
4957 UpdateGlobalHistoryTitle(mCurrentURI);
4958 }
4959
4960 // Update SessionHistory with the document's title.
4961 if (mLoadType != LOAD_BYPASS_HISTORY && mLoadType != LOAD_ERROR_PAGE) {
4962 SetTitleOnHistoryEntry(true);
4963 }
4964
4965 return NS_OK;
4966}
4967
4968void nsDocShell::SetTitleOnHistoryEntry(bool aUpdateEntryInSessionHistory) {
4969 if (mOSHE) {
4970 mOSHE->SetTitle(mTitle);
4971 }
4972
4973 if (mActiveEntry && mBrowsingContext) {
4974 mActiveEntry->SetTitle(mTitle);
4975 if (aUpdateEntryInSessionHistory) {
4976 if (XRE_IsParentProcess()) {
4977 SessionHistoryEntry* entry =
4978 mBrowsingContext->Canonical()->GetActiveSessionHistoryEntry();
4979 if (entry) {
4980 entry->SetTitle(mTitle);
4981 }
4982 } else {
4983 mozilla::Unused
4984 << ContentChild::GetSingleton()->SendSessionHistoryEntryTitle(
4985 mBrowsingContext, mTitle);
4986 }
4987 }
4988 }
4989}
4990
4991nsPoint nsDocShell::GetCurScrollPos() {
4992 nsPoint scrollPos;
4993 if (nsIScrollableFrame* sf = GetRootScrollFrame()) {
4994 scrollPos = sf->GetVisualViewportOffset();
4995 }
4996 return scrollPos;
4997}
4998
4999nsresult nsDocShell::SetCurScrollPosEx(int32_t aCurHorizontalPos,
5000 int32_t aCurVerticalPos) {
5001 nsIScrollableFrame* sf = GetRootScrollFrame();
5002 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"
, 5002); return NS_ERROR_FAILURE; } } while (false)
;
5003
5004 ScrollMode scrollMode =
5005 sf->IsSmoothScroll() ? ScrollMode::SmoothMsd : ScrollMode::Instant;
5006
5007 nsPoint targetPos(aCurHorizontalPos, aCurVerticalPos);
5008 sf->ScrollTo(targetPos, scrollMode);
5009
5010 // Set the visual viewport offset as well.
5011
5012 RefPtr<PresShell> presShell = GetPresShell();
5013 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"
, 5013); return NS_ERROR_FAILURE; } } while (false)
;
5014
5015 nsPresContext* presContext = presShell->GetPresContext();
5016 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"
, 5016); return NS_ERROR_FAILURE; } } while (false)
;
5017
5018 // Only the root content document can have a distinct visual viewport offset.
5019 if (!presContext->IsRootContentDocumentCrossProcess()) {
5020 return NS_OK;
5021 }
5022
5023 // Not on a platform with a distinct visual viewport - don't bother setting
5024 // the visual viewport offset.
5025 if (!presShell->IsVisualViewportSizeSet()) {
5026 return NS_OK;
5027 }
5028
5029 presShell->ScrollToVisual(targetPos, layers::FrameMetrics::eMainThread,
5030 scrollMode);
5031
5032 return NS_OK;
5033}
5034
5035void nsDocShell::SetScrollbarPreference(mozilla::ScrollbarPreference aPref) {
5036 if (mScrollbarPref == aPref) {
5037 return;
5038 }
5039 mScrollbarPref = aPref;
5040 auto* ps = GetPresShell();
5041 if (!ps) {
5042 return;
5043 }
5044 nsIFrame* scrollFrame = ps->GetRootScrollFrame();
5045 if (!scrollFrame) {
5046 return;
5047 }
5048 ps->FrameNeedsReflow(scrollFrame,
5049 IntrinsicDirty::FrameAncestorsAndDescendants,
5050 NS_FRAME_IS_DIRTY);
5051}
5052
5053//*****************************************************************************
5054// nsDocShell::nsIRefreshURI
5055//*****************************************************************************
5056
5057NS_IMETHODIMPnsresult
5058nsDocShell::RefreshURI(nsIURI* aURI, nsIPrincipal* aPrincipal,
5059 uint32_t aDelay) {
5060 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"
, 5060); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mIsBeingDestroyed"
")"); do { *((volatile int*)__null) = 5060; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5061
5062 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"
, 5062); return NS_ERROR_INVALID_ARG; } } while (false)
;
5063
5064 /* Check if Meta refresh/redirects are permitted. Some
5065 * embedded applications may not want to do this.
5066 * Must do this before sending out NOTIFY_REFRESH events
5067 * because listeners may have side effects (e.g. displaying a
5068 * button to manually trigger the refresh later).
5069 */
5070 bool allowRedirects = true;
5071 GetAllowMetaRedirects(&allowRedirects);
5072 if (!allowRedirects) {
5073 return NS_OK;
5074 }
5075
5076 // If any web progress listeners are listening for NOTIFY_REFRESH events,
5077 // give them a chance to block this refresh.
5078 bool sameURI;
5079 nsresult rv = aURI->Equals(mCurrentURI, &sameURI);
5080 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
5081 sameURI = false;
5082 }
5083 if (!RefreshAttempted(this, aURI, aDelay, sameURI)) {
5084 return NS_OK;
5085 }
5086
5087 nsCOMPtr<nsITimerCallback> refreshTimer =
5088 new nsRefreshTimer(this, aURI, aPrincipal, aDelay);
5089
5090 BusyFlags busyFlags = GetBusyFlags();
5091
5092 if (!mRefreshURIList) {
5093 mRefreshURIList = nsArray::Create();
5094 }
5095
5096 if (busyFlags & BUSY_FLAGS_BUSY ||
5097 (!mBrowsingContext->IsActive() && mDisableMetaRefreshWhenInactive)) {
5098 // We don't want to create the timer right now. Instead queue up the
5099 // request and trigger the timer in EndPageLoad() or whenever we become
5100 // active.
5101 mRefreshURIList->AppendElement(refreshTimer);
5102 } else {
5103 // There is no page loading going on right now. Create the
5104 // timer and fire it right away.
5105 nsCOMPtr<nsPIDOMWindowOuter> win = GetWindow();
5106 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"
, 5106); return NS_ERROR_FAILURE; } } while (false)
;
5107
5108 nsCOMPtr<nsITimer> timer;
5109 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)
5110 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)
;
5111
5112 mRefreshURIList->AppendElement(timer); // owning timer ref
5113 }
5114 return NS_OK;
5115}
5116
5117nsresult nsDocShell::ForceRefreshURIFromTimer(nsIURI* aURI,
5118 nsIPrincipal* aPrincipal,
5119 uint32_t aDelay,
5120 nsITimer* aTimer) {
5121 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"
, 5121); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aTimer" ") ("
"Must have a timer here" ")"); do { *((volatile int*)__null)
= 5121; __attribute__((nomerge)) ::abort(); } while (false);
} } while (false)
;
5122
5123 // Remove aTimer from mRefreshURIList if needed
5124 if (mRefreshURIList) {
5125 uint32_t n = 0;
5126 mRefreshURIList->GetLength(&n);
5127
5128 for (uint32_t i = 0; i < n; ++i) {
5129 nsCOMPtr<nsITimer> timer = do_QueryElementAt(mRefreshURIList, i);
5130 if (timer == aTimer) {
5131 mRefreshURIList->RemoveElementAt(i);
5132 break;
5133 }
5134 }
5135 }
5136
5137 return ForceRefreshURI(aURI, aPrincipal, aDelay);
5138}
5139
5140NS_IMETHODIMPnsresult
5141nsDocShell::ForceRefreshURI(nsIURI* aURI, nsIPrincipal* aPrincipal,
5142 uint32_t aDelay) {
5143 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"
, 5143); return NS_ERROR_INVALID_ARG; } } while (false)
;
5144
5145 RefPtr<nsDocShellLoadState> loadState = new nsDocShellLoadState(aURI);
5146 loadState->SetOriginalURI(mCurrentURI);
5147 loadState->SetResultPrincipalURI(aURI);
5148 loadState->SetResultPrincipalURIIsSome(true);
5149 loadState->SetKeepResultPrincipalURIIfSet(true);
5150 loadState->SetIsMetaRefresh(true);
5151
5152 // Set the triggering pricipal to aPrincipal if available, or current
5153 // document's principal otherwise.
5154 nsCOMPtr<nsIPrincipal> principal = aPrincipal;
5155 RefPtr<Document> doc = GetDocument();
5156 if (!principal) {
5157 if (!doc) {
5158 return NS_ERROR_FAILURE;
5159 }
5160 principal = doc->NodePrincipal();
5161 }
5162 loadState->SetTriggeringPrincipal(principal);
5163 if (doc) {
5164 loadState->SetCsp(doc->GetCsp());
5165 loadState->SetHasValidUserGestureActivation(
5166 doc->HasValidTransientUserGestureActivation());
5167 loadState->SetTriggeringSandboxFlags(doc->GetSandboxFlags());
5168 loadState->SetTriggeringWindowId(doc->InnerWindowID());
5169 loadState->SetTriggeringStorageAccess(doc->UsingStorageAccess());
5170 }
5171
5172 loadState->SetPrincipalIsExplicit(true);
5173
5174 /* Check if this META refresh causes a redirection
5175 * to another site.
5176 */
5177 bool equalUri = false;
5178 nsresult rv = aURI->Equals(mCurrentURI, &equalUri);
5179
5180 nsCOMPtr<nsIReferrerInfo> referrerInfo;
5181 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && !equalUri && aDelay <= REFRESH_REDIRECT_TIMER15000) {
5182 /* It is a META refresh based redirection within the threshold time
5183 * we have in mind (15000 ms as defined by REFRESH_REDIRECT_TIMER).
5184 * Pass a REPLACE flag to LoadURI().
5185 */
5186 loadState->SetLoadType(LOAD_REFRESH_REPLACE);
5187
5188 /* For redirects we mimic HTTP, which passes the
5189 * original referrer.
5190 * We will pass in referrer but will not send to server
5191 */
5192 if (mReferrerInfo) {
5193 referrerInfo = static_cast<ReferrerInfo*>(mReferrerInfo.get())
5194 ->CloneWithNewSendReferrer(false);
5195 }
5196 } else {
5197 loadState->SetLoadType(LOAD_REFRESH);
5198 /* We do need to pass in a referrer, but we don't want it to
5199 * be sent to the server.
5200 * For most refreshes the current URI is an appropriate
5201 * internal referrer.
5202 */
5203 referrerInfo = new ReferrerInfo(mCurrentURI, ReferrerPolicy::_empty, false);
5204 }
5205
5206 loadState->SetReferrerInfo(referrerInfo);
5207 loadState->SetLoadFlags(
5208 nsIWebNavigation::LOAD_FLAGS_DISALLOW_INHERIT_PRINCIPAL);
5209 loadState->SetFirstParty(true);
5210
5211 /*
5212 * LoadURI(...) will cancel all refresh timers... This causes the
5213 * Timer and its refreshData instance to be released...
5214 */
5215 LoadURI(loadState, false);
5216
5217 return NS_OK;
5218}
5219
5220static const char16_t* SkipASCIIWhitespace(const char16_t* aStart,
5221 const char16_t* aEnd) {
5222 const char16_t* iter = aStart;
5223 while (iter != aEnd && mozilla::IsAsciiWhitespace(*iter)) {
5224 ++iter;
5225 }
5226 return iter;
5227}
5228
5229static std::tuple<const char16_t*, const char16_t*> ExtractURLString(
5230 const char16_t* aPosition, const char16_t* aEnd) {
5231 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"
, 5231); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPosition != aEnd"
")"); do { *((volatile int*)__null) = 5231; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5232
5233 // 1. Let urlString be the substring of input from the code point at
5234 // position to the end of the string.
5235 const char16_t* urlStart = aPosition;
5236 const char16_t* urlEnd = aEnd;
5237
5238 // 2. If the code point in input pointed to by position is U+0055 (U) or
5239 // U+0075 (u), then advance position to the next code point.
5240 // Otherwise, jump to the step labeled skip quotes.
5241 if (*aPosition == 'U' || *aPosition == 'u') {
5242 ++aPosition;
5243
5244 // 3. If the code point in input pointed to by position is U+0052 (R) or
5245 // U+0072 (r), then advance position to the next code point.
5246 // Otherwise, jump to the step labeled parse.
5247 if (aPosition == aEnd || (*aPosition != 'R' && *aPosition != 'r')) {
5248 return std::make_tuple(urlStart, urlEnd);
5249 }
5250
5251 ++aPosition;
5252
5253 // 4. If the code point in input pointed to by position is U+004C (L) or
5254 // U+006C (l), then advance position to the next code point.
5255 // Otherwise, jump to the step labeled parse.
5256 if (aPosition == aEnd || (*aPosition != 'L' && *aPosition != 'l')) {
5257 return std::make_tuple(urlStart, urlEnd);
5258 }
5259
5260 ++aPosition;
5261
5262 // 5. Skip ASCII whitespace within input given position.
5263 aPosition = SkipASCIIWhitespace(aPosition, aEnd);
5264
5265 // 6. If the code point in input pointed to by position is U+003D (=),
5266 // then advance position to the next code point. Otherwise, jump to
5267 // the step labeled parse.
5268 if (aPosition == aEnd || *aPosition != '=') {
5269 return std::make_tuple(urlStart, urlEnd);
5270 }
5271
5272 ++aPosition;
5273
5274 // 7. Skip ASCII whitespace within input given position.
5275 aPosition = SkipASCIIWhitespace(aPosition, aEnd);
5276 }
5277
5278 // 8. Skip quotes: If the code point in input pointed to by position is
5279 // U+0027 (') or U+0022 ("), then let quote be that code point, and
5280 // advance position to the next code point. Otherwise, let quote be
5281 // the empty string.
5282 Maybe<char> quote;
5283 if (aPosition != aEnd && (*aPosition == '\'' || *aPosition == '"')) {
5284 quote.emplace(*aPosition);
5285 ++aPosition;
5286 }
5287
5288 // 9. Set urlString to the substring of input from the code point at
5289 // position to the end of the string.
5290 urlStart = aPosition;
5291 urlEnd = aEnd;
5292
5293 // 10. If quote is not the empty string, and there is a code point in
5294 // urlString equal to quote, then truncate urlString at that code
5295 // point, so that it and all subsequent code points are removed.
5296 const char16_t* quotePos;
5297 if (quote.isSome() &&
5298 (quotePos = nsCharTraits<char16_t>::find(
5299 urlStart, std::distance(urlStart, aEnd), quote.value()))) {
5300 urlEnd = quotePos;
5301 }
5302
5303 return std::make_tuple(urlStart, urlEnd);
5304}
5305
5306void nsDocShell::SetupRefreshURIFromHeader(Document* aDocument,
5307 const nsAString& aHeader) {
5308 if (mIsBeingDestroyed) {
5309 return;
5310 }
5311
5312 const char16_t* position = aHeader.BeginReading();
5313 const char16_t* end = aHeader.EndReading();
5314
5315 // See
5316 // https://html.spec.whatwg.org/#pragma-directives:shared-declarative-refresh-steps.
5317
5318 // 3. Skip ASCII whitespace
5319 position = SkipASCIIWhitespace(position, end);
5320
5321 // 4. Let time be 0.
5322 CheckedInt<uint32_t> milliSeconds;
5323
5324 // 5. Collect a sequence of code points that are ASCII digits
5325 const char16_t* digitsStart = position;
5326 while (position != end && mozilla::IsAsciiDigit(*position)) {
5327 ++position;
5328 }
5329
5330 if (position == digitsStart) {
5331 // 6. If timeString is the empty string, then:
5332 // 1. If the code point in input pointed to by position is not U+002E
5333 // (.), then return.
5334 if (position == end || *position != '.') {
5335 return;
5336 }
5337 } else {
5338 // 7. Otherwise, set time to the result of parsing timeString using the
5339 // rules for parsing non-negative integers.
5340 nsContentUtils::ParseHTMLIntegerResultFlags result;
5341 uint32_t seconds =
5342 nsContentUtils::ParseHTMLInteger(digitsStart, position, &result);
5343 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"
, 5343); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!(result & nsContentUtils::eParseHTMLInteger_Negative)"
")"); do { *((volatile int*)__null) = 5343; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5344 if (result & nsContentUtils::eParseHTMLInteger_Error) {
5345 // The spec assumes no errors here (since we only pass ASCII digits in),
5346 // but we can still overflow, so this block should deal with that (and
5347 // only that).
5348 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"
, 5348); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!(result & nsContentUtils::eParseHTMLInteger_ErrorOverflow)"
")"); do { *((volatile int*)__null) = 5348; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5349 return;
5350 }
5351 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"
, 5352); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!(result & nsContentUtils::eParseHTMLInteger_DidNotConsumeAllInput)"
")"); do { *((volatile int*)__null) = 5352; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
5352 !(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"
, 5352); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!(result & nsContentUtils::eParseHTMLInteger_DidNotConsumeAllInput)"
")"); do { *((volatile int*)__null) = 5352; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5353
5354 milliSeconds = seconds;
5355 milliSeconds *= 1000;
5356 if (!milliSeconds.isValid()) {
5357 return;
5358 }
5359 }
5360
5361 // 8. Collect a sequence of code points that are ASCII digits and U+002E FULL
5362 // STOP characters (.) from input given position. Ignore any collected
5363 // characters.
5364 while (position != end &&
5365 (mozilla::IsAsciiDigit(*position) || *position == '.')) {
5366 ++position;
5367 }
5368
5369 // 9. Let urlRecord be document's URL.
5370 nsCOMPtr<nsIURI> urlRecord(aDocument->GetDocumentURI());
5371
5372 // 10. If position is not past the end of input
5373 if (position != end) {
5374 // 1. If the code point in input pointed to by position is not U+003B (;),
5375 // U+002C (,), or ASCII whitespace, then return.
5376 if (*position != ';' && *position != ',' &&
5377 !mozilla::IsAsciiWhitespace(*position)) {
5378 return;
5379 }
5380
5381 // 2. Skip ASCII whitespace within input given position.
5382 position = SkipASCIIWhitespace(position, end);
5383
5384 // 3. If the code point in input pointed to by position is U+003B (;) or
5385 // U+002C (,), then advance position to the next code point.
5386 if (position != end && (*position == ';' || *position == ',')) {
5387 ++position;
5388
5389 // 4. Skip ASCII whitespace within input given position.
5390 position = SkipASCIIWhitespace(position, end);
5391 }
5392
5393 // 11. If position is not past the end of input, then:
5394 if (position != end) {
5395 const char16_t* urlStart;
5396 const char16_t* urlEnd;
5397
5398 // 1-10. See ExtractURLString.
5399 std::tie(urlStart, urlEnd) = ExtractURLString(position, end);
5400
5401 // 11. Parse: Parse urlString relative to document. If that fails, return.
5402 // Otherwise, set urlRecord to the resulting URL record.
5403 nsresult rv =
5404 NS_NewURI(getter_AddRefs(urlRecord),
5405 Substring(urlStart, std::distance(urlStart, urlEnd)),
5406 /* charset = */ nullptr, aDocument->GetDocBaseURI());
5407 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"
, 5407); return; } } while (false)
;
5408 }
5409 }
5410
5411 nsIPrincipal* principal = aDocument->NodePrincipal();
5412 nsCOMPtr<nsIScriptSecurityManager> securityManager =
5413 nsContentUtils::GetSecurityManager();
5414 nsresult rv = securityManager->CheckLoadURIWithPrincipal(
5415 principal, urlRecord,
5416 nsIScriptSecurityManager::LOAD_IS_AUTOMATIC_DOCUMENT_REPLACEMENT,
5417 aDocument->InnerWindowID());
5418 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"
, 5418); return; } } while (false)
;
5419
5420 bool isjs = true;
5421 rv = NS_URIChainHasFlags(
5422 urlRecord, nsIProtocolHandler::URI_OPENING_EXECUTES_SCRIPT, &isjs);
5423 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"
, 5423); return; } } while (false)
;
5424
5425 if (isjs) {
5426 return;
5427 }
5428
5429 RefreshURI(urlRecord, principal, milliSeconds.value());
5430}
5431
5432static void DoCancelRefreshURITimers(nsIMutableArray* aTimerList) {
5433 if (!aTimerList) {
5434 return;
5435 }
5436
5437 uint32_t n = 0;
5438 aTimerList->GetLength(&n);
5439
5440 while (n) {
5441 nsCOMPtr<nsITimer> timer(do_QueryElementAt(aTimerList, --n));
5442
5443 aTimerList->RemoveElementAt(n); // bye bye owning timer ref
5444
5445 if (timer) {
5446 timer->Cancel();
5447 }
5448 }
5449}
5450
5451NS_IMETHODIMPnsresult
5452nsDocShell::CancelRefreshURITimers() {
5453 DoCancelRefreshURITimers(mRefreshURIList);
5454 DoCancelRefreshURITimers(mSavedRefreshURIList);
5455 DoCancelRefreshURITimers(mBFCachedRefreshURIList);
5456 mRefreshURIList = nullptr;
5457 mSavedRefreshURIList = nullptr;
5458 mBFCachedRefreshURIList = nullptr;
5459
5460 return NS_OK;
5461}
5462
5463NS_IMETHODIMPnsresult
5464nsDocShell::GetRefreshPending(bool* aResult) {
5465 if (!mRefreshURIList) {
5466 *aResult = false;
5467 return NS_OK;
5468 }
5469
5470 uint32_t count;
5471 nsresult rv = mRefreshURIList->GetLength(&count);
5472 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
5473 *aResult = (count != 0);
5474 }
5475 return rv;
5476}
5477
5478void nsDocShell::RefreshURIToQueue() {
5479 if (mRefreshURIList) {
5480 uint32_t n = 0;
5481 mRefreshURIList->GetLength(&n);
5482
5483 for (uint32_t i = 0; i < n; ++i) {
5484 nsCOMPtr<nsITimer> timer = do_QueryElementAt(mRefreshURIList, i);
5485 if (!timer) {
5486 continue; // this must be a nsRefreshURI already
5487 }
5488
5489 // Replace this timer object with a nsRefreshTimer object.
5490 nsCOMPtr<nsITimerCallback> callback;
5491 timer->GetCallback(getter_AddRefs(callback));
5492
5493 timer->Cancel();
5494
5495 mRefreshURIList->ReplaceElementAt(callback, i);
5496 }
5497 }
5498}
5499
5500NS_IMETHODIMPnsresult
5501nsDocShell::SuspendRefreshURIs() {
5502 RefreshURIToQueue();
5503
5504 // Suspend refresh URIs for our child shells as well.
5505 for (auto* child : mChildList.ForwardRange()) {
5506 nsCOMPtr<nsIDocShell> shell = do_QueryObject(child);
5507 if (shell) {
5508 shell->SuspendRefreshURIs();
5509 }
5510 }
5511
5512 return NS_OK;
5513}
5514
5515NS_IMETHODIMPnsresult
5516nsDocShell::ResumeRefreshURIs() {
5517 RefreshURIFromQueue();
5518
5519 // Resume refresh URIs for our child shells as well.
5520 for (auto* child : mChildList.ForwardRange()) {
5521 nsCOMPtr<nsIDocShell> shell = do_QueryObject(child);
5522 if (shell) {
5523 shell->ResumeRefreshURIs();
5524 }
5525 }
5526
5527 return NS_OK;
5528}
5529
5530nsresult nsDocShell::RefreshURIFromQueue() {
5531 if (!mRefreshURIList) {
5532 return NS_OK;
5533 }
5534 uint32_t n = 0;
5535 mRefreshURIList->GetLength(&n);
5536
5537 while (n) {
5538 nsCOMPtr<nsITimerCallback> refreshInfo =
5539 do_QueryElementAt(mRefreshURIList, --n);
5540
5541 if (refreshInfo) {
5542 // This is the nsRefreshTimer object, waiting to be
5543 // setup in a timer object and fired.
5544 // Create the timer and trigger it.
5545 uint32_t delay = static_cast<nsRefreshTimer*>(
5546 static_cast<nsITimerCallback*>(refreshInfo))
5547 ->GetDelay();
5548 nsCOMPtr<nsPIDOMWindowOuter> win = GetWindow();
5549 if (win) {
5550 nsCOMPtr<nsITimer> timer;
5551 NS_NewTimerWithCallback(getter_AddRefs(timer), refreshInfo, delay,
5552 nsITimer::TYPE_ONE_SHOT);
5553
5554 if (timer) {
5555 // Replace the nsRefreshTimer element in the queue with
5556 // its corresponding timer object, so that in case another
5557 // load comes through before the timer can go off, the timer will
5558 // get cancelled in CancelRefreshURITimer()
5559 mRefreshURIList->ReplaceElementAt(timer, n);
5560 }
5561 }
5562 }
5563 }
5564
5565 return NS_OK;
5566}
5567
5568static bool IsFollowupPartOfMultipart(nsIRequest* aRequest) {
5569 nsCOMPtr<nsIMultiPartChannel> multiPartChannel = do_QueryInterface(aRequest);
5570 bool firstPart = false;
5571 return multiPartChannel &&
5572 NS_SUCCEEDED(multiPartChannel->GetIsFirstPart(&firstPart))((bool)(__builtin_expect(!!(!NS_FAILED_impl(multiPartChannel->
GetIsFirstPart(&firstPart))), 1)))
&&
5573 !firstPart;
5574}
5575
5576nsresult nsDocShell::Embed(nsIDocumentViewer* aDocumentViewer,
5577 WindowGlobalChild* aWindowActor,
5578 bool aIsTransientAboutBlank, bool aPersist,
5579 nsIRequest* aRequest, nsIURI* aPreviousURI) {
5580 // Save the LayoutHistoryState of the previous document, before
5581 // setting up new document
5582 PersistLayoutHistoryState();
5583
5584 nsresult rv = SetupNewViewer(aDocumentViewer, aWindowActor);
5585 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"
, 5585); return rv; } } while (false)
;
5586
5587 // XXX What if SetupNewViewer fails?
5588 if (mozilla::SessionHistoryInParent() ? !!mLoadingEntry : !!mLSHE) {
5589 // Set history.state
5590 SetDocCurrentStateObj(mLSHE,
5591 mLoadingEntry ? &mLoadingEntry->mInfo : nullptr);
5592 }
5593
5594 if (mLSHE) {
5595 // Restore the editing state, if it's stored in session history.
5596 if (mLSHE->HasDetachedEditor()) {
5597 ReattachEditorToWindow(mLSHE);
5598 }
5599
5600 SetHistoryEntryAndUpdateBC(Nothing(), Some<nsISHEntry*>(mLSHE));
5601 }
5602
5603 if (!aIsTransientAboutBlank && mozilla::SessionHistoryInParent() &&
5604 !IsFollowupPartOfMultipart(aRequest)) {
5605 bool expired = false;
5606 uint32_t cacheKey = 0;
5607 nsCOMPtr<nsICacheInfoChannel> cacheChannel = do_QueryInterface(aRequest);
5608 if (cacheChannel) {
5609 // Check if the page has expired from cache
5610 uint32_t expTime = 0;
5611 cacheChannel->GetCacheTokenExpirationTime(&expTime);
5612 uint32_t now = PRTimeToSeconds(PR_Now());
5613 if (expTime <= now) {
5614 expired = true;
5615 }
5616
5617 // The checks for updating cache key are similar to the old session
5618 // history in OnNewURI. Try to update the cache key if
5619 // - we should update session history and aren't doing a session
5620 // history load.
5621 // - we're doing a forced reload.
5622 if (((!mLoadingEntry || !mLoadingEntry->mLoadIsFromSessionHistory) &&
5623 mBrowsingContext->ShouldUpdateSessionHistory(mLoadType)) ||
5624 IsForceReloadType(mLoadType)) {
5625 cacheChannel->GetCacheKey(&cacheKey);
5626 }
5627 }
5628
5629 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)
;
5630 MoveLoadingToActiveEntry(aPersist, expired, cacheKey, aPreviousURI);
5631 }
5632
5633 bool updateHistory = true;
5634
5635 // Determine if this type of load should update history
5636 switch (mLoadType) {
5637 case LOAD_NORMAL_REPLACE:
5638 case LOAD_REFRESH_REPLACE:
5639 case LOAD_STOP_CONTENT_AND_REPLACE:
5640 case LOAD_RELOAD_BYPASS_CACHE:
5641 case LOAD_RELOAD_BYPASS_PROXY:
5642 case LOAD_RELOAD_BYPASS_PROXY_AND_CACHE:
5643 case LOAD_REPLACE_BYPASS_CACHE:
5644 updateHistory = false;
5645 break;
5646 default:
5647 break;
5648 }
5649
5650 if (!updateHistory) {
5651 SetLayoutHistoryState(nullptr);
5652 }
5653
5654 return NS_OK;
5655}
5656
5657//*****************************************************************************
5658// nsDocShell::nsIWebProgressListener
5659//*****************************************************************************
5660
5661NS_IMETHODIMPnsresult
5662nsDocShell::OnProgressChange(nsIWebProgress* aProgress, nsIRequest* aRequest,
5663 int32_t aCurSelfProgress, int32_t aMaxSelfProgress,
5664 int32_t aCurTotalProgress,
5665 int32_t aMaxTotalProgress) {
5666 return NS_OK;
5667}
5668
5669NS_IMETHODIMPnsresult
5670nsDocShell::OnStateChange(nsIWebProgress* aProgress, nsIRequest* aRequest,
5671 uint32_t aStateFlags, nsresult aStatus) {
5672 if ((~aStateFlags & (STATE_START | STATE_IS_NETWORK)) == 0) {
5673 // Save timing statistics.
5674 nsCOMPtr<nsIChannel> channel(do_QueryInterface(aRequest));
5675 nsCOMPtr<nsIURI> uri;
5676 channel->GetURI(getter_AddRefs(uri));
5677 nsAutoCString aURI;
5678 uri->GetAsciiSpec(aURI);
5679
5680 if (this == aProgress) {
5681 mozilla::Unused << MaybeInitTiming();
5682 mTiming->NotifyFetchStart(uri,
5683 ConvertLoadTypeToNavigationType(mLoadType));
5684 // If we are starting a DocumentChannel, we need to pass the timing
5685 // statistics so that should a process switch occur, the starting type can
5686 // be passed to the new DocShell running in the other content process.
5687 if (RefPtr<DocumentChannel> docChannel = do_QueryObject(aRequest)) {
5688 docChannel->SetNavigationTiming(mTiming);
5689 }
5690 }
5691
5692 // Page has begun to load
5693 mBusyFlags = (BusyFlags)(BUSY_FLAGS_BUSY | BUSY_FLAGS_BEFORE_PAGE_LOAD);
5694
5695 if ((aStateFlags & STATE_RESTORING) == 0) {
5696 if (StaticPrefs::browser_sessionstore_platform_collection_AtStartup()) {
5697 if (IsForceReloadType(mLoadType)) {
5698 if (WindowContext* windowContext =
5699 mBrowsingContext->GetCurrentWindowContext()) {
5700 SessionStoreChild::From(windowContext->GetWindowGlobalChild())
5701 ->ResetSessionStore(mBrowsingContext,
5702 mBrowsingContext->GetSessionStoreEpoch());
5703 }
5704 }
5705 }
5706 }
5707 } else if ((~aStateFlags & (STATE_TRANSFERRING | STATE_IS_DOCUMENT)) == 0) {
5708 // Page is loading
5709 mBusyFlags = (BusyFlags)(BUSY_FLAGS_BUSY | BUSY_FLAGS_PAGE_LOADING);
5710 } else if ((aStateFlags & STATE_STOP) && (aStateFlags & STATE_IS_NETWORK)) {
5711 // Page has finished loading
5712 mBusyFlags = BUSY_FLAGS_NONE;
5713 }
5714
5715 if ((~aStateFlags & (STATE_IS_DOCUMENT | STATE_STOP)) == 0) {
5716 nsCOMPtr<nsIWebProgress> webProgress =
5717 do_QueryInterface(GetAsSupports(this));
5718 // Is the document stop notification for this document?
5719 if (aProgress == webProgress.get()) {
5720 nsCOMPtr<nsIChannel> channel(do_QueryInterface(aRequest));
5721 EndPageLoad(aProgress, channel, aStatus);
5722 }
5723 }
5724 // note that redirect state changes will go through here as well, but it
5725 // is better to handle those in OnRedirectStateChange where more
5726 // information is available.
5727 return NS_OK;
5728}
5729
5730NS_IMETHODIMPnsresult
5731nsDocShell::OnLocationChange(nsIWebProgress* aProgress, nsIRequest* aRequest,
5732 nsIURI* aURI, uint32_t aFlags) {
5733 // Since we've now changed Documents, notify the BrowsingContext that we've
5734 // changed. Ideally we'd just let the BrowsingContext do this when it
5735 // changes the current window global, but that happens before this and we
5736 // have a lot of tests that depend on the specific ordering of messages.
5737 bool isTopLevel = false;
5738 if (XRE_IsParentProcess() &&
5739 !(aFlags & nsIWebProgressListener::LOCATION_CHANGE_SAME_DOCUMENT) &&
5740 NS_SUCCEEDED(aProgress->GetIsTopLevel(&isTopLevel))((bool)(__builtin_expect(!!(!NS_FAILED_impl(aProgress->GetIsTopLevel
(&isTopLevel))), 1)))
&& isTopLevel) {
5741 GetBrowsingContext()->Canonical()->UpdateSecurityState();
5742 }
5743 return NS_OK;
5744}
5745
5746void nsDocShell::OnRedirectStateChange(nsIChannel* aOldChannel,
5747 nsIChannel* aNewChannel,
5748 uint32_t aRedirectFlags,
5749 uint32_t aStateFlags) {
5750 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"
, 5751); MOZ_PretendNoReturn(); } } while (0)
5751 "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"
, 5751); MOZ_PretendNoReturn(); } } while (0)
;
5752
5753 if (!(aStateFlags & STATE_IS_DOCUMENT)) {
5754 return; // not a toplevel document
5755 }
5756
5757 nsCOMPtr<nsIURI> oldURI, newURI;
5758 aOldChannel->GetURI(getter_AddRefs(oldURI));
5759 aNewChannel->GetURI(getter_AddRefs(newURI));
5760 if (!oldURI || !newURI) {
5761 return;
5762 }
5763
5764 // DocumentChannel adds redirect chain to global history in the parent
5765 // process. The redirect chain can't be queried from the content process, so
5766 // there's no need to update global history here.
5767 RefPtr<DocumentChannel> docChannel = do_QueryObject(aOldChannel);
5768 if (!docChannel) {
5769 // Below a URI visit is saved (see AddURIVisit method doc).
5770 // The visit chain looks something like:
5771 // ...
5772 // Site N - 1
5773 // => Site N
5774 // (redirect to =>) Site N + 1 (we are here!)
5775
5776 // Get N - 1 and transition type
5777 nsCOMPtr<nsIURI> previousURI;
5778 uint32_t previousFlags = 0;
5779 ExtractLastVisit(aOldChannel, getter_AddRefs(previousURI), &previousFlags);
5780
5781 if (aRedirectFlags & nsIChannelEventSink::REDIRECT_INTERNAL ||
5782 net::ChannelIsPost(aOldChannel)) {
5783 // 1. Internal redirects are ignored because they are specific to the
5784 // channel implementation.
5785 // 2. POSTs are not saved by global history.
5786 //
5787 // Regardless, we need to propagate the previous visit to the new
5788 // channel.
5789 SaveLastVisit(aNewChannel, previousURI, previousFlags);
5790 } else {
5791 // Get the HTTP response code, if available.
5792 uint32_t responseStatus = 0;
5793 nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(aOldChannel);
5794 if (httpChannel) {
5795 Unused << httpChannel->GetResponseStatus(&responseStatus);
5796 }
5797
5798 // Add visit N -1 => N
5799 AddURIVisit(oldURI, previousURI, previousFlags, responseStatus);
5800
5801 // Since N + 1 could be the final destination, we will not save N => N + 1
5802 // here. OnNewURI will do that, so we will cache it.
5803 SaveLastVisit(aNewChannel, oldURI, aRedirectFlags);
5804 }
5805 }
5806
5807 if (!(aRedirectFlags & nsIChannelEventSink::REDIRECT_INTERNAL) &&
5808 mLoadType & (LOAD_CMD_RELOAD | LOAD_CMD_HISTORY)) {
5809 mLoadType = LOAD_NORMAL_REPLACE;
5810 SetHistoryEntryAndUpdateBC(Some(nullptr), Nothing());
5811 }
5812}
5813
5814NS_IMETHODIMPnsresult
5815nsDocShell::OnStatusChange(nsIWebProgress* aWebProgress, nsIRequest* aRequest,
5816 nsresult aStatus, const char16_t* aMessage) {
5817 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"
, 5817); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "notification excluded in AddProgressListener(...)"
")"); do { *((volatile int*)__null) = 5817; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5818 return NS_OK;
5819}
5820
5821NS_IMETHODIMPnsresult
5822nsDocShell::OnSecurityChange(nsIWebProgress* aWebProgress, nsIRequest* aRequest,
5823 uint32_t aState) {
5824 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"
, 5824); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "notification excluded in AddProgressListener(...)"
")"); do { *((volatile int*)__null) = 5824; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5825 return NS_OK;
5826}
5827
5828NS_IMETHODIMPnsresult
5829nsDocShell::OnContentBlockingEvent(nsIWebProgress* aWebProgress,
5830 nsIRequest* aRequest, uint32_t aEvent) {
5831 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"
, 5831); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "notification excluded in AddProgressListener(...)"
")"); do { *((volatile int*)__null) = 5831; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5832 return NS_OK;
5833}
5834
5835already_AddRefed<nsIURIFixupInfo> nsDocShell::KeywordToURI(
5836 const nsACString& aKeyword, bool aIsPrivateContext) {
5837 nsCOMPtr<nsIURIFixupInfo> info;
5838 if (!XRE_IsContentProcess()) {
5839 nsCOMPtr<nsIURIFixup> uriFixup = components::URIFixup::Service();
5840 if (uriFixup) {
5841 uriFixup->KeywordToURI(aKeyword, aIsPrivateContext, getter_AddRefs(info));
5842 }
5843 }
5844 return info.forget();
5845}
5846
5847/* static */
5848already_AddRefed<nsIURI> nsDocShell::MaybeFixBadCertDomainErrorURI(
5849 nsIChannel* aChannel, nsIURI* aUrl) {
5850 if (!aChannel) {
5851 return nullptr;
5852 }
5853
5854 nsresult rv = NS_OK;
5855 nsAutoCString host;
5856 rv = aUrl->GetAsciiHost(host);
5857 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"
, 5857)
) {
5858 return nullptr;
5859 }
5860
5861 // No point in going further if "www." is included in the hostname
5862 // already. That is the only hueristic we're applying in this function.
5863 if (StringBeginsWith(host, "www."_ns)) {
5864 return nullptr;
5865 }
5866
5867 // Return if fixup enable pref is turned off.
5868 if (!mozilla::StaticPrefs::security_bad_cert_domain_error_url_fix_enabled()) {
5869 return nullptr;
5870 }
5871
5872 // Return if scheme is not HTTPS.
5873 if (!SchemeIsHTTPS(aUrl)) {
5874 return nullptr;
5875 }
5876
5877 nsCOMPtr<nsILoadInfo> info = aChannel->LoadInfo();
5878 if (!info) {
5879 return nullptr;
5880 }
5881
5882 // Skip doing the fixup if our channel was redirected, because we
5883 // shouldn't be guessing things about the post-redirect URI.
5884 if (!info->RedirectChain().IsEmpty()) {
5885 return nullptr;
5886 }
5887
5888 int32_t port = 0;
5889 rv = aUrl->GetPort(&port);
5890 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"
, 5890)
) {
5891 return nullptr;
5892 }
5893
5894 // Don't fix up hosts with ports.
5895 if (port != -1) {
5896 return nullptr;
5897 }
5898
5899 // Don't fix up localhost url.
5900 if (host == "localhost") {
5901 return nullptr;
5902 }
5903
5904 // Don't fix up hostnames with IP address.
5905 if (net_IsValidIPv4Addr(host) || net_IsValidIPv6Addr(host)) {
5906 return nullptr;
5907 }
5908
5909 nsAutoCString userPass;
5910 rv = aUrl->GetUserPass(userPass);
5911 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"
, 5911)
) {
5912 return nullptr;
5913 }
5914
5915 // Security - URLs with user / password info should NOT be modified.
5916 if (!userPass.IsEmpty()) {
5917 return nullptr;
5918 }
5919
5920 nsCOMPtr<nsITransportSecurityInfo> tsi;
5921 rv = aChannel->GetSecurityInfo(getter_AddRefs(tsi));
5922 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"
, 5922)
) {
5923 return nullptr;
5924 }
5925
5926 if (NS_WARN_IF(!tsi)NS_warn_if_impl(!tsi, "!tsi", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 5926)
) {
5927 return nullptr;
5928 }
5929
5930 nsCOMPtr<nsIX509Cert> cert;
5931 rv = tsi->GetServerCert(getter_AddRefs(cert));
5932 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"
, 5932)
) {
5933 return nullptr;
5934 }
5935
5936 nsTArray<uint8_t> certBytes;
5937 rv = cert->GetRawDER(certBytes);
5938 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
5939 return nullptr;
5940 }
5941
5942 mozilla::pkix::Input serverCertInput;
5943 mozilla::pkix::Result rv1 =
5944 serverCertInput.Init(certBytes.Elements(), certBytes.Length());
5945 if (rv1 != mozilla::pkix::Success) {
5946 return nullptr;
5947 }
5948
5949 nsAutoCString newHost("www."_ns);
5950 newHost.Append(host);
5951
5952 mozilla::pkix::Input newHostInput;
5953 rv1 = newHostInput.Init(
5954 BitwiseCast<const uint8_t*, const char*>(newHost.BeginReading()),
5955 newHost.Length());
5956 if (rv1 != mozilla::pkix::Success) {
5957 return nullptr;
5958 }
5959
5960 // Check if adding a "www." prefix to the request's hostname will
5961 // cause the response's certificate to match.
5962 rv1 = mozilla::pkix::CheckCertHostname(serverCertInput, newHostInput);
5963 if (rv1 != mozilla::pkix::Success) {
5964 return nullptr;
5965 }
5966
5967 nsCOMPtr<nsIURI> newURI;
5968 Unused << NS_MutateURI(aUrl).SetHost(newHost).Finalize(
5969 getter_AddRefs(newURI));
5970
5971 return newURI.forget();
5972}
5973
5974/* static */
5975already_AddRefed<nsIURI> nsDocShell::AttemptURIFixup(
5976 nsIChannel* aChannel, nsresult aStatus,
5977 const mozilla::Maybe<nsCString>& aOriginalURIString, uint32_t aLoadType,
5978 bool aIsTopFrame, bool aAllowKeywordFixup, bool aUsePrivateBrowsing,
5979 bool aNotifyKeywordSearchLoading, nsIInputStream** aNewPostData,
5980 bool* outWasSchemelessInput) {
5981 if (aStatus != NS_ERROR_UNKNOWN_HOST && aStatus != NS_ERROR_NET_RESET &&
5982 aStatus != NS_ERROR_CONNECTION_REFUSED &&
5983 aStatus !=
5984 mozilla::psm::GetXPCOMFromNSSError(SSL_ERROR_BAD_CERT_DOMAIN)) {
5985 return nullptr;
5986 }
5987
5988 if (!(aLoadType == LOAD_NORMAL && aIsTopFrame) && !aAllowKeywordFixup) {
5989 return nullptr;
5990 }
5991
5992 nsCOMPtr<nsIURI> url;
5993 nsresult rv = aChannel->GetURI(getter_AddRefs(url));
5994 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
5995 return nullptr;
5996 }
5997
5998 //
5999 // Try and make an alternative URI from the old one
6000 //
6001 nsCOMPtr<nsIURI> newURI;
6002 nsCOMPtr<nsIInputStream> newPostData;
6003
6004 nsAutoCString oldSpec;
6005 url->GetSpec(oldSpec);
6006
6007 //
6008 // First try keyword fixup
6009 //
6010 nsAutoString keywordProviderName, keywordAsSent;
6011 if (aStatus == NS_ERROR_UNKNOWN_HOST && aAllowKeywordFixup) {
6012 // we should only perform a keyword search under the following
6013 // conditions:
6014 // (0) Pref keyword.enabled is true
6015 // (1) the url scheme is http (or https)
6016 // (2) the url does not have a protocol scheme
6017 // If we don't enforce such a policy, then we end up doing
6018 // keyword searchs on urls we don't intend like imap, file,
6019 // mailbox, etc. This could lead to a security problem where we
6020 // send data to the keyword server that we shouldn't be.
6021 // Someone needs to clean up keywords in general so we can
6022 // determine on a per url basis if we want keywords
6023 // enabled...this is just a bandaid...
6024 nsAutoCString scheme;
6025 Unused << url->GetScheme(scheme);
6026 if (Preferences::GetBool("keyword.enabled", false) &&
6027 StringBeginsWith(scheme, "http"_ns)) {
6028 bool attemptFixup = false;
6029 nsAutoCString host;
6030 Unused << url->GetHost(host);
6031 if (host.FindChar('.') == kNotFound) {
6032 attemptFixup = true;
6033 } else {
6034 // For domains with dots, we check the public suffix validity.
6035 nsCOMPtr<nsIEffectiveTLDService> tldService =
6036 do_GetService(NS_EFFECTIVETLDSERVICE_CONTRACTID"@mozilla.org/network/effective-tld-service;1");
6037 if (tldService) {
6038 nsAutoCString suffix;
6039 attemptFixup =
6040 NS_SUCCEEDED(tldService->GetKnownPublicSuffix(url, suffix))((bool)(__builtin_expect(!!(!NS_FAILED_impl(tldService->GetKnownPublicSuffix
(url, suffix))), 1)))
&&
6041 suffix.IsEmpty();
6042 }
6043 }
6044 if (attemptFixup) {
6045 nsCOMPtr<nsIURIFixupInfo> info;
6046 // only send non-qualified hosts to the keyword server
6047 if (aOriginalURIString && !aOriginalURIString->IsEmpty()) {
6048 info = KeywordToURI(*aOriginalURIString, aUsePrivateBrowsing);
6049 } else {
6050 //
6051 // If this string was passed through nsStandardURL by
6052 // chance, then it may have been converted from UTF-8 to
6053 // ACE, which would result in a completely bogus keyword
6054 // query. Here we try to recover the original Unicode
6055 // value, but this is not 100% correct since the value may
6056 // have been normalized per the IDN normalization rules.
6057 //
6058 // Since we don't have access to the exact original string
6059 // that was entered by the user, this will just have to do.
6060 bool isACE;
6061 nsAutoCString utf8Host;
6062 nsCOMPtr<nsIIDNService> idnSrv =
6063 do_GetService(NS_IDNSERVICE_CONTRACTID"@mozilla.org/network/idn-service;1");
6064 if (idnSrv && NS_SUCCEEDED(idnSrv->IsACE(host, &isACE))((bool)(__builtin_expect(!!(!NS_FAILED_impl(idnSrv->IsACE(
host, &isACE))), 1)))
&& isACE &&
6065 NS_SUCCEEDED(idnSrv->ConvertACEtoUTF8(host, utf8Host))((bool)(__builtin_expect(!!(!NS_FAILED_impl(idnSrv->ConvertACEtoUTF8
(host, utf8Host))), 1)))
) {
6066 info = KeywordToURI(utf8Host, aUsePrivateBrowsing);
6067
6068 } else {
6069 info = KeywordToURI(host, aUsePrivateBrowsing);
6070 }
6071 }
6072 if (info) {
6073 info->GetPreferredURI(getter_AddRefs(newURI));
6074 info->GetWasSchemelessInput(outWasSchemelessInput);
6075 if (newURI) {
6076 info->GetKeywordAsSent(keywordAsSent);
6077 info->GetKeywordProviderName(keywordProviderName);
6078 info->GetPostData(getter_AddRefs(newPostData));
6079 }
6080 }
6081 }
6082 }
6083 }
6084
6085 //
6086 // Now try change the address, e.g. turn http://foo into
6087 // http://www.foo.com, and if that doesn't work try https with
6088 // https://foo and https://www.foo.com.
6089 //
6090 if (aStatus == NS_ERROR_UNKNOWN_HOST || aStatus == NS_ERROR_NET_RESET) {
6091 // Skip fixup for anything except a normal document load
6092 // operation on the topframe.
6093 bool doCreateAlternate = aLoadType == LOAD_NORMAL && aIsTopFrame;
6094
6095 if (doCreateAlternate) {
6096 nsCOMPtr<nsILoadInfo> loadInfo = aChannel->LoadInfo();
6097 nsIPrincipal* principal = loadInfo->TriggeringPrincipal();
6098 // Only do this if our channel was loaded directly by the user from the
6099 // URL bar or similar (system principal) and not redirected, because we
6100 // shouldn't be guessing things about links from other sites, or a
6101 // post-redirect URI.
6102 doCreateAlternate = principal && principal->IsSystemPrincipal() &&
6103 loadInfo->RedirectChain().IsEmpty();
6104 }
6105 // Test if keyword lookup produced a new URI or not
6106 if (doCreateAlternate && newURI) {
6107 bool sameURI = false;
6108 url->Equals(newURI, &sameURI);
6109 if (!sameURI) {
6110 // Keyword lookup made a new URI so no need to try
6111 // an alternate one.
6112 doCreateAlternate = false;
6113 }
6114 }
6115 if (doCreateAlternate) {
6116 newURI = nullptr;
6117 newPostData = nullptr;
6118 keywordProviderName.Truncate();
6119 keywordAsSent.Truncate();
6120 nsCOMPtr<nsIURIFixup> uriFixup = components::URIFixup::Service();
6121 if (uriFixup) {
6122 nsCOMPtr<nsIURIFixupInfo> fixupInfo;
6123 uriFixup->GetFixupURIInfo(oldSpec, nsIURIFixup::FIXUP_FLAG_NONE,
6124 getter_AddRefs(fixupInfo));
6125 if (fixupInfo) {
6126 fixupInfo->GetPreferredURI(getter_AddRefs(newURI));
6127 }
6128 }
6129 }
6130 } else if (aStatus == NS_ERROR_CONNECTION_REFUSED &&
6131 Preferences::GetBool("browser.fixup.fallback-to-https", false)) {
6132 // Try HTTPS, since http didn't work
6133 if (SchemeIsHTTP(url)) {
6134 int32_t port = 0;
6135 url->GetPort(&port);
6136
6137 // Fall back to HTTPS only if port is default
6138 if (port == -1) {
6139 newURI = nullptr;
6140 newPostData = nullptr;
6141 Unused << NS_MutateURI(url)
6142 .SetScheme("https"_ns)
6143 .Finalize(getter_AddRefs(newURI));
6144 }
6145 }
6146 }
6147
6148 // If we have a SSL_ERROR_BAD_CERT_DOMAIN error, try prefixing the domain name
6149 // with www. to see if we can avoid showing the cert error page. For example,
6150 // https://example.com -> https://www.example.com.
6151 if (aStatus ==
6152 mozilla::psm::GetXPCOMFromNSSError(SSL_ERROR_BAD_CERT_DOMAIN)) {
6153 newPostData = nullptr;
6154 newURI = MaybeFixBadCertDomainErrorURI(aChannel, url);
6155 }
6156
6157 // Did we make a new URI that is different to the old one? If so
6158 // load it.
6159 //
6160 if (newURI) {
6161 // Make sure the new URI is different from the old one,
6162 // otherwise there's little point trying to load it again.
6163 bool sameURI = false;
6164 url->Equals(newURI, &sameURI);
6165 if (!sameURI) {
6166 if (aNewPostData) {
6167 newPostData.forget(aNewPostData);
6168 }
6169 if (aNotifyKeywordSearchLoading) {
6170 // This notification is meant for Firefox Health Report so it
6171 // can increment counts from the search engine
6172 MaybeNotifyKeywordSearchLoading(keywordProviderName, keywordAsSent);
6173 }
6174 return newURI.forget();
6175 }
6176 }
6177
6178 return nullptr;
6179}
6180
6181nsresult nsDocShell::FilterStatusForErrorPage(
6182 nsresult aStatus, nsIChannel* aChannel, uint32_t aLoadType,
6183 bool aIsTopFrame, bool aUseErrorPages, bool aIsInitialDocument,
6184 bool* aSkippedUnknownProtocolNavigation) {
6185 // Errors to be shown only on top-level frames
6186 if ((aStatus == NS_ERROR_UNKNOWN_HOST ||
6187 aStatus == NS_ERROR_CONNECTION_REFUSED ||
6188 aStatus == NS_ERROR_UNKNOWN_PROXY_HOST ||
6189 aStatus == NS_ERROR_PROXY_CONNECTION_REFUSED ||
6190 aStatus == NS_ERROR_PROXY_FORBIDDEN ||
6191 aStatus == NS_ERROR_PROXY_NOT_IMPLEMENTED ||
6192 aStatus == NS_ERROR_PROXY_AUTHENTICATION_FAILED ||
6193 aStatus == NS_ERROR_PROXY_TOO_MANY_REQUESTS ||
6194 aStatus == NS_ERROR_MALFORMED_URI ||
6195 aStatus == NS_ERROR_BLOCKED_BY_POLICY ||
6196 aStatus == NS_ERROR_DOM_COOP_FAILED ||
6197 aStatus == NS_ERROR_DOM_COEP_FAILED) &&
6198 (aIsTopFrame || aUseErrorPages)) {
6199 return aStatus;
6200 }
6201
6202 if (aStatus == NS_ERROR_NET_TIMEOUT ||
6203 aStatus == NS_ERROR_NET_TIMEOUT_EXTERNAL ||
6204 aStatus == NS_ERROR_PROXY_GATEWAY_TIMEOUT ||
6205 aStatus == NS_ERROR_REDIRECT_LOOP ||
6206 aStatus == NS_ERROR_UNKNOWN_SOCKET_TYPE ||
6207 aStatus == NS_ERROR_NET_INTERRUPT || aStatus == NS_ERROR_NET_RESET ||
6208 aStatus == NS_ERROR_PROXY_BAD_GATEWAY || aStatus == NS_ERROR_OFFLINE ||
6209 aStatus == NS_ERROR_MALWARE_URI || aStatus == NS_ERROR_PHISHING_URI ||
6210 aStatus == NS_ERROR_UNWANTED_URI || aStatus == NS_ERROR_HARMFUL_URI ||
6211 aStatus == NS_ERROR_UNSAFE_CONTENT_TYPE ||
6212 aStatus == NS_ERROR_INTERCEPTION_FAILED ||
6213 aStatus == NS_ERROR_NET_INADEQUATE_SECURITY ||
6214 aStatus == NS_ERROR_NET_HTTP2_SENT_GOAWAY ||
6215 aStatus == NS_ERROR_NET_HTTP3_PROTOCOL_ERROR ||
6216 aStatus == NS_ERROR_DOM_BAD_URI || aStatus == NS_ERROR_FILE_NOT_FOUND ||
6217 aStatus == NS_ERROR_FILE_ACCESS_DENIED ||
6218 aStatus == NS_ERROR_CORRUPTED_CONTENT ||
6219 aStatus == NS_ERROR_INVALID_CONTENT_ENCODING ||
6220 NS_ERROR_GET_MODULE(aStatus) == NS_ERROR_MODULE_SECURITY21) {
6221 // Errors to be shown for any frame
6222 return aStatus;
6223 }
6224
6225 if (aStatus == NS_ERROR_UNKNOWN_PROTOCOL) {
6226 // For unknown protocols we only display an error if the load is triggered
6227 // by the browser itself, or we're replacing the initial document (and
6228 // nothing else). Showing the error for page-triggered navigations causes
6229 // annoying behavior for users, see bug 1528305.
6230 //
6231 // We could, maybe, try to detect if this is in response to some user
6232 // interaction (like clicking a link, or something else) and maybe show
6233 // the error page in that case. But this allows for ctrl+clicking and such
6234 // to see the error page.
6235 nsCOMPtr<nsILoadInfo> info = aChannel->LoadInfo();
6236 if (!info->TriggeringPrincipal()->IsSystemPrincipal() &&
6237 StaticPrefs::dom_no_unknown_protocol_error_enabled() &&
6238 !aIsInitialDocument) {
6239 if (aSkippedUnknownProtocolNavigation) {
6240 *aSkippedUnknownProtocolNavigation = true;
6241 }
6242 return NS_OK;
6243 }
6244 return aStatus;
6245 }
6246
6247 if (aStatus == NS_ERROR_DOCUMENT_NOT_CACHED) {
6248 // Non-caching channels will simply return NS_ERROR_OFFLINE.
6249 // Caching channels would have to look at their flags to work
6250 // out which error to return. Or we can fix up the error here.
6251 if (!(aLoadType & LOAD_CMD_HISTORY)) {
6252 return NS_ERROR_OFFLINE;
6253 }
6254 return aStatus;
6255 }
6256
6257 return NS_OK;
6258}
6259
6260nsresult nsDocShell::EndPageLoad(nsIWebProgress* aProgress,
6261 nsIChannel* aChannel, nsresult aStatus) {
6262 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)
6263 ("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)
6264 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)
;
6265 if (!aChannel) {
6266 return NS_ERROR_NULL_POINTER;
6267 }
6268
6269 // Make sure to discard the initial client if we never created the initial
6270 // about:blank document. Do this before possibly returning from the method
6271 // due to an error.
6272 mInitialClientSource.reset();
6273
6274 nsCOMPtr<nsIConsoleReportCollector> reporter = do_QueryInterface(aChannel);
6275 if (reporter) {
6276 nsCOMPtr<nsILoadGroup> loadGroup;
6277 aChannel->GetLoadGroup(getter_AddRefs(loadGroup));
6278 if (loadGroup) {
6279 reporter->FlushConsoleReports(loadGroup);
6280 } else {
6281 reporter->FlushConsoleReports(GetDocument());
6282 }
6283 }
6284
6285 nsCOMPtr<nsIURI> url;
6286 nsresult rv = aChannel->GetURI(getter_AddRefs(url));
6287 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
6288 return rv;
6289 }
6290
6291 nsCOMPtr<nsITimedChannel> timingChannel = do_QueryInterface(aChannel);
6292 if (timingChannel) {
6293 TimeStamp channelCreationTime;
6294 rv = timingChannel->GetChannelCreation(&channelCreationTime);
6295 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && !channelCreationTime.IsNull()) {
6296 Telemetry::AccumulateTimeDelta(Telemetry::TOTAL_CONTENT_PAGE_LOAD_TIME,
6297 channelCreationTime);
6298 }
6299 }
6300
6301 // Timing is picked up by the window, we don't need it anymore
6302 mTiming = nullptr;
6303
6304 // clean up reload state for meta charset
6305 if (eCharsetReloadRequested == mCharsetReloadState) {
6306 mCharsetReloadState = eCharsetReloadStopOrigional;
6307 } else {
6308 mCharsetReloadState = eCharsetReloadInit;
6309 }
6310
6311 // Save a pointer to the currently-loading history entry.
6312 // nsDocShell::EndPageLoad will clear mLSHE, but we may need this history
6313 // entry further down in this method.
6314 nsCOMPtr<nsISHEntry> loadingSHE = mLSHE;
6315 mozilla::Unused << loadingSHE; // XXX: Not sure if we need this anymore
6316
6317 //
6318 // one of many safeguards that prevent death and destruction if
6319 // someone is so very very rude as to bring this window down
6320 // during this load handler.
6321 //
6322 nsCOMPtr<nsIDocShell> kungFuDeathGrip(this);
6323
6324 // Notify the DocumentViewer that the Document has finished loading. This
6325 // will cause any OnLoad(...) and PopState(...) handlers to fire.
6326 if (!mEODForCurrentDocument && mDocumentViewer) {
6327 mIsExecutingOnLoadHandler = true;
6328 nsCOMPtr<nsIDocumentViewer> viewer = mDocumentViewer;
6329 viewer->LoadComplete(aStatus);
6330 mIsExecutingOnLoadHandler = false;
6331
6332 mEODForCurrentDocument = true;
6333 }
6334 /* Check if the httpChannel has any cache-control related response headers,
6335 * like no-store, no-cache. If so, update SHEntry so that
6336 * when a user goes back/forward to this page, we appropriately do
6337 * form value restoration or load from server.
6338 */
6339 nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(aChannel));
6340 if (!httpChannel) {
6341 // HttpChannel could be hiding underneath a Multipart channel.
6342 GetHttpChannel(aChannel, getter_AddRefs(httpChannel));
6343 }
6344
6345 if (httpChannel) {
6346 // figure out if SH should be saving layout state.
6347 bool discardLayoutState = ShouldDiscardLayoutState(httpChannel);
6348 if (mLSHE && discardLayoutState && (mLoadType & LOAD_CMD_NORMAL) &&
6349 (mLoadType != LOAD_BYPASS_HISTORY) && (mLoadType != LOAD_ERROR_PAGE)) {
6350 mLSHE->SetSaveLayoutStateFlag(false);
6351 }
6352 }
6353
6354 // Clear mLSHE after calling the onLoadHandlers. This way, if the
6355 // onLoadHandler tries to load something different in
6356 // itself or one of its children, we can deal with it appropriately.
6357 if (mLSHE) {
6358 mLSHE->SetLoadType(LOAD_HISTORY);
6359
6360 // Clear the mLSHE reference to indicate document loading is done one
6361 // way or another.
6362 SetHistoryEntryAndUpdateBC(Some(nullptr), Nothing());
6363 }
6364 mActiveEntryIsLoadingFromSessionHistory = false;
6365
6366 // if there's a refresh header in the channel, this method
6367 // will set it up for us.
6368 if (mBrowsingContext->IsActive() || !mDisableMetaRefreshWhenInactive)
6369 RefreshURIFromQueue();
6370
6371 // Test whether this is the top frame or a subframe
6372 bool isTopFrame = mBrowsingContext->IsTop();
6373
6374 bool hadErrorStatus = false;
6375 // If status code indicates an error it means that DocumentChannel already
6376 // tried to fixup the uri and failed. Throw an error dialog box here.
6377 if (NS_FAILED(aStatus)((bool)(__builtin_expect(!!(NS_FAILED_impl(aStatus)), 0)))) {
6378 // If we got CONTENT_BLOCKED from EndPageLoad, then we need to fire
6379 // the error event to our embedder, since tests are relying on this.
6380 // The error event is usually fired by the caller of InternalLoad, but
6381 // this particular error can happen asynchronously.
6382 // Bug 1629201 is filed for having much clearer decision making around
6383 // which cases need error events.
6384 bool fireFrameErrorEvent = (aStatus == NS_ERROR_CONTENT_BLOCKED_SHOW_ALT ||
6385 aStatus == NS_ERROR_CONTENT_BLOCKED);
6386 UnblockEmbedderLoadEventForFailure(fireFrameErrorEvent);
6387
6388 bool isInitialDocument =
6389 !GetExtantDocument() || GetExtantDocument()->IsInitialDocument();
6390 bool skippedUnknownProtocolNavigation = false;
6391 aStatus = FilterStatusForErrorPage(aStatus, aChannel, mLoadType, isTopFrame,
6392 mBrowsingContext->GetUseErrorPages(),
6393 isInitialDocument,
6394 &skippedUnknownProtocolNavigation);
6395 hadErrorStatus = true;
6396 if (NS_FAILED(aStatus)((bool)(__builtin_expect(!!(NS_FAILED_impl(aStatus)), 0)))) {
6397 if (!mIsBeingDestroyed) {
6398 DisplayLoadError(aStatus, url, nullptr, aChannel);
6399 }
6400 } else if (skippedUnknownProtocolNavigation) {
6401 nsTArray<nsString> params;
6402 if (NS_FAILED(((bool)(__builtin_expect(!!(NS_FAILED_impl(NS_GetSanitizedURIStringFromURI
(url, *params.AppendElement()))), 0)))
6403 NS_GetSanitizedURIStringFromURI(url, *params.AppendElement()))((bool)(__builtin_expect(!!(NS_FAILED_impl(NS_GetSanitizedURIStringFromURI
(url, *params.AppendElement()))), 0)))
) {
6404 params.LastElement().AssignLiteral(u"(unknown uri)");
6405 }
6406 nsContentUtils::ReportToConsole(
6407 nsIScriptError::warningFlag, "DOM"_ns, GetExtantDocument(),
6408 nsContentUtils::eDOM_PROPERTIES, "UnknownProtocolNavigationPrevented",
6409 params);
6410 }
6411 } else {
6412 // If we have a host
6413 nsCOMPtr<nsILoadInfo> loadInfo = aChannel->LoadInfo();
6414 PredictorLearnRedirect(url, aChannel, loadInfo->GetOriginAttributes());
6415 }
6416
6417 if (hadErrorStatus) {
6418 // Don't send session store updates if the reason EndPageLoad was called is
6419 // because we are process switching. Sometimes the update takes too long and
6420 // incorrectly overrides session store data from the following load.
6421 return NS_OK;
6422 }
6423 if (StaticPrefs::browser_sessionstore_platform_collection_AtStartup()) {
6424 if (WindowContext* windowContext =
6425 mBrowsingContext->GetCurrentWindowContext()) {
6426 using Change = SessionStoreChangeListener::Change;
6427
6428 // We've finished loading the page and now we want to collect all the
6429 // session store state that the page is initialized with.
6430 SessionStoreChangeListener::CollectSessionStoreData(
6431 windowContext,
6432 EnumSet<Change>(Change::Input, Change::Scroll, Change::SessionHistory,
6433 Change::WireFrame));
6434 }
6435 }
6436
6437 return NS_OK;
6438}
6439
6440//*****************************************************************************
6441// nsDocShell: Content Viewer Management
6442//*****************************************************************************
6443
6444nsresult nsDocShell::EnsureDocumentViewer() {
6445 if (mDocumentViewer) {
6446 return NS_OK;
6447 }
6448 if (mIsBeingDestroyed) {
6449 return NS_ERROR_FAILURE;
6450 }
6451
6452 nsCOMPtr<nsIContentSecurityPolicy> cspToInheritForAboutBlank;
6453 nsCOMPtr<nsIURI> baseURI;
6454 nsIPrincipal* principal = GetInheritedPrincipal(false);
6455 nsIPrincipal* partitionedPrincipal = GetInheritedPrincipal(false, true);
6456
6457 nsCOMPtr<nsIDocShellTreeItem> parentItem;
6458 GetInProcessSameTypeParent(getter_AddRefs(parentItem));
6459 if (parentItem) {
6460 if (nsCOMPtr<nsPIDOMWindowOuter> domWin = GetWindow()) {
6461 nsCOMPtr<Element> parentElement = domWin->GetFrameElementInternal();
6462 if (parentElement) {
6463 baseURI = parentElement->GetBaseURI();
6464 cspToInheritForAboutBlank = parentElement->GetCsp();
6465 }
6466 }
6467 }
6468
6469 nsresult rv = CreateAboutBlankDocumentViewer(
6470 principal, partitionedPrincipal, cspToInheritForAboutBlank, baseURI,
6471 /* aIsInitialDocument */ true);
6472
6473 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"
, 6473); return NS_ERROR_UNEXPECTED; } } while (false)
;
6474
6475 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
6476 RefPtr<Document> doc(GetDocument());
6477 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"
, 6479); AnnotateMozCrashReason("MOZ_ASSERT" "(" "doc" ") (" "Should have doc if CreateAboutBlankDocumentViewer "
"succeeded!" ")"); do { *((volatile int*)__null) = 6479; __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
6478 "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"
, 6479); AnnotateMozCrashReason("MOZ_ASSERT" "(" "doc" ") (" "Should have doc if CreateAboutBlankDocumentViewer "
"succeeded!" ")"); do { *((volatile int*)__null) = 6479; __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
6479 "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"
, 6479); AnnotateMozCrashReason("MOZ_ASSERT" "(" "doc" ") (" "Should have doc if CreateAboutBlankDocumentViewer "
"succeeded!" ")"); do { *((volatile int*)__null) = 6479; __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
;
6480 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"
, 6480); AnnotateMozCrashReason("MOZ_ASSERT" "(" "doc->IsInitialDocument()"
") (" "Document should be initial document" ")"); do { *((volatile
int*)__null) = 6480; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
6481
6482 // Documents created using EnsureDocumentViewer may be transient
6483 // placeholders created by framescripts before content has a
6484 // chance to load. In some cases, window.open(..., "noopener")
6485 // will create such a document and then synchronously tear it
6486 // down, firing a "pagehide" event. Doing so violates our
6487 // assertions about DocGroups. It's easier to silence the
6488 // assertion here than to avoid creating the extra document.
6489 doc->IgnoreDocGroupMismatches();
6490 }
6491
6492 return rv;
6493}
6494
6495nsresult nsDocShell::CreateAboutBlankDocumentViewer(
6496 nsIPrincipal* aPrincipal, nsIPrincipal* aPartitionedPrincipal,
6497 nsIContentSecurityPolicy* aCSP, nsIURI* aBaseURI, bool aIsInitialDocument,
6498 const Maybe<nsILoadInfo::CrossOriginEmbedderPolicy>& aCOEP,
6499 bool aTryToSaveOldPresentation, bool aCheckPermitUnload,
6500 WindowGlobalChild* aActor) {
6501 RefPtr<Document> blankDoc;
6502 nsCOMPtr<nsIDocumentViewer> viewer;
6503 nsresult rv = NS_ERROR_FAILURE;
6504
6505 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"
, 6505); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aActor->DocumentPrincipal() == aPrincipal"
")"); do { *((volatile int*)__null) = 6505; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
6506
6507 /* mCreatingDocument should never be true at this point. However, it's
6508 a theoretical possibility. We want to know about it and make it stop,
6509 and this sounds like a job for an assertion. */
6510 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"
, 6511); MOZ_PretendNoReturn(); } } while (0)
6511 "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"
, 6511); MOZ_PretendNoReturn(); } } while (0)
;
6512 if (mCreatingDocument) {
6513 return NS_ERROR_FAILURE;
6514 }
6515
6516 if (!mBrowsingContext->AncestorsAreCurrent() ||
6517 mBrowsingContext->IsInBFCache()) {
6518 mBrowsingContext->RemoveRootFromBFCacheSync();
6519 return NS_ERROR_NOT_AVAILABLE;
6520 }
6521
6522 // mDocumentViewer->PermitUnload may release |this| docshell.
6523 nsCOMPtr<nsIDocShell> kungFuDeathGrip(this);
6524
6525 AutoRestore<bool> creatingDocument(mCreatingDocument);
6526 mCreatingDocument = true;
6527
6528 if (aPrincipal && !aPrincipal->IsSystemPrincipal() &&
6529 mItemType != typeChrome) {
6530 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"
, 6531); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPrincipal->OriginAttributesRef() == mBrowsingContext->OriginAttributesRef()"
")"); do { *((volatile int*)__null) = 6531; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6531 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"
, 6531); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPrincipal->OriginAttributesRef() == mBrowsingContext->OriginAttributesRef()"
")"); do { *((volatile int*)__null) = 6531; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6532 }
6533
6534 // Make sure timing is created. But first record whether we had it
6535 // already, so we don't clobber the timing for an in-progress load.
6536 bool hadTiming = mTiming;
6537 bool toBeReset = MaybeInitTiming();
6538 if (mDocumentViewer) {
6539 if (aCheckPermitUnload) {
6540 // We've got a content viewer already. Make sure the user
6541 // permits us to discard the current document and replace it
6542 // with about:blank. And also ensure we fire the unload events
6543 // in the current document.
6544
6545 // Unload gets fired first for
6546 // document loaded from the session history.
6547 mTiming->NotifyBeforeUnload();
6548
6549 bool okToUnload;
6550 rv = mDocumentViewer->PermitUnload(&okToUnload);
6551
6552 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && !okToUnload) {
6553 // The user chose not to unload the page, interrupt the load.
6554 MaybeResetInitTiming(toBeReset);
6555 return NS_ERROR_FAILURE;
6556 }
6557 if (mTiming) {
6558 mTiming->NotifyUnloadAccepted(mCurrentURI);
6559 }
6560 }
6561
6562 mSavingOldViewer =
6563 aTryToSaveOldPresentation &&
6564 CanSavePresentation(LOAD_NORMAL, nullptr, nullptr,
6565 /* aReportBFCacheComboTelemetry */ true);
6566
6567 // Make sure to blow away our mLoadingURI just in case. No loads
6568 // from inside this pagehide.
6569 mLoadingURI = nullptr;
6570
6571 // Stop any in-progress loading, so that we don't accidentally trigger any
6572 // PageShow notifications from Embed() interrupting our loading below.
6573 Stop();
6574
6575 // Notify the current document that it is about to be unloaded!!
6576 //
6577 // It is important to fire the unload() notification *before* any state
6578 // is changed within the DocShell - otherwise, javascript will get the
6579 // wrong information :-(
6580 //
6581 (void)FirePageHideNotification(!mSavingOldViewer);
6582 // pagehide notification might destroy this docshell.
6583 if (mIsBeingDestroyed) {
6584 return NS_ERROR_DOCSHELL_DYING;
6585 }
6586 }
6587
6588 // Now make sure we don't think we're in the middle of firing unload after
6589 // this point. This will make us fire unload when the about:blank document
6590 // unloads... but that's ok, more or less. Would be nice if it fired load
6591 // too, of course.
6592 mFiredUnloadEvent = false;
6593
6594 nsCOMPtr<nsIDocumentLoaderFactory> docFactory =
6595 nsContentUtils::FindInternalDocumentViewer("text/html"_ns);
6596
6597 if (docFactory) {
6598 nsCOMPtr<nsIPrincipal> principal, partitionedPrincipal;
6599 const uint32_t sandboxFlags =
6600 mBrowsingContext->GetHasLoadedNonInitialDocument()
6601 ? mBrowsingContext->GetSandboxFlags()
6602 : mBrowsingContext->GetInitialSandboxFlags();
6603 // If we're sandboxed, then create a new null principal. We skip
6604 // this if we're being created from WindowGlobalChild, since in
6605 // that case we already have a null principal if required.
6606 // We can't compare againt the BrowsingContext sandbox flag, since
6607 // the value was taken when the load initiated and may have since
6608 // changed.
6609 if ((sandboxFlags & SANDBOXED_ORIGIN) && !aActor) {
6610 if (aPrincipal) {
6611 principal = NullPrincipal::CreateWithInheritedAttributes(aPrincipal);
6612 } else {
6613 principal = NullPrincipal::Create(GetOriginAttributes());
6614 }
6615 partitionedPrincipal = principal;
6616 } else {
6617 principal = aPrincipal;
6618 partitionedPrincipal = aPartitionedPrincipal;
6619 }
6620
6621 // We cannot get the foreign partitioned prinicpal for the initial
6622 // about:blank page. So, we change to check if we need to use the
6623 // partitioned principal for the service worker here.
6624 MaybeCreateInitialClientSource(
6625 StoragePrincipalHelper::ShouldUsePartitionPrincipalForServiceWorker(
6626 this)
6627 ? partitionedPrincipal
6628 : principal);
6629
6630 // generate (about:blank) document to load
6631 blankDoc = nsContentDLF::CreateBlankDocument(mLoadGroup, principal,
6632 partitionedPrincipal, this);
6633 if (blankDoc) {
6634 // Hack: manually set the CSP for the new document
6635 // Please create an actual copy of the CSP (do not share the same
6636 // reference) otherwise appending a new policy within the new
6637 // document will be incorrectly propagated to the opening doc.
6638 if (aCSP) {
6639 RefPtr<nsCSPContext> cspToInherit = new nsCSPContext();
6640 cspToInherit->InitFromOther(static_cast<nsCSPContext*>(aCSP));
6641 blankDoc->SetCsp(cspToInherit);
6642 }
6643
6644 blankDoc->SetIsInitialDocument(aIsInitialDocument);
6645
6646 blankDoc->SetEmbedderPolicy(aCOEP);
6647
6648 // Hack: set the base URI manually, since this document never
6649 // got Reset() with a channel.
6650 blankDoc->SetBaseURI(aBaseURI);
6651
6652 // Copy our sandbox flags to the document. These are immutable
6653 // after being set here.
6654 blankDoc->SetSandboxFlags(sandboxFlags);
6655
6656 blankDoc->InitFeaturePolicy();
6657
6658 // create a content viewer for us and the new document
6659 docFactory->CreateInstanceForDocument(
6660 NS_ISUPPORTS_CAST(nsIDocShell*, this)static_cast<nsISupports*>(static_cast<nsIDocShell*>
(this))
, blankDoc, "view",
6661 getter_AddRefs(viewer));
6662
6663 // hook 'em up
6664 if (viewer) {
6665 viewer->SetContainer(this);
6666 rv = Embed(viewer, aActor, true, false, nullptr, mCurrentURI);
6667 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"
, 6667); return rv; } } while (false)
;
6668
6669 SetCurrentURI(blankDoc->GetDocumentURI(), nullptr,
6670 /* aFireLocationChange */ true,
6671 /* aIsInitialAboutBlank */ true,
6672 /* aLocationFlags */ 0);
6673 rv = mIsBeingDestroyed ? NS_ERROR_NOT_AVAILABLE : NS_OK;
6674 }
6675 }
6676 }
6677
6678 // The transient about:blank viewer doesn't have a session history entry.
6679 SetHistoryEntryAndUpdateBC(Nothing(), Some(nullptr));
6680
6681 // Clear out our mTiming like we would in EndPageLoad, if we didn't
6682 // have one before entering this function.
6683 if (!hadTiming) {
6684 mTiming = nullptr;
6685 mBlankTiming = true;
6686 }
6687
6688 return rv;
6689}
6690
6691NS_IMETHODIMPnsresult
6692nsDocShell::CreateAboutBlankDocumentViewer(nsIPrincipal* aPrincipal,
6693 nsIPrincipal* aPartitionedPrincipal,
6694 nsIContentSecurityPolicy* aCSP) {
6695 return CreateAboutBlankDocumentViewer(aPrincipal, aPartitionedPrincipal, aCSP,
6696 nullptr,
6697 /* aIsInitialDocument */ false);
6698}
6699
6700nsresult nsDocShell::CreateDocumentViewerForActor(
6701 WindowGlobalChild* aWindowActor) {
6702 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"
, 6702); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aWindowActor"
")"); do { *((volatile int*)__null) = 6702; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6703
6704 // FIXME: WindowGlobalChild should provide the PartitionedPrincipal.
6705 // FIXME: We may want to support non-initial documents here.
6706 nsresult rv = CreateAboutBlankDocumentViewer(
6707 aWindowActor->DocumentPrincipal(), aWindowActor->DocumentPrincipal(),
6708 /* aCsp */ nullptr,
6709 /* aBaseURI */ nullptr,
6710 /* aIsInitialDocument */ true,
6711 /* aCOEP */ Nothing(),
6712 /* aTryToSaveOldPresentation */ true,
6713 /* aCheckPermitUnload */ true, aWindowActor);
6714#ifdef DEBUG1
6715 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
6716 RefPtr<Document> doc(GetDocument());
6717 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"
, 6719); AnnotateMozCrashReason("MOZ_ASSERT" "(" "doc" ") (" "Should have a document if CreateAboutBlankDocumentViewer succeeded"
")"); do { *((volatile int*)__null) = 6719; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6718 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"
, 6719); AnnotateMozCrashReason("MOZ_ASSERT" "(" "doc" ") (" "Should have a document if CreateAboutBlankDocumentViewer succeeded"
")"); do { *((volatile int*)__null) = 6719; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6719 "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"
, 6719); AnnotateMozCrashReason("MOZ_ASSERT" "(" "doc" ") (" "Should have a document if CreateAboutBlankDocumentViewer succeeded"
")"); do { *((volatile int*)__null) = 6719; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6720 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"
, 6721); AnnotateMozCrashReason("MOZ_ASSERT" "(" "doc->GetOwnerGlobal() == aWindowActor->GetWindowGlobal()"
") (" "New document should be in the same global as our actor"
")"); do { *((volatile int*)__null) = 6721; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6721 "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"
, 6721); AnnotateMozCrashReason("MOZ_ASSERT" "(" "doc->GetOwnerGlobal() == aWindowActor->GetWindowGlobal()"
") (" "New document should be in the same global as our actor"
")"); do { *((volatile int*)__null) = 6721; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6722 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"
, 6723); AnnotateMozCrashReason("MOZ_ASSERT" "(" "doc->IsInitialDocument()"
") (" "New document should be an initial document" ")"); do {
*((volatile int*)__null) = 6723; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
6723 "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"
, 6723); AnnotateMozCrashReason("MOZ_ASSERT" "(" "doc->IsInitialDocument()"
") (" "New document should be an initial document" ")"); do {
*((volatile int*)__null) = 6723; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
6724 }
6725#endif
6726
6727 return rv;
6728}
6729
6730bool nsDocShell::CanSavePresentation(uint32_t aLoadType,
6731 nsIRequest* aNewRequest,
6732 Document* aNewDocument,
6733 bool aReportBFCacheComboTelemetry) {
6734 if (!mOSHE) {
6735 return false; // no entry to save into
6736 }
6737
6738 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"
, 6739); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mozilla::SessionHistoryInParent()"
") (" "mOSHE cannot be non-null with SHIP" ")"); do { *((volatile
int*)__null) = 6739; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
6739 "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"
, 6739); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mozilla::SessionHistoryInParent()"
") (" "mOSHE cannot be non-null with SHIP" ")"); do { *((volatile
int*)__null) = 6739; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
6740 nsCOMPtr<nsIDocumentViewer> viewer = mOSHE->GetDocumentViewer();
6741 if (viewer) {
6742 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"
, 6742)
;
6743 return false;
6744 }
6745
6746 // Only save presentation for "normal" loads and link loads. Anything else
6747 // probably wants to refetch the page, so caching the old presentation
6748 // would be incorrect.
6749 if (aLoadType != LOAD_NORMAL && aLoadType != LOAD_HISTORY &&
6750 aLoadType != LOAD_LINK && aLoadType != LOAD_STOP_CONTENT &&
6751 aLoadType != LOAD_STOP_CONTENT_AND_REPLACE &&
6752 aLoadType != LOAD_ERROR_PAGE) {
6753 return false;
6754 }
6755
6756 // If the session history entry has the saveLayoutState flag set to false,
6757 // then we should not cache the presentation.
6758 if (!mOSHE->GetSaveLayoutStateFlag()) {
6759 return false;
6760 }
6761
6762 // If the document is not done loading, don't cache it.
6763 if (!mScriptGlobal || mScriptGlobal->IsLoading()) {
6764 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)
6765 ("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)
;
6766 return false;
6767 }
6768
6769 if (mScriptGlobal->WouldReuseInnerWindow(aNewDocument)) {
6770 return false;
6771 }
6772
6773 // Avoid doing the work of saving the presentation state in the case where
6774 // the content viewer cache is disabled.
6775 if (nsSHistory::GetMaxTotalViewers() == 0) {
6776 return false;
6777 }
6778
6779 // Don't cache the content viewer if we're in a subframe.
6780 if (mBrowsingContext->GetParent()) {
6781 return false; // this is a subframe load
6782 }
6783
6784 // If the document does not want its presentation cached, then don't.
6785 RefPtr<Document> doc = mScriptGlobal->GetExtantDoc();
6786
6787 uint32_t bfCacheCombo = 0;
6788 bool canSavePresentation =
6789 doc->CanSavePresentation(aNewRequest, bfCacheCombo, true);
6790 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"
, 6790); AnnotateMozCrashReason("MOZ_ASSERT" "(" "bfCacheCombo == 0"
")"); do { *((volatile int*)__null) = 6790; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
6791 if (canSavePresentation && doc->IsTopLevelContentDocument()) {
6792 auto* browsingContextGroup = mBrowsingContext->Group();
6793 nsTArray<RefPtr<BrowsingContext>>& topLevelContext =
6794 browsingContextGroup->Toplevels();
6795
6796 for (const auto& browsingContext : topLevelContext) {
6797 if (browsingContext != mBrowsingContext) {
6798 if (StaticPrefs::docshell_shistory_bfcache_require_no_opener()) {
6799 canSavePresentation = false;
6800 }
6801 bfCacheCombo |= BFCacheStatus::NOT_ONLY_TOPLEVEL_IN_BCG;
6802 break;
6803 }
6804 }
6805 }
6806
6807 if (aReportBFCacheComboTelemetry) {
6808 ReportBFCacheComboTelemetry(bfCacheCombo);
6809 }
6810 return doc && canSavePresentation;
6811}
6812
6813/* static */
6814void nsDocShell::ReportBFCacheComboTelemetry(uint32_t aCombo) {
6815 // There are 11 possible reasons to make a request fails to use BFCache
6816 // (see BFCacheStatus in dom/base/Document.h), and we'd like to record
6817 // the common combinations for reasons which make requests fail to use
6818 // BFCache. These combinations are generated based on some local browsings,
6819 // we need to adjust them when necessary.
6820 enum BFCacheStatusCombo : uint32_t {
6821 BFCACHE_SUCCESS,
6822 NOT_ONLY_TOPLEVEL = mozilla::dom::BFCacheStatus::NOT_ONLY_TOPLEVEL_IN_BCG,
6823 // If both unload and beforeunload listeners are presented, it'll be
6824 // recorded as unload
6825 UNLOAD = mozilla::dom::BFCacheStatus::UNLOAD_LISTENER,
6826 UNLOAD_REQUEST = mozilla::dom::BFCacheStatus::UNLOAD_LISTENER |
6827 mozilla::dom::BFCacheStatus::REQUEST,
6828 REQUEST = mozilla::dom::BFCacheStatus::REQUEST,
6829 UNLOAD_REQUEST_PEER = mozilla::dom::BFCacheStatus::UNLOAD_LISTENER |
6830 mozilla::dom::BFCacheStatus::REQUEST |
6831 mozilla::dom::BFCacheStatus::ACTIVE_PEER_CONNECTION,
6832 UNLOAD_REQUEST_PEER_MSE =
6833 mozilla::dom::BFCacheStatus::UNLOAD_LISTENER |
6834 mozilla::dom::BFCacheStatus::REQUEST |
6835 mozilla::dom::BFCacheStatus::ACTIVE_PEER_CONNECTION |
6836 mozilla::dom::BFCacheStatus::CONTAINS_MSE_CONTENT,
6837 UNLOAD_REQUEST_MSE = mozilla::dom::BFCacheStatus::UNLOAD_LISTENER |
6838 mozilla::dom::BFCacheStatus::REQUEST |
6839 mozilla::dom::BFCacheStatus::CONTAINS_MSE_CONTENT,
6840 SUSPENDED_UNLOAD_REQUEST_PEER =
6841 mozilla::dom::BFCacheStatus::SUSPENDED |
6842 mozilla::dom::BFCacheStatus::UNLOAD_LISTENER |
6843 mozilla::dom::BFCacheStatus::REQUEST |
6844 mozilla::dom::BFCacheStatus::ACTIVE_PEER_CONNECTION,
6845 REMOTE_SUBFRAMES = mozilla::dom::BFCacheStatus::CONTAINS_REMOTE_SUBFRAMES,
6846 BEFOREUNLOAD = mozilla::dom::BFCacheStatus::BEFOREUNLOAD_LISTENER,
6847 };
6848
6849 // Beforeunload is recorded as a blocker only if it is the only one to block
6850 // bfcache.
6851 if (aCombo != mozilla::dom::BFCacheStatus::BEFOREUNLOAD_LISTENER) {
6852 aCombo &= ~mozilla::dom::BFCacheStatus::BEFOREUNLOAD_LISTENER;
6853 }
6854 switch (aCombo) {
6855 case BFCACHE_SUCCESS:
6856 Telemetry::AccumulateCategorical(
6857 Telemetry::LABELS_BFCACHE_COMBO::BFCache_Success);
6858 break;
6859 case NOT_ONLY_TOPLEVEL:
6860 if (StaticPrefs::docshell_shistory_bfcache_require_no_opener()) {
6861 Telemetry::AccumulateCategorical(
6862 Telemetry::LABELS_BFCACHE_COMBO::Other);
6863 break;
6864 }
6865 Telemetry::AccumulateCategorical(
6866 Telemetry::LABELS_BFCACHE_COMBO::BFCache_Success);
6867 Telemetry::AccumulateCategorical(
6868 Telemetry::LABELS_BFCACHE_COMBO::Success_Not_Toplevel);
6869 break;
6870 case UNLOAD:
6871 Telemetry::AccumulateCategorical(Telemetry::LABELS_BFCACHE_COMBO::Unload);
6872 break;
6873 case BEFOREUNLOAD:
6874 Telemetry::AccumulateCategorical(
6875 Telemetry::LABELS_BFCACHE_COMBO::Beforeunload);
6876 break;
6877 case UNLOAD_REQUEST:
6878 Telemetry::AccumulateCategorical(
6879 Telemetry::LABELS_BFCACHE_COMBO::Unload_Req);
6880 break;
6881 case REQUEST:
6882 Telemetry::AccumulateCategorical(Telemetry::LABELS_BFCACHE_COMBO::Req);
6883 break;
6884 case UNLOAD_REQUEST_PEER:
6885 Telemetry::AccumulateCategorical(
6886 Telemetry::LABELS_BFCACHE_COMBO::Unload_Req_Peer);
6887 break;
6888 case UNLOAD_REQUEST_PEER_MSE:
6889 Telemetry::AccumulateCategorical(
6890 Telemetry::LABELS_BFCACHE_COMBO::Unload_Req_Peer_MSE);
6891 break;
6892 case UNLOAD_REQUEST_MSE:
6893 Telemetry::AccumulateCategorical(
6894 Telemetry::LABELS_BFCACHE_COMBO::Unload_Req_MSE);
6895 break;
6896 case SUSPENDED_UNLOAD_REQUEST_PEER:
6897 Telemetry::AccumulateCategorical(
6898 Telemetry::LABELS_BFCACHE_COMBO::SPD_Unload_Req_Peer);
6899 break;
6900 case REMOTE_SUBFRAMES:
6901 Telemetry::AccumulateCategorical(
6902 Telemetry::LABELS_BFCACHE_COMBO::Remote_Subframes);
6903 break;
6904 default:
6905 Telemetry::AccumulateCategorical(Telemetry::LABELS_BFCACHE_COMBO::Other);
6906 break;
6907 }
6908};
6909
6910void nsDocShell::ReattachEditorToWindow(nsISHEntry* aSHEntry) {
6911 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"
, 6911); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mozilla::SessionHistoryInParent()"
")"); do { *((volatile int*)__null) = 6911; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6912 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"
, 6912); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mIsBeingDestroyed"
")"); do { *((volatile int*)__null) = 6912; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6913
6914 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"
, 6915); MOZ_PretendNoReturn(); } } while (0)
6915 "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"
, 6915); MOZ_PretendNoReturn(); } } while (0)
;
6916 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"
, 6917); MOZ_PretendNoReturn(); } } while (0)
6917 "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"
, 6917); MOZ_PretendNoReturn(); } } while (0)
;
6918
6919 if (mEditorData || !aSHEntry) {
6920 return;
6921 }
6922
6923 mEditorData = WrapUnique(aSHEntry->ForgetEditorData());
6924 if (mEditorData) {
6925#ifdef DEBUG1
6926 nsresult rv =
6927#endif
6928 mEditorData->ReattachToWindow(this);
6929 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"
, 6929); MOZ_PretendNoReturn(); } } while (0)
;
6930 }
6931}
6932
6933void nsDocShell::DetachEditorFromWindow() {
6934 if (!mEditorData || mEditorData->WaitingForLoad()) {
6935 // If there's nothing to detach, or if the editor data is actually set
6936 // up for the _new_ page that's coming in, don't detach.
6937 return;
6938 }
6939
6940 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"
, 6941); MOZ_PretendNoReturn(); } } while (0)
6941 "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"
, 6941); MOZ_PretendNoReturn(); } } while (0)
;
6942
6943 nsresult res = mEditorData->DetachFromWindow();
6944 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"
, 6944); MOZ_PretendNoReturn(); } } while (0)
;
6945
6946 if (NS_SUCCEEDED(res)((bool)(__builtin_expect(!!(!NS_FAILED_impl(res)), 1)))) {
6947 // Make mOSHE hold the owning ref to the editor data.
6948 if (mOSHE) {
6949 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"
, 6951); 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) = 6951; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6950 "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"
, 6951); 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) = 6951; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6951 "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"
, 6951); 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) = 6951; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6952 mOSHE->SetEditorData(mEditorData.release());
6953 } else {
6954 mEditorData = nullptr;
6955 }
6956 }
6957
6958#ifdef DEBUG1
6959 {
6960 bool isEditable;
6961 GetEditable(&isEditable);
6962 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"
, 6963); MOZ_PretendNoReturn(); } } while (0)
6963 "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"
, 6963); MOZ_PretendNoReturn(); } } while (0)
;
6964 }
6965#endif // DEBUG
6966}
6967
6968nsresult nsDocShell::CaptureState() {
6969 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"
, 6969); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mozilla::SessionHistoryInParent()"
")"); do { *((volatile int*)__null) = 6969; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6970
6971 if (!mOSHE || mOSHE == mLSHE) {
6972 // No entry to save into, or we're replacing the existing entry.
6973 return NS_ERROR_FAILURE;
6974 }
6975
6976 if (!mScriptGlobal) {
6977 return NS_ERROR_FAILURE;
6978 }
6979
6980 nsCOMPtr<nsISupports> windowState = mScriptGlobal->SaveWindowState();
6981 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"
, 6981); return NS_ERROR_FAILURE; } } while (false)
;
6982
6983 if (MOZ_UNLIKELY(MOZ_LOG_TEST(gPageCacheLog, LogLevel::Debug))(__builtin_expect(!!((__builtin_expect(!!(mozilla::detail::log_test
(gPageCacheLog, LogLevel::Debug)), 0))), 0))
) {
6984 nsAutoCString spec;
6985 nsCOMPtr<nsIURI> uri = mOSHE->GetURI();
6986 if (uri) {
6987 uri->GetSpec(spec);
6988 }
6989 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)
6990 ("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)
;
6991 }
6992
6993 mOSHE->SetWindowState(windowState);
6994
6995 // Suspend refresh URIs and save off the timer queue
6996 mOSHE->SetRefreshURIList(mSavedRefreshURIList);
6997
6998 // Capture the current content viewer bounds.
6999 if (mDocumentViewer) {
7000 nsIntRect bounds;
7001 mDocumentViewer->GetBounds(bounds);
7002 mOSHE->SetViewerBounds(bounds);
7003 }
7004
7005 // Capture the docshell hierarchy.
7006 mOSHE->ClearChildShells();
7007
7008 uint32_t childCount = mChildList.Length();
7009 for (uint32_t i = 0; i < childCount; ++i) {
7010 nsCOMPtr<nsIDocShellTreeItem> childShell = do_QueryInterface(ChildAt(i));
7011 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"
, 7011); MOZ_PretendNoReturn(); } } while (0)
;
7012
7013 mOSHE->AddChildShell(childShell);
7014 }
7015
7016 return NS_OK;
7017}
7018
7019NS_IMETHODIMPnsresult
7020nsDocShell::RestorePresentationEvent::Run() {
7021 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"
, 7021); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mozilla::SessionHistoryInParent()"
")"); do { *((volatile int*)__null) = 7021; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7022
7023 if (mDocShell && NS_FAILED(mDocShell->RestoreFromHistory())((bool)(__builtin_expect(!!(NS_FAILED_impl(mDocShell->RestoreFromHistory
())), 0)))
) {
7024 NS_WARNING("RestoreFromHistory failed")NS_DebugBreak(NS_DEBUG_WARNING, "RestoreFromHistory failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 7024)
;
7025 }
7026 return NS_OK;
7027}
7028
7029NS_IMETHODIMPnsresult
7030nsDocShell::BeginRestore(nsIDocumentViewer* aDocumentViewer, bool aTop) {
7031 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"
, 7031); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mozilla::SessionHistoryInParent()"
")"); do { *((volatile int*)__null) = 7031; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7032
7033 nsresult rv;
7034 if (!aDocumentViewer) {
7035 rv = EnsureDocumentViewer();
7036 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"
, 7036); return rv; } } while (false)
;
7037
7038 aDocumentViewer = mDocumentViewer;
7039 }
7040
7041 // Dispatch events for restoring the presentation. We try to simulate
7042 // the progress notifications loading the document would cause, so we add
7043 // the document's channel to the loadgroup to initiate stateChange
7044 // notifications.
7045
7046 RefPtr<Document> doc = aDocumentViewer->GetDocument();
7047 if (doc) {
7048 nsIChannel* channel = doc->GetChannel();
7049 if (channel) {
7050 mEODForCurrentDocument = false;
7051 mIsRestoringDocument = true;
7052 mLoadGroup->AddRequest(channel, nullptr);
7053 mIsRestoringDocument = false;
7054 }
7055 }
7056
7057 if (!aTop) {
7058 // This point corresponds to us having gotten OnStartRequest or
7059 // STATE_START, so do the same thing that CreateDocumentViewer does at
7060 // this point to ensure that unload/pagehide events for this document
7061 // will fire when it's unloaded again.
7062 mFiredUnloadEvent = false;
7063
7064 // For non-top frames, there is no notion of making sure that the
7065 // previous document is in the domwindow when STATE_START notifications
7066 // happen. We can just call BeginRestore for all of the child shells
7067 // now.
7068 rv = BeginRestoreChildren();
7069 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"
, 7069); return rv; } } while (false)
;
7070 }
7071
7072 return NS_OK;
7073}
7074
7075nsresult nsDocShell::BeginRestoreChildren() {
7076 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"
, 7076); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mozilla::SessionHistoryInParent()"
")"); do { *((volatile int*)__null) = 7076; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7077
7078 for (auto* childDocLoader : mChildList.ForwardRange()) {
7079 nsCOMPtr<nsIDocShell> child = do_QueryObject(childDocLoader);
7080 if (child) {
7081 nsresult rv = child->BeginRestore(nullptr, false);
7082 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"
, 7082); return rv; } } while (false)
;
7083 }
7084 }
7085 return NS_OK;
7086}
7087
7088NS_IMETHODIMPnsresult
7089nsDocShell::FinishRestore() {
7090 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"
, 7090); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mozilla::SessionHistoryInParent()"
")"); do { *((volatile int*)__null) = 7090; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7091
7092 // First we call finishRestore() on our children. In the simulated load,
7093 // all of the child frames finish loading before the main document.
7094
7095 for (auto* childDocLoader : mChildList.ForwardRange()) {
7096 nsCOMPtr<nsIDocShell> child = do_QueryObject(childDocLoader);
7097 if (child) {
7098 child->FinishRestore();
7099 }
7100 }
7101
7102 if (mOSHE && mOSHE->HasDetachedEditor()) {
7103 ReattachEditorToWindow(mOSHE);
7104 }
7105
7106 RefPtr<Document> doc = GetDocument();
7107 if (doc) {
7108 // Finally, we remove the request from the loadgroup. This will
7109 // cause onStateChange(STATE_STOP) to fire, which will fire the
7110 // pageshow event to the chrome.
7111
7112 nsIChannel* channel = doc->GetChannel();
7113 if (channel) {
7114 mIsRestoringDocument = true;
7115 mLoadGroup->RemoveRequest(channel, nullptr, NS_OK);
7116 mIsRestoringDocument = false;
7117 }
7118 }
7119
7120 return NS_OK;
7121}
7122
7123NS_IMETHODIMPnsresult
7124nsDocShell::GetRestoringDocument(bool* aRestoring) {
7125 *aRestoring = mIsRestoringDocument;
7126 return NS_OK;
7127}
7128
7129nsresult nsDocShell::RestorePresentation(nsISHEntry* aSHEntry,
7130 bool* aRestoring) {
7131 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"
, 7131); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mozilla::SessionHistoryInParent()"
")"); do { *((volatile int*)__null) = 7131; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7132 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"
, 7132); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mIsBeingDestroyed"
")"); do { *((volatile int*)__null) = 7132; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7133
7134 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"
, 7135); MOZ_PretendNoReturn(); } } while (0)
7135 "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"
, 7135); MOZ_PretendNoReturn(); } } while (0)
;
7136
7137 nsCOMPtr<nsIDocumentViewer> viewer = aSHEntry->GetDocumentViewer();
7138
7139 nsAutoCString spec;
7140 if (MOZ_UNLIKELY(MOZ_LOG_TEST(gPageCacheLog, LogLevel::Debug))(__builtin_expect(!!((__builtin_expect(!!(mozilla::detail::log_test
(gPageCacheLog, LogLevel::Debug)), 0))), 0))
) {
7141 nsCOMPtr<nsIURI> uri = aSHEntry->GetURI();
7142 if (uri) {
7143 uri->GetSpec(spec);
7144 }
7145 }
7146
7147 *aRestoring = false;
7148
7149 if (!viewer) {
7150 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)
7151 ("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)
;
7152 return NS_OK;
7153 }
7154
7155 // We need to make sure the content viewer's container is this docshell.
7156 // In subframe navigation, it's possible for the docshell that the
7157 // content viewer was originally loaded into to be replaced with a
7158 // different one. We don't currently support restoring the presentation
7159 // in that case.
7160
7161 nsCOMPtr<nsIDocShell> container;
7162 viewer->GetContainer(getter_AddRefs(container));
7163 if (!::SameCOMIdentity(container, GetAsSupports(this))) {
7164 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)
7165 ("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)
;
7166 aSHEntry->SetDocumentViewer(nullptr);
7167 return NS_ERROR_FAILURE;
7168 }
7169
7170 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"
, 7170); MOZ_PretendNoReturn(); } } while (0)
;
7171
7172 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)
7173 ("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)
;
7174
7175 SetHistoryEntryAndUpdateBC(Some(aSHEntry), Nothing());
7176
7177 // Post an event that will remove the request after we've returned
7178 // to the event loop. This mimics the way it is called by nsIChannel
7179 // implementations.
7180
7181 // Revoke any pending restore (just in case).
7182 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"
, 7183); MOZ_PretendNoReturn(); } } while (0)
7183 "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"
, 7183); MOZ_PretendNoReturn(); } } while (0)
;
7184 mRestorePresentationEvent.Revoke();
7185
7186 RefPtr<RestorePresentationEvent> evt = new RestorePresentationEvent(this);
7187 nsresult rv = Dispatch(do_AddRef(evt));
7188 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
7189 mRestorePresentationEvent = evt.get();
7190 // The rest of the restore processing will happen on our event
7191 // callback.
7192 *aRestoring = true;
7193 }
7194
7195 return rv;
7196}
7197
7198namespace {
7199class MOZ_STACK_CLASS PresentationEventForgetter {
7200 public:
7201 explicit PresentationEventForgetter(
7202 nsRevocableEventPtr<nsDocShell::RestorePresentationEvent>&
7203 aRestorePresentationEvent)
7204 : mRestorePresentationEvent(aRestorePresentationEvent),
7205 mEvent(aRestorePresentationEvent.get()) {}
7206
7207 ~PresentationEventForgetter() { Forget(); }
7208
7209 void Forget() {
7210 if (mRestorePresentationEvent.get() == mEvent) {
7211 mRestorePresentationEvent.Forget();
7212 mEvent = nullptr;
7213 }
7214 }
7215
7216 private:
7217 nsRevocableEventPtr<nsDocShell::RestorePresentationEvent>&
7218 mRestorePresentationEvent;
7219 RefPtr<nsDocShell::RestorePresentationEvent> mEvent;
7220};
7221
7222} // namespace
7223
7224bool nsDocShell::SandboxFlagsImplyCookies(const uint32_t& aSandboxFlags) {
7225 return (aSandboxFlags & (SANDBOXED_ORIGIN | SANDBOXED_SCRIPTS)) == 0;
7226}
7227
7228nsresult nsDocShell::RestoreFromHistory() {
7229 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"
, 7229); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mozilla::SessionHistoryInParent()"
")"); do { *((volatile int*)__null) = 7229; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7230 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"
, 7230); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mRestorePresentationEvent.IsPending()"
")"); do { *((volatile int*)__null) = 7230; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7231 PresentationEventForgetter forgetter(mRestorePresentationEvent);
7232
7233 // This section of code follows the same ordering as CreateDocumentViewer.
7234 if (!mLSHE) {
7235 return NS_ERROR_FAILURE;
7236 }
7237
7238 nsCOMPtr<nsIDocumentViewer> viewer = mLSHE->GetDocumentViewer();
7239 if (!viewer) {
7240 return NS_ERROR_FAILURE;
7241 }
7242
7243 if (mSavingOldViewer) {
7244 // We determined that it was safe to cache the document presentation
7245 // at the time we initiated the new load. We need to check whether
7246 // it's still safe to do so, since there may have been DOM mutations
7247 // or new requests initiated.
7248 RefPtr<Document> doc = viewer->GetDocument();
7249 nsIRequest* request = nullptr;
7250 if (doc) {
7251 request = doc->GetChannel();
7252 }
7253 mSavingOldViewer = CanSavePresentation(
7254 mLoadType, request, doc, /* aReportBFCacheComboTelemetry */ false);
7255 }
7256
7257 // Protect against mLSHE going away via a load triggered from
7258 // pagehide or unload.
7259 nsCOMPtr<nsISHEntry> origLSHE = mLSHE;
7260
7261 // Make sure to blow away our mLoadingURI just in case. No loads
7262 // from inside this pagehide.
7263 mLoadingURI = nullptr;
7264
7265 // Notify the old content viewer that it's being hidden.
7266 FirePageHideNotification(!mSavingOldViewer);
7267 // pagehide notification might destroy this docshell.
7268 if (mIsBeingDestroyed) {
7269 return NS_ERROR_DOCSHELL_DYING;
7270 }
7271
7272 // If mLSHE was changed as a result of the pagehide event, then
7273 // something else was loaded. Don't finish restoring.
7274 if (mLSHE != origLSHE) {
7275 return NS_OK;
7276 }
7277
7278 // Add the request to our load group. We do this before swapping out
7279 // the content viewers so that consumers of STATE_START can access
7280 // the old document. We only deal with the toplevel load at this time --
7281 // to be consistent with normal document loading, subframes cannot start
7282 // loading until after data arrives, which is after STATE_START completes.
7283
7284 RefPtr<RestorePresentationEvent> currentPresentationRestoration =
7285 mRestorePresentationEvent.get();
7286 Stop();
7287 // Make sure we're still restoring the same presentation.
7288 // If we aren't, docshell is in process doing another load already.
7289 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"
, 7290); return NS_ERROR_UNEXPECTED; } } while (false)
7290 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"
, 7290); return NS_ERROR_UNEXPECTED; } } while (false)
;
7291 BeginRestore(viewer, true);
7292 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"
, 7293); return NS_ERROR_UNEXPECTED; } } while (false)
7293 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"
, 7293); return NS_ERROR_UNEXPECTED; } } while (false)
;
7294 forgetter.Forget();
7295
7296 // Set mFiredUnloadEvent = false so that the unload handler for the
7297 // *new* document will fire.
7298 mFiredUnloadEvent = false;
7299
7300 mURIResultedInDocument = true;
7301 RefPtr<ChildSHistory> rootSH = GetRootSessionHistory();
7302 if (rootSH) {
7303 mPreviousEntryIndex = rootSH->Index();
7304 rootSH->LegacySHistory()->UpdateIndex();
7305 mLoadedEntryIndex = rootSH->Index();
7306 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)
7307 ("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)
7308 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)
;
7309 }
7310
7311 // Rather than call Embed(), we will retrieve the viewer from the session
7312 // history entry and swap it in.
7313 // XXX can we refactor this so that we can just call Embed()?
7314 PersistLayoutHistoryState();
7315 nsresult rv;
7316 if (mDocumentViewer) {
7317 if (mSavingOldViewer && NS_FAILED(CaptureState())((bool)(__builtin_expect(!!(NS_FAILED_impl(CaptureState())), 0
)))
) {
7318 if (mOSHE) {
7319 mOSHE->SyncPresentationState();
7320 }
7321 mSavingOldViewer = false;
7322 }
7323 }
7324
7325 mSavedRefreshURIList = nullptr;
7326
7327 // In cases where we use a transient about:blank viewer between loads,
7328 // we never show the transient viewer, so _its_ previous viewer is never
7329 // unhooked from the view hierarchy. Destroy any such previous viewer now,
7330 // before we grab the root view sibling, so that we don't grab a view
7331 // that's about to go away.
7332
7333 if (mDocumentViewer) {
7334 // Make sure to hold a strong ref to previousViewer here while we
7335 // drop the reference to it from mDocumentViewer.
7336 nsCOMPtr<nsIDocumentViewer> previousViewer =
7337 mDocumentViewer->GetPreviousViewer();
7338 if (previousViewer) {
7339 mDocumentViewer->SetPreviousViewer(nullptr);
7340 previousViewer->Destroy();
7341 }
7342 }
7343
7344 // Save off the root view's parent and sibling so that we can insert the
7345 // new content viewer's root view at the same position. Also save the
7346 // bounds of the root view's widget.
7347
7348 nsView* rootViewSibling = nullptr;
7349 nsView* rootViewParent = nullptr;
7350 nsIntRect newBounds(0, 0, 0, 0);
7351
7352 PresShell* oldPresShell = GetPresShell();
7353 if (oldPresShell) {
7354 nsViewManager* vm = oldPresShell->GetViewManager();
7355 if (vm) {
7356 nsView* oldRootView = vm->GetRootView();
7357
7358 if (oldRootView) {
7359 rootViewSibling = oldRootView->GetNextSibling();
7360 rootViewParent = oldRootView->GetParent();
7361
7362 mDocumentViewer->GetBounds(newBounds);
7363 }
7364 }
7365 }
7366
7367 nsCOMPtr<nsIContent> container;
7368 RefPtr<Document> sibling;
7369 if (rootViewParent && rootViewParent->GetParent()) {
7370 nsIFrame* frame = rootViewParent->GetParent()->GetFrame();
7371 container = frame ? frame->GetContent() : nullptr;
7372 }
7373 if (rootViewSibling) {
7374 nsIFrame* frame = rootViewSibling->GetFrame();
7375 sibling = frame ? frame->PresShell()->GetDocument() : nullptr;
7376 }
7377
7378 // Transfer ownership to mDocumentViewer. By ensuring that either the
7379 // docshell or the session history, but not both, have references to the
7380 // content viewer, we prevent the viewer from being torn down after
7381 // Destroy() is called.
7382
7383 if (mDocumentViewer) {
7384 mDocumentViewer->Close(mSavingOldViewer ? mOSHE.get() : nullptr);
7385 viewer->SetPreviousViewer(mDocumentViewer);
7386 }
7387 if (mOSHE && (!mDocumentViewer || !mSavingOldViewer)) {
7388 // We don't plan to save a viewer in mOSHE; tell it to drop
7389 // any other state it's holding.
7390 mOSHE->SyncPresentationState();
7391 }
7392
7393 // Order the mDocumentViewer setup just like Embed does.
7394 mDocumentViewer = nullptr;
7395
7396 // Now that we're about to switch documents, forget all of our children.
7397 // Note that we cached them as needed up in CaptureState above.
7398 DestroyChildren();
7399
7400 mDocumentViewer.swap(viewer);
7401
7402 // Grab all of the related presentation from the SHEntry now.
7403 // Clearing the viewer from the SHEntry will clear all of this state.
7404 nsCOMPtr<nsISupports> windowState = mLSHE->GetWindowState();
7405 mLSHE->SetWindowState(nullptr);
7406
7407 bool sticky = mLSHE->GetSticky();
7408
7409 RefPtr<Document> document = mDocumentViewer->GetDocument();
7410
7411 nsCOMArray<nsIDocShellTreeItem> childShells;
7412 int32_t i = 0;
7413 nsCOMPtr<nsIDocShellTreeItem> child;
7414 while (NS_SUCCEEDED(mLSHE->ChildShellAt(i++, getter_AddRefs(child)))((bool)(__builtin_expect(!!(!NS_FAILED_impl(mLSHE->ChildShellAt
(i++, getter_AddRefs(child)))), 1)))
&&
7415 child) {
7416 childShells.AppendObject(child);
7417 }
7418
7419 // get the previous content viewer size
7420 nsIntRect oldBounds(0, 0, 0, 0);
7421 mLSHE->GetViewerBounds(oldBounds);
7422
7423 // Restore the refresh URI list. The refresh timers will be restarted
7424 // when EndPageLoad() is called.
7425 nsCOMPtr<nsIMutableArray> refreshURIList = mLSHE->GetRefreshURIList();
7426
7427 // Reattach to the window object.
7428 mIsRestoringDocument = true; // for MediaDocument::BecomeInteractive
7429 rv = mDocumentViewer->Open(windowState, mLSHE);
7430 mIsRestoringDocument = false;
7431
7432 // Hack to keep nsDocShellEditorData alive across the
7433 // SetContentViewer(nullptr) call below.
7434 UniquePtr<nsDocShellEditorData> data(mLSHE->ForgetEditorData());
7435
7436 // Now remove it from the cached presentation.
7437 mLSHE->SetDocumentViewer(nullptr);
7438 mEODForCurrentDocument = false;
7439
7440 mLSHE->SetEditorData(data.release());
7441
7442#ifdef DEBUG1
7443 {
7444 nsCOMPtr<nsIMutableArray> refreshURIs = mLSHE->GetRefreshURIList();
7445 nsCOMPtr<nsIDocShellTreeItem> childShell;
7446 mLSHE->ChildShellAt(0, getter_AddRefs(childShell));
7447 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"
, 7448); MOZ_PretendNoReturn(); } } while (0)
7448 "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"
, 7448); MOZ_PretendNoReturn(); } } while (0)
;
7449 }
7450#endif
7451
7452 // Restore the sticky state of the viewer. The viewer has set this state
7453 // on the history entry in Destroy() just before marking itself non-sticky,
7454 // to avoid teardown of the presentation.
7455 mDocumentViewer->SetSticky(sticky);
7456
7457 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"
, 7457); return rv; } } while (false)
;
7458
7459 // mLSHE is now our currently-loaded document.
7460 SetHistoryEntryAndUpdateBC(Nothing(), Some<nsISHEntry*>(mLSHE));
7461
7462 // We aren't going to restore any items from the LayoutHistoryState,
7463 // but we don't want them to stay around in case the page is reloaded.
7464 SetLayoutHistoryState(nullptr);
7465
7466 // This is the end of our Embed() replacement
7467
7468 mSavingOldViewer = false;
7469 mEODForCurrentDocument = false;
7470
7471 if (document) {
7472 RefPtr<nsDocShell> parent = GetInProcessParentDocshell();
7473 if (parent) {
7474 RefPtr<Document> d = parent->GetDocument();
7475 if (d) {
7476 if (d->EventHandlingSuppressed()) {
7477 document->SuppressEventHandling(d->EventHandlingSuppressed());
7478 }
7479 }
7480 }
7481
7482 // Use the uri from the mLSHE we had when we entered this function
7483 // (which need not match the document's URI if anchors are involved),
7484 // since that's the history entry we're loading. Note that if we use
7485 // origLSHE we don't have to worry about whether the entry in question
7486 // is still mLSHE or whether it's now mOSHE.
7487 nsCOMPtr<nsIURI> uri = origLSHE->GetURI();
7488 SetCurrentURI(uri, document->GetChannel(), /* aFireLocationChange */ true,
7489 /* aIsInitialAboutBlank */ false,
7490 /* aLocationFlags */ 0);
7491 }
7492
7493 // This is the end of our CreateDocumentViewer() replacement.
7494 // Now we simulate a load. First, we restore the state of the javascript
7495 // window object.
7496 nsCOMPtr<nsPIDOMWindowOuter> privWin = GetWindow();
7497 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"
, 7497); MOZ_PretendNoReturn(); } } while (0)
;
7498
7499 // Now, dispatch a title change event which would happen as the
7500 // <head> is parsed.
7501 document->NotifyPossibleTitleChange(false);
7502
7503 // Now we simulate appending child docshells for subframes.
7504 for (i = 0; i < childShells.Count(); ++i) {
7505 nsIDocShellTreeItem* childItem = childShells.ObjectAt(i);
7506 nsCOMPtr<nsIDocShell> childShell = do_QueryInterface(childItem);
7507
7508 // Make sure to not clobber the state of the child. Since AddChild
7509 // always clobbers it, save it off first.
7510 bool allowRedirects;
7511 childShell->GetAllowMetaRedirects(&allowRedirects);
7512
7513 bool allowSubframes;
7514 childShell->GetAllowSubframes(&allowSubframes);
7515
7516 bool allowImages;
7517 childShell->GetAllowImages(&allowImages);
7518
7519 bool allowMedia = childShell->GetAllowMedia();
7520
7521 bool allowDNSPrefetch;
7522 childShell->GetAllowDNSPrefetch(&allowDNSPrefetch);
7523
7524 bool allowContentRetargeting = childShell->GetAllowContentRetargeting();
7525 bool allowContentRetargetingOnChildren =
7526 childShell->GetAllowContentRetargetingOnChildren();
7527
7528 // this.AddChild(child) calls child.SetDocLoaderParent(this), meaning that
7529 // the child inherits our state. Among other things, this means that the
7530 // child inherits our mPrivateBrowsingId, which is what we want.
7531 AddChild(childItem);
7532
7533 childShell->SetAllowMetaRedirects(allowRedirects);
7534 childShell->SetAllowSubframes(allowSubframes);
7535 childShell->SetAllowImages(allowImages);
7536 childShell->SetAllowMedia(allowMedia);
7537 childShell->SetAllowDNSPrefetch(allowDNSPrefetch);
7538 childShell->SetAllowContentRetargeting(allowContentRetargeting);
7539 childShell->SetAllowContentRetargetingOnChildren(
7540 allowContentRetargetingOnChildren);
7541
7542 rv = childShell->BeginRestore(nullptr, false);
7543 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"
, 7543); return rv; } } while (false)
;
7544 }
7545
7546 // Make sure to restore the window state after adding the child shells back
7547 // to the tree. This is necessary for Thaw() and Resume() to propagate
7548 // properly.
7549 rv = privWin->RestoreWindowState(windowState);
7550 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"
, 7550); return rv; } } while (false)
;
7551
7552 RefPtr<PresShell> presShell = GetPresShell();
7553
7554 // We may be displayed on a different monitor (or in a different
7555 // HiDPI mode) than when we got into the history list. So we need
7556 // to check if this has happened. See bug 838239.
7557
7558 // Because the prescontext normally handles resolution changes via
7559 // a runnable (see nsPresContext::UIResolutionChanged), its device
7560 // context won't be -immediately- updated as a result of calling
7561 // presShell->BackingScaleFactorChanged().
7562
7563 // But we depend on that device context when adjusting the view size
7564 // via mDocumentViewer->SetBounds(newBounds) below. So we need to
7565 // explicitly tell it to check for changed resolution here.
7566 if (presShell) {
7567 RefPtr<nsPresContext> pc = presShell->GetPresContext();
7568 if (pc->DeviceContext()->CheckDPIChange()) {
7569 presShell->BackingScaleFactorChanged();
7570 }
7571 // Recompute zoom and text-zoom and such.
7572 pc->RecomputeBrowsingContextDependentData();
7573 }
7574
7575 nsViewManager* newVM = presShell ? presShell->GetViewManager() : nullptr;
7576 nsView* newRootView = newVM ? newVM->GetRootView() : nullptr;
7577
7578 // Insert the new root view at the correct location in the view tree.
7579 if (container) {
7580 nsSubDocumentFrame* subDocFrame =
7581 do_QueryFrame(container->GetPrimaryFrame());
7582 rootViewParent = subDocFrame ? subDocFrame->EnsureInnerView() : nullptr;
7583 } else {
7584 rootViewParent = nullptr;
7585 }
7586 if (sibling && sibling->GetPresShell() &&
7587 sibling->GetPresShell()->GetViewManager()) {
7588 rootViewSibling = sibling->GetPresShell()->GetViewManager()->GetRootView();
7589 } else {
7590 rootViewSibling = nullptr;
7591 }
7592 if (rootViewParent && newRootView &&
7593 newRootView->GetParent() != rootViewParent) {
7594 nsViewManager* parentVM = rootViewParent->GetViewManager();
7595 if (parentVM) {
7596 // InsertChild(parent, child, sib, true) inserts the child after
7597 // sib in content order, which is before sib in view order. BUT
7598 // when sib is null it inserts at the end of the the document
7599 // order, i.e., first in view order. But when oldRootSibling is
7600 // null, the old root as at the end of the view list --- last in
7601 // content order --- and we want to call InsertChild(parent, child,
7602 // nullptr, false) in that case.
7603 parentVM->InsertChild(rootViewParent, newRootView, rootViewSibling,
7604 rootViewSibling ? true : false);
7605
7606 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"
, 7607); MOZ_PretendNoReturn(); } } while (0)
7607 "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"
, 7607); MOZ_PretendNoReturn(); } } while (0)
;
7608 }
7609 }
7610
7611 nsCOMPtr<nsPIDOMWindowInner> privWinInner = privWin->GetCurrentInnerWindow();
7612
7613 // If parent is suspended, increase suspension count.
7614 // This can't be done as early as event suppression since this
7615 // depends on docshell tree.
7616 privWinInner->SyncStateFromParentWindow();
7617
7618 // Now that all of the child docshells have been put into place, we can
7619 // restart the timers for the window and all of the child frames.
7620 privWinInner->Resume();
7621
7622 // Now that we have found the inner window of the page restored
7623 // from the history, we have to make sure that
7624 // performance.navigation.type is 2.
7625 Performance* performance = privWinInner->GetPerformance();
7626 if (performance) {
7627 performance->GetDOMTiming()->NotifyRestoreStart();
7628 }
7629
7630 // Restore the refresh URI list. The refresh timers will be restarted
7631 // when EndPageLoad() is called.
7632 mRefreshURIList = refreshURIList;
7633
7634 // Meta-refresh timers have been restarted for this shell, but not
7635 // for our children. Walk the child shells and restart their timers.
7636 for (auto* childDocLoader : mChildList.ForwardRange()) {
7637 nsCOMPtr<nsIDocShell> child = do_QueryObject(childDocLoader);
7638 if (child) {
7639 child->ResumeRefreshURIs();
7640 }
7641 }
7642
7643 // Make sure this presentation is the same size as the previous
7644 // presentation. If this is not the same size we showed it at last time,
7645 // then we need to resize the widget.
7646
7647 // XXXbryner This interacts poorly with Firefox's infobar. If the old
7648 // presentation had the infobar visible, then we will resize the new
7649 // presentation to that smaller size. However, firing the locationchanged
7650 // event will hide the infobar, which will immediately resize the window
7651 // back to the larger size. A future optimization might be to restore
7652 // the presentation at the "wrong" size, then fire the locationchanged
7653 // event and check whether the docshell's new size is the same as the
7654 // cached viewer size (skipping the resize if they are equal).
7655
7656 if (newRootView) {
7657 if (!newBounds.IsEmpty() && !newBounds.IsEqualEdges(oldBounds)) {
7658 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)
7659 ("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)
7660 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)
;
7661 mDocumentViewer->SetBounds(newBounds);
7662 } else {
7663 nsIScrollableFrame* rootScrollFrame =
7664 presShell->GetRootScrollFrameAsScrollable();
7665 if (rootScrollFrame) {
7666 rootScrollFrame->PostScrolledAreaEventForCurrentArea();
7667 }
7668 }
7669 }
7670
7671 // The FinishRestore call below can kill these, null them out so we don't
7672 // have invalid pointer lying around.
7673 newRootView = rootViewSibling = rootViewParent = nullptr;
7674 newVM = nullptr;
7675
7676 // If the IsUnderHiddenEmbedderElement() state has been changed, we need to
7677 // update it.
7678 if (oldPresShell && presShell &&
7679 presShell->IsUnderHiddenEmbedderElement() !=
7680 oldPresShell->IsUnderHiddenEmbedderElement()) {
7681 presShell->SetIsUnderHiddenEmbedderElement(
7682 oldPresShell->IsUnderHiddenEmbedderElement());
7683 }
7684
7685 // Simulate the completion of the load.
7686 nsDocShell::FinishRestore();
7687
7688 // Restart plugins, and paint the content.
7689 if (presShell) {
7690 presShell->Thaw();
7691 }
7692
7693 return privWin->FireDelayedDOMEvents(true);
7694}
7695
7696nsresult nsDocShell::CreateDocumentViewer(const nsACString& aContentType,
7697 nsIRequest* aRequest,
7698 nsIStreamListener** aContentHandler) {
7699 if (DocGroup::TryToLoadIframesInBackground()) {
7700 ResetToFirstLoad();
7701 }
7702
7703 *aContentHandler = nullptr;
7704
7705 if (!mTreeOwner || mIsBeingDestroyed) {
7706 // If we don't have a tree owner, then we're in the process of being
7707 // destroyed. Rather than continue trying to load something, just give up.
7708 return NS_ERROR_DOCSHELL_DYING;
7709 }
7710
7711 if (!mBrowsingContext->AncestorsAreCurrent() ||
7712 mBrowsingContext->IsInBFCache()) {
7713 mBrowsingContext->RemoveRootFromBFCacheSync();
7714 return NS_ERROR_NOT_AVAILABLE;
7715 }
7716
7717 // Can we check the content type of the current content viewer
7718 // and reuse it without destroying it and re-creating it?
7719
7720 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"
, 7720); MOZ_PretendNoReturn(); } } while (0)
;
7721
7722 // Instantiate the content viewer object
7723 nsCOMPtr<nsIDocumentViewer> viewer;
7724 nsresult rv = NewDocumentViewerObj(aContentType, aRequest, mLoadGroup,
7725 aContentHandler, getter_AddRefs(viewer));
7726
7727 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
7728 return rv;
7729 }
7730
7731 // Notify the current document that it is about to be unloaded!!
7732 //
7733 // It is important to fire the unload() notification *before* any state
7734 // is changed within the DocShell - otherwise, javascript will get the
7735 // wrong information :-(
7736 //
7737
7738 if (mSavingOldViewer) {
7739 // We determined that it was safe to cache the document presentation
7740 // at the time we initiated the new load. We need to check whether
7741 // it's still safe to do so, since there may have been DOM mutations
7742 // or new requests initiated.
7743 RefPtr<Document> doc = viewer->GetDocument();
7744 mSavingOldViewer = CanSavePresentation(
7745 mLoadType, aRequest, doc, /* aReportBFCacheComboTelemetry */ false);
7746 }
7747
7748 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"
, 7748); MOZ_PretendNoReturn(); } } while (0)
;
7749
7750 nsCOMPtr<nsIChannel> aOpenedChannel = do_QueryInterface(aRequest);
7751 if (aOpenedChannel) {
7752 aOpenedChannel->GetURI(getter_AddRefs(mLoadingURI));
7753 }
7754
7755 // Grab the current URI, we need to pass it to Embed, and OnNewURI will reset
7756 // it before we do call Embed.
7757 nsCOMPtr<nsIURI> previousURI = mCurrentURI;
7758
7759 FirePageHideNotification(!mSavingOldViewer);
7760 if (mIsBeingDestroyed) {
7761 // Force to stop the newly created orphaned viewer.
7762 viewer->Stop();
7763 return NS_ERROR_DOCSHELL_DYING;
7764 }
7765 mLoadingURI = nullptr;
7766
7767 // Set mFiredUnloadEvent = false so that the unload handler for the
7768 // *new* document will fire.
7769 mFiredUnloadEvent = false;
7770
7771 // we've created a new document so go ahead and call
7772 // OnNewURI(), but don't fire OnLocationChange()
7773 // notifications before we've called Embed(). See bug 284993.
7774 mURIResultedInDocument = true;
7775 bool errorOnLocationChangeNeeded = false;
7776 nsCOMPtr<nsIChannel> failedChannel = mFailedChannel;
7777 nsCOMPtr<nsIURI> failedURI;
7778
7779 if (mLoadType == LOAD_ERROR_PAGE) {
7780 // We need to set the SH entry and our current URI here and not
7781 // at the moment we load the page. We want the same behavior
7782 // of Stop() as for a normal page load. See bug 514232 for details.
7783
7784 // Revert mLoadType to load type to state the page load failed,
7785 // following function calls need it.
7786 mLoadType = mFailedLoadType;
7787
7788 Document* doc = viewer->GetDocument();
7789 if (doc) {
7790 doc->SetFailedChannel(failedChannel);
7791 }
7792
7793 nsCOMPtr<nsIPrincipal> triggeringPrincipal;
7794 if (failedChannel) {
7795 // Make sure we have a URI to set currentURI.
7796 NS_GetFinalChannelURI(failedChannel, getter_AddRefs(failedURI));
7797 } else {
7798 // if there is no failed channel we have to explicitly provide
7799 // a triggeringPrincipal for the history entry.
7800 triggeringPrincipal = nsContentUtils::GetSystemPrincipal();
7801 }
7802
7803 if (!failedURI) {
7804 failedURI = mFailedURI;
7805 }
7806 if (!failedURI) {
7807 // We need a URI object to store a session history entry, so make up a URI
7808 NS_NewURI(getter_AddRefs(failedURI), "about:blank");
7809 }
7810
7811 // When we don't have failedURI, something wrong will happen. See
7812 // bug 291876.
7813 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"
, 7813); AnnotateMozCrashReason("MOZ_ASSERT" "(" "failedURI" ") ("
"We don't have a URI for history APIs." ")"); do { *((volatile
int*)__null) = 7813; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
7814
7815 mFailedChannel = nullptr;
7816 mFailedURI = nullptr;
7817
7818 // Create an shistory entry for the old load.
7819 if (failedURI) {
7820 errorOnLocationChangeNeeded =
7821 OnNewURI(failedURI, failedChannel, triggeringPrincipal, nullptr,
7822 nullptr, nullptr, false, false);
7823 }
7824
7825 // Be sure to have a correct mLSHE, it may have been cleared by
7826 // EndPageLoad. See bug 302115.
7827 ChildSHistory* shistory = GetSessionHistory();
7828 if (!mozilla::SessionHistoryInParent() && shistory && !mLSHE) {
7829 int32_t idx = shistory->LegacySHistory()->GetRequestedIndex();
7830 if (idx == -1) {
7831 idx = shistory->Index();
7832 }
7833 shistory->LegacySHistory()->GetEntryAtIndex(idx, getter_AddRefs(mLSHE));
7834 }
7835
7836 mLoadType = LOAD_ERROR_PAGE;
7837 }
7838
7839 nsCOMPtr<nsIURI> finalURI;
7840 // If this a redirect, use the final url (uri)
7841 // else use the original url
7842 //
7843 // Note that this should match what documents do (see Document::Reset).
7844 NS_GetFinalChannelURI(aOpenedChannel, getter_AddRefs(finalURI));
7845
7846 bool onLocationChangeNeeded = false;
7847 if (finalURI) {
7848 // Pass false for aCloneSHChildren, since we're loading a new page here.
7849 onLocationChangeNeeded = OnNewURI(finalURI, aOpenedChannel, nullptr,
7850 nullptr, nullptr, nullptr, true, false);
7851 }
7852
7853 // let's try resetting the load group if we need to...
7854 nsCOMPtr<nsILoadGroup> currentLoadGroup;
7855 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"
, 7857); return NS_ERROR_FAILURE; } } while (false)
7856 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"
, 7857); return NS_ERROR_FAILURE; } } while (false)
7857 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"
, 7857); return NS_ERROR_FAILURE; } } while (false)
;
7858
7859 if (currentLoadGroup != mLoadGroup) {
7860 nsLoadFlags loadFlags = 0;
7861
7862 // Cancel any URIs that are currently loading...
7863 // XXX: Need to do this eventually Stop();
7864 //
7865 // Retarget the document to this loadgroup...
7866 //
7867 /* First attach the channel to the right loadgroup
7868 * and then remove from the old loadgroup. This
7869 * puts the notifications in the right order and
7870 * we don't null-out mLSHE in OnStateChange() for
7871 * all redirected urls
7872 */
7873 aOpenedChannel->SetLoadGroup(mLoadGroup);
7874
7875 // Mark the channel as being a document URI...
7876 aOpenedChannel->GetLoadFlags(&loadFlags);
7877 loadFlags |= nsIChannel::LOAD_DOCUMENT_URI;
7878 nsCOMPtr<nsILoadInfo> loadInfo = aOpenedChannel->LoadInfo();
7879 if (SandboxFlagsImplyCookies(loadInfo->GetSandboxFlags())) {
7880 loadFlags |= nsIRequest::LOAD_DOCUMENT_NEEDS_COOKIE;
7881 }
7882
7883 aOpenedChannel->SetLoadFlags(loadFlags);
7884
7885 mLoadGroup->AddRequest(aRequest, nullptr);
7886 if (currentLoadGroup) {
7887 currentLoadGroup->RemoveRequest(aRequest, nullptr, NS_BINDING_RETARGETED);
7888 }
7889
7890 // Update the notification callbacks, so that progress and
7891 // status information are sent to the right docshell...
7892 aOpenedChannel->SetNotificationCallbacks(this);
7893 }
7894
7895 if (DocGroup::TryToLoadIframesInBackground()) {
7896 if ((!mDocumentViewer || GetDocument()->IsInitialDocument()) &&
7897 IsSubframe()) {
7898 // At this point, we know we just created a new iframe document based on
7899 // the response from the server, and we check if it's a cross-domain
7900 // iframe
7901
7902 RefPtr<Document> newDoc = viewer->GetDocument();
7903
7904 RefPtr<nsDocShell> parent = GetInProcessParentDocshell();
7905 nsCOMPtr<nsIPrincipal> parentPrincipal =
7906 parent->GetDocument()->NodePrincipal();
7907 nsCOMPtr<nsIPrincipal> thisPrincipal = newDoc->NodePrincipal();
7908
7909 SiteIdentifier parentSite;
7910 SiteIdentifier thisSite;
7911
7912 nsresult rv =
7913 BasePrincipal::Cast(parentPrincipal)->GetSiteIdentifier(parentSite);
7914 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"
, 7914); return rv; } } while (false)
;
7915
7916 rv = BasePrincipal::Cast(thisPrincipal)->GetSiteIdentifier(thisSite);
7917 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"
, 7917); return rv; } } while (false)
;
7918
7919 if (!parentSite.Equals(thisSite)) {
7920 if (profiler_thread_is_being_profiled_for_markers()) {
7921 nsCOMPtr<nsIURI> prinURI;
7922 BasePrincipal::Cast(thisPrincipal)->GetURI(getter_AddRefs(prinURI));
7923 nsPrintfCString marker(
7924 "Iframe loaded in background: %s",
7925 nsContentUtils::TruncatedURLForDisplay(prinURI).get());
7926 PROFILER_MARKER_TEXT("Background Iframe", DOM, {}, marker)do { ; do { if (profiler_is_collecting_markers()) { ::profiler_add_marker_impl
("Background Iframe", ::geckoprofiler::category::DOM, {}, ::geckoprofiler
::markers::TextMarker{}, marker); } } while (false); } while (
false)
;
7927 }
7928 SetBackgroundLoadIframe();
7929 }
7930 }
7931 }
7932
7933 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"
, 7936); return NS_ERROR_FAILURE; } } while (false)
7934 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"
, 7936); return NS_ERROR_FAILURE; } } while (false)
7935 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"
, 7936); return NS_ERROR_FAILURE; } } while (false)
7936 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"
, 7936); return NS_ERROR_FAILURE; } } while (false)
;
7937
7938 if (!mBrowsingContext->GetHasLoadedNonInitialDocument()) {
7939 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"
, 7939); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "false"
") (" "NS_SUCCEEDED(mBrowsingContext->SetHasLoadedNonInitialDocument(true))"
")"); do { *((volatile int*)__null) = 7939; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
7940 }
7941
7942 if (TreatAsBackgroundLoad()) {
7943 nsCOMPtr<nsIRunnable> triggerParentCheckDocShell =
7944 NewRunnableMethod("nsDocShell::TriggerParentCheckDocShellIsEmpty", this,
7945 &nsDocShell::TriggerParentCheckDocShellIsEmpty);
7946 nsresult rv = NS_DispatchToCurrentThread(triggerParentCheckDocShell);
7947 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"
, 7947); return rv; } } while (false)
;
7948 }
7949
7950 mSavedRefreshURIList = nullptr;
7951 mSavingOldViewer = false;
7952 mEODForCurrentDocument = false;
7953
7954 // if this document is part of a multipart document,
7955 // the ID can be used to distinguish it from the other parts.
7956 nsCOMPtr<nsIMultiPartChannel> multiPartChannel(do_QueryInterface(aRequest));
7957 if (multiPartChannel) {
7958 if (PresShell* presShell = GetPresShell()) {
7959 if (Document* doc = presShell->GetDocument()) {
7960 uint32_t partID;
7961 multiPartChannel->GetPartID(&partID);
7962 doc->SetPartID(partID);
7963 }
7964 }
7965 }
7966
7967 if (errorOnLocationChangeNeeded) {
7968 FireOnLocationChange(this, failedChannel, failedURI,
7969 LOCATION_CHANGE_ERROR_PAGE);
7970 } else if (onLocationChangeNeeded) {
7971 uint32_t locationFlags =
7972 (mLoadType & LOAD_CMD_RELOAD) ? uint32_t(LOCATION_CHANGE_RELOAD) : 0;
7973 FireOnLocationChange(this, aRequest, mCurrentURI, locationFlags);
7974 }
7975
7976 return NS_OK;
7977}
7978
7979nsresult nsDocShell::NewDocumentViewerObj(const nsACString& aContentType,
7980 nsIRequest* aRequest,
7981 nsILoadGroup* aLoadGroup,
7982 nsIStreamListener** aContentHandler,
7983 nsIDocumentViewer** aViewer) {
7984 nsCOMPtr<nsIChannel> aOpenedChannel = do_QueryInterface(aRequest);
7985
7986 nsCOMPtr<nsIDocumentLoaderFactory> docLoaderFactory =
7987 nsContentUtils::FindInternalDocumentViewer(aContentType);
7988 if (!docLoaderFactory) {
7989 return NS_ERROR_FAILURE;
7990 }
7991
7992 // Now create an instance of the content viewer nsLayoutDLF makes the
7993 // determination if it should be a "view-source" instead of "view"
7994 nsresult rv = docLoaderFactory->CreateInstance(
7995 "view", aOpenedChannel, aLoadGroup, aContentType, this, nullptr,
7996 aContentHandler, aViewer);
7997 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"
, 7997); return rv; } } while (false)
;
7998
7999 (*aViewer)->SetContainer(this);
8000 return NS_OK;
8001}
8002
8003nsresult nsDocShell::SetupNewViewer(nsIDocumentViewer* aNewViewer,
8004 WindowGlobalChild* aWindowActor) {
8005 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"
, 8005); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mIsBeingDestroyed"
")"); do { *((volatile int*)__null) = 8005; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8006
8007 //
8008 // Copy content viewer state from previous or parent content viewer.
8009 //
8010 // The following logic is mirrored in nsHTMLDocument::StartDocumentLoad!
8011 //
8012 // Do NOT to maintain a reference to the old content viewer outside
8013 // of this "copying" block, or it will not be destroyed until the end of
8014 // this routine and all <SCRIPT>s and event handlers fail! (bug 20315)
8015 //
8016 // In this block of code, if we get an error result, we return it
8017 // but if we get a null pointer, that's perfectly legal for parent
8018 // and parentContentViewer.
8019 //
8020
8021 int32_t x = 0;
8022 int32_t y = 0;
8023 int32_t cx = 0;
8024 int32_t cy = 0;
8025
8026 // This will get the size from the current content viewer or from the
8027 // Init settings
8028 DoGetPositionAndSize(&x, &y, &cx, &cy);
8029
8030 nsCOMPtr<nsIDocShellTreeItem> parentAsItem;
8031 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"
, 8032); return NS_ERROR_FAILURE; } } while (false)
8032 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"
, 8032); return NS_ERROR_FAILURE; } } while (false)
;
8033 nsCOMPtr<nsIDocShell> parent(do_QueryInterface(parentAsItem));
8034
8035 const Encoding* reloadEncoding = nullptr;
8036 int32_t reloadEncodingSource = kCharsetUninitialized;
8037 // |newMUDV| also serves as a flag to set the data from the above vars
8038 nsCOMPtr<nsIDocumentViewer> newViewer;
8039
8040 if (mDocumentViewer || parent) {
8041 nsCOMPtr<nsIDocumentViewer> oldViewer;
8042 if (mDocumentViewer) {
8043 // Get any interesting state from old content viewer
8044 // XXX: it would be far better to just reuse the document viewer ,
8045 // since we know we're just displaying the same document as before
8046 oldViewer = mDocumentViewer;
8047
8048 // Tell the old content viewer to hibernate in session history when
8049 // it is destroyed.
8050
8051 if (mSavingOldViewer && NS_FAILED(CaptureState())((bool)(__builtin_expect(!!(NS_FAILED_impl(CaptureState())), 0
)))
) {
8052 if (mOSHE) {
8053 mOSHE->SyncPresentationState();
8054 }
8055 mSavingOldViewer = false;
8056 }
8057 } else {
8058 // No old content viewer, so get state from parent's content viewer
8059 parent->GetDocViewer(getter_AddRefs(oldViewer));
8060 }
8061
8062 if (oldViewer) {
8063 newViewer = aNewViewer;
8064 if (newViewer) {
8065 reloadEncoding =
8066 oldViewer->GetReloadEncodingAndSource(&reloadEncodingSource);
8067 }
8068 }
8069 }
8070
8071 nscolor bgcolor = NS_RGBA(0, 0, 0, 0)((nscolor)(((0) << 24) | ((0) << 16) | ((0) <<
8) | (0)))
;
8072 bool isUnderHiddenEmbedderElement = false;
8073 // Ensure that the content viewer is destroyed *after* the GC - bug 71515
8074 nsCOMPtr<nsIDocumentViewer> viewer = mDocumentViewer;
8075 if (viewer) {
8076 // Stop any activity that may be happening in the old document before
8077 // releasing it...
8078 viewer->Stop();
8079
8080 // Try to extract the canvas background color from the old
8081 // presentation shell, so we can use it for the next document.
8082 if (PresShell* presShell = viewer->GetPresShell()) {
8083 bgcolor = presShell->GetCanvasBackground();
8084 isUnderHiddenEmbedderElement = presShell->IsUnderHiddenEmbedderElement();
8085 }
8086
8087 viewer->Close(mSavingOldViewer ? mOSHE.get() : nullptr);
8088 aNewViewer->SetPreviousViewer(viewer);
8089 }
8090 if (mOSHE && (!mDocumentViewer || !mSavingOldViewer)) {
8091 // We don't plan to save a viewer in mOSHE; tell it to drop
8092 // any other state it's holding.
8093 mOSHE->SyncPresentationState();
8094 }
8095
8096 mDocumentViewer = nullptr;
8097
8098 // Now that we're about to switch documents, forget all of our children.
8099 // Note that we cached them as needed up in CaptureState above.
8100 DestroyChildren();
8101
8102 mDocumentViewer = aNewViewer;
8103
8104 nsCOMPtr<nsIWidget> widget;
8105 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"
, 8105); return NS_ERROR_FAILURE; } } while (false)
;
8106
8107 nsIntRect bounds(x, y, cx, cy);
8108
8109 mDocumentViewer->SetNavigationTiming(mTiming);
8110
8111 if (NS_FAILED(mDocumentViewer->Init(widget, bounds, aWindowActor))((bool)(__builtin_expect(!!(NS_FAILED_impl(mDocumentViewer->
Init(widget, bounds, aWindowActor))), 0)))
) {
8112 nsCOMPtr<nsIDocumentViewer> viewer = mDocumentViewer;
8113 viewer->Close(nullptr);
8114 viewer->Destroy();
8115 mDocumentViewer = nullptr;
8116 SetCurrentURIInternal(nullptr);
8117 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"
, 8117)
;
8118 return NS_ERROR_FAILURE;
8119 }
8120
8121 // If we have old state to copy, set the old state onto the new content
8122 // viewer
8123 if (newViewer) {
8124 newViewer->SetReloadEncodingAndSource(reloadEncoding, reloadEncodingSource);
8125 }
8126
8127 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"
, 8127); return NS_ERROR_FAILURE; } } while (false)
;
8128
8129 // Stuff the bgcolor from the old pres shell into the new
8130 // pres shell. This improves page load continuity.
8131 if (RefPtr<PresShell> presShell = mDocumentViewer->GetPresShell()) {
8132 presShell->SetCanvasBackground(bgcolor);
8133 presShell->ActivenessMaybeChanged();
8134 if (isUnderHiddenEmbedderElement) {
8135 presShell->SetIsUnderHiddenEmbedderElement(isUnderHiddenEmbedderElement);
8136 }
8137 }
8138
8139 // XXX: It looks like the LayoutState gets restored again in Embed()
8140 // right after the call to SetupNewViewer(...)
8141
8142 // We don't show the mDocumentViewer yet, since we want to draw the old page
8143 // until we have enough of the new page to show. Just return with the new
8144 // viewer still set to hidden.
8145
8146 return NS_OK;
8147}
8148
8149void nsDocShell::SetDocCurrentStateObj(nsISHEntry* aShEntry,
8150 SessionHistoryInfo* aInfo) {
8151 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"
, 8151); return; } } while (false)
;
8152
8153 RefPtr<Document> document = GetDocument();
8154 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"
, 8154); return; } } while (false)
;
8155
8156 nsCOMPtr<nsIStructuredCloneContainer> scContainer;
8157 if (mozilla::SessionHistoryInParent()) {
8158 // If aInfo is null, just set the document's state object to null.
8159 if (aInfo) {
8160 scContainer = aInfo->GetStateData();
8161 }
8162 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)
8163 ("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)
;
8164 } else {
8165 if (aShEntry) {
8166 scContainer = aShEntry->GetStateData();
8167
8168 // If aShEntry is null, just set the document's state object to null.
8169 }
8170 }
8171
8172 // It's OK for scContainer too be null here; that just means there's no
8173 // state data associated with this history entry.
8174 document->SetStateObject(scContainer);
8175}
8176
8177nsresult nsDocShell::CheckLoadingPermissions() {
8178 // This method checks whether the caller may load content into
8179 // this docshell. Even though we've done our best to hide windows
8180 // from code that doesn't have the right to access them, it's
8181 // still possible for an evil site to open a window and access
8182 // frames in the new window through window.frames[] (which is
8183 // allAccess for historic reasons), so we still need to do this
8184 // check on load.
8185 nsresult rv = NS_OK;
8186
8187 if (!IsSubframe()) {
8188 // We're not a frame. Permit all loads.
8189 return rv;
8190 }
8191
8192 // Note - The check for a current JSContext here isn't necessarily sensical.
8193 // It's just designed to preserve the old semantics during a mass-conversion
8194 // patch.
8195 if (!nsContentUtils::GetCurrentJSContext()) {
8196 return NS_OK;
8197 }
8198
8199 // Check if the caller is from the same origin as this docshell,
8200 // or any of its ancestors.
8201 for (RefPtr<BrowsingContext> bc = mBrowsingContext; bc;
8202 bc = bc->GetParent()) {
8203 // If the BrowsingContext is not in process, then it
8204 // is true by construction that its principal will not
8205 // subsume the current docshell principal.
8206 if (!bc->IsInProcess()) {
8207 continue;
8208 }
8209
8210 nsCOMPtr<nsIScriptGlobalObject> sgo =
8211 bc->GetDocShell()->GetScriptGlobalObject();
8212 nsCOMPtr<nsIScriptObjectPrincipal> sop(do_QueryInterface(sgo));
8213
8214 nsIPrincipal* p;
8215 if (!sop || !(p = sop->GetPrincipal())) {
8216 return NS_ERROR_UNEXPECTED;
8217 }
8218
8219 if (nsContentUtils::SubjectPrincipal()->Subsumes(p)) {
8220 // Same origin, permit load
8221 return NS_OK;
8222 }
8223 }
8224
8225 return NS_ERROR_DOM_PROP_ACCESS_DENIED;
8226}
8227
8228//*****************************************************************************
8229// nsDocShell: Site Loading
8230//*****************************************************************************
8231
8232void nsDocShell::CopyFavicon(nsIURI* aOldURI, nsIURI* aNewURI,
8233 bool aInPrivateBrowsing) {
8234 if (XRE_IsContentProcess()) {
8235 dom::ContentChild* contentChild = dom::ContentChild::GetSingleton();
8236 if (contentChild) {
8237 contentChild->SendCopyFavicon(aOldURI, aNewURI, aInPrivateBrowsing);
8238 }
8239 return;
8240 }
8241
8242#ifdef MOZ_PLACES1
8243 nsCOMPtr<nsIFaviconService> favSvc =
8244 do_GetService("@mozilla.org/browser/favicon-service;1");
8245 if (favSvc) {
8246 favSvc->CopyFavicons(aOldURI, aNewURI,
8247 aInPrivateBrowsing
8248 ? nsIFaviconService::FAVICON_LOAD_PRIVATE
8249 : nsIFaviconService::FAVICON_LOAD_NON_PRIVATE,
8250 nullptr);
8251 }
8252#endif
8253}
8254
8255class InternalLoadEvent : public Runnable {
8256 public:
8257 InternalLoadEvent(nsDocShell* aDocShell, nsDocShellLoadState* aLoadState)
8258 : mozilla::Runnable("InternalLoadEvent"),
8259 mDocShell(aDocShell),
8260 mLoadState(aLoadState) {
8261 // For events, both target and filename should be the version of "null" they
8262 // expect. By the time the event is fired, both window targeting and file
8263 // downloading have been handled, so we should never have an internal load
8264 // event that retargets or had a download.
8265 mLoadState->SetTarget(u""_ns);
8266 mLoadState->SetFileName(VoidString());
8267 }
8268
8269 NS_IMETHODvirtual nsresult
8270 Run() override {
8271#ifndef ANDROID
8272 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"
, 8273); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mLoadState->TriggeringPrincipal()"
") (" "InternalLoadEvent: Should always have a principal here"
")"); do { *((volatile int*)__null) = 8273; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
8273 "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"
, 8273); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mLoadState->TriggeringPrincipal()"
") (" "InternalLoadEvent: Should always have a principal here"
")"); do { *((volatile int*)__null) = 8273; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8274#endif
8275 return mDocShell->InternalLoad(mLoadState);
8276 }
8277
8278 private:
8279 RefPtr<nsDocShell> mDocShell;
8280 RefPtr<nsDocShellLoadState> mLoadState;
8281};
8282
8283/**
8284 * Returns true if we started an asynchronous load (i.e., from the network), but
8285 * the document we're loading there hasn't yet become this docshell's active
8286 * document.
8287 *
8288 * When JustStartedNetworkLoad is true, you should be careful about modifying
8289 * mLoadType and mLSHE. These are both set when the asynchronous load first
8290 * starts, and the load expects that, when it eventually runs InternalLoad,
8291 * mLoadType and mLSHE will have their original values.
8292 */
8293bool nsDocShell::JustStartedNetworkLoad() {
8294 return mDocumentRequest && mDocumentRequest != GetCurrentDocChannel();
8295}
8296
8297// The contentType will be INTERNAL_(I)FRAME if this docshell is for a
8298// non-toplevel browsing context in spec terms. (frame, iframe, <object>,
8299// <embed>, etc)
8300//
8301// This return value will be used when we call NS_CheckContentLoadPolicy, and
8302// later when we call DoURILoad.
8303nsContentPolicyType nsDocShell::DetermineContentType() {
8304 if (!IsSubframe()) {
8305 return nsIContentPolicy::TYPE_DOCUMENT;
8306 }
8307
8308 const auto& maybeEmbedderElementType =
8309 GetBrowsingContext()->GetEmbedderElementType();
8310 if (!maybeEmbedderElementType) {
8311 // If the EmbedderElementType hasn't been set yet, just assume we're
8312 // an iframe since that's more common.
8313 return nsIContentPolicy::TYPE_INTERNAL_IFRAME;
8314 }
8315
8316 return maybeEmbedderElementType->EqualsLiteral("iframe")
8317 ? nsIContentPolicy::TYPE_INTERNAL_IFRAME
8318 : nsIContentPolicy::TYPE_INTERNAL_FRAME;
8319}
8320
8321bool nsDocShell::NoopenerForceEnabled() {
8322 // If current's top-level browsing context's active document's
8323 // cross-origin-opener-policy is "same-origin" or "same-origin + COEP" then
8324 // if currentDoc's origin is not same origin with currentDoc's top-level
8325 // origin, noopener is force enabled, and name is cleared to "_blank".
8326 auto topPolicy = mBrowsingContext->Top()->GetOpenerPolicy();
8327 return (topPolicy == nsILoadInfo::OPENER_POLICY_SAME_ORIGIN ||
8328 topPolicy ==
8329 nsILoadInfo::
8330 OPENER_POLICY_SAME_ORIGIN_EMBEDDER_POLICY_REQUIRE_CORP) &&
8331 !mBrowsingContext->SameOriginWithTop();
8332}
8333
8334nsresult nsDocShell::PerformRetargeting(nsDocShellLoadState* aLoadState) {
8335 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"
, 8335); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState"
") (" "need a load state!" ")"); do { *((volatile int*)__null
) = 8335; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
;
8336 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"
, 8336); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aLoadState->Target().IsEmpty()"
") (" "should have a target here!" ")"); do { *((volatile int
*)__null) = 8336; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
8337 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"
, 8338); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->TargetBrowsingContext().IsNull()"
") (" "should not have picked target yet" ")"); do { *((volatile
int*)__null) = 8338; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
8338 "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"
, 8338); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->TargetBrowsingContext().IsNull()"
") (" "should not have picked target yet" ")"); do { *((volatile
int*)__null) = 8338; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
8339
8340 nsresult rv = NS_OK;
8341 RefPtr<BrowsingContext> targetContext;
8342
8343 // Only _self, _parent, and _top are supported in noopener case. But we
8344 // have to be careful to not apply that to the noreferrer case. See bug
8345 // 1358469.
8346 bool allowNamedTarget =
8347 !aLoadState->HasInternalLoadFlags(INTERNAL_LOAD_FLAGS_NO_OPENER) ||
8348 aLoadState->HasInternalLoadFlags(INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER);
8349 if (allowNamedTarget ||
8350 aLoadState->Target().LowerCaseEqualsLiteral("_self") ||
8351 aLoadState->Target().LowerCaseEqualsLiteral("_parent") ||
8352 aLoadState->Target().LowerCaseEqualsLiteral("_top")) {
8353 Document* document = GetDocument();
8354 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"
, 8354); return NS_ERROR_FAILURE; } } while (false)
;
8355 WindowGlobalChild* wgc = document->GetWindowGlobalChild();
8356 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"
, 8356); return NS_ERROR_FAILURE; } } while (false)
;
8357 targetContext = wgc->FindBrowsingContextWithName(
8358 aLoadState->Target(), /* aUseEntryGlobalForAccessCheck */ false);
8359 }
8360
8361 if (!targetContext) {
8362 // If the targetContext doesn't exist, then this is a new docShell and we
8363 // should consider this a TYPE_DOCUMENT load
8364 //
8365 // For example, when target="_blank"
8366
8367 // If there's no targetContext, that means we are about to create a new
8368 // window. Perform a content policy check before creating the window. Please
8369 // note for all other docshell loads content policy checks are performed
8370 // within the contentSecurityManager when the channel is about to be
8371 // openend.
8372 nsISupports* requestingContext = nullptr;
8373 if (XRE_IsContentProcess()) {
8374 // In e10s the child process doesn't have access to the element that
8375 // contains the browsing context (because that element is in the chrome
8376 // process). So we just pass mScriptGlobal.
8377 requestingContext = ToSupports(mScriptGlobal);
8378 } else {
8379 // This is for loading non-e10s tabs and toplevel windows of various
8380 // sorts.
8381 // For the toplevel window cases, requestingElement will be null.
8382 nsCOMPtr<Element> requestingElement =
8383 mScriptGlobal->GetFrameElementInternal();
8384 requestingContext = requestingElement;
8385 }
8386
8387 // Ideally we should use the same loadinfo as within DoURILoad which
8388 // should match this one when both are applicable.
8389 nsCOMPtr<nsILoadInfo> secCheckLoadInfo =
8390 new LoadInfo(mScriptGlobal, aLoadState->URI(),
8391 aLoadState->TriggeringPrincipal(), requestingContext,
8392 nsILoadInfo::SEC_ONLY_FOR_EXPLICIT_CONTENTSEC_CHECK, 0);
8393
8394 // Since Content Policy checks are performed within docShell as well as
8395 // the ContentSecurityManager we need a reliable way to let certain
8396 // nsIContentPolicy consumers ignore duplicate calls.
8397 secCheckLoadInfo->SetSkipContentPolicyCheckForWebRequest(true);
8398
8399 int16_t shouldLoad = nsIContentPolicy::ACCEPT;
8400 rv = NS_CheckContentLoadPolicy(aLoadState->URI(), secCheckLoadInfo,
8401 ""_ns, // mime guess
8402 &shouldLoad);
8403
8404 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) || NS_CP_REJECTED(shouldLoad)((shouldLoad) != nsIContentPolicy::ACCEPT)) {
8405 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
8406 if (shouldLoad == nsIContentPolicy::REJECT_TYPE) {
8407 return NS_ERROR_CONTENT_BLOCKED_SHOW_ALT;
8408 }
8409 if (shouldLoad == nsIContentPolicy::REJECT_POLICY) {
8410 return NS_ERROR_BLOCKED_BY_POLICY;
8411 }
8412 }
8413
8414 return NS_ERROR_CONTENT_BLOCKED;
8415 }
8416 }
8417
8418 //
8419 // Resolve the window target before going any further...
8420 // If the load has been targeted to another DocShell, then transfer the
8421 // load to it...
8422 //
8423
8424 // We've already done our owner-inheriting. Mask out that bit, so we
8425 // don't try inheriting an owner from the target window if we came up
8426 // with a null owner above.
8427 aLoadState->UnsetInternalLoadFlag(INTERNAL_LOAD_FLAGS_INHERIT_PRINCIPAL);
8428
8429 if (!targetContext) {
8430 // If the docshell's document is sandboxed, only open a new window
8431 // if the document's SANDBOXED_AUXILLARY_NAVIGATION flag is not set.
8432 // (i.e. if allow-popups is specified)
8433 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"
, 8433); return NS_ERROR_FAILURE; } } while (false)
;
8434 Document* doc = mDocumentViewer->GetDocument();
8435
8436 const bool isDocumentAuxSandboxed =
8437 doc && (doc->GetSandboxFlags() & SANDBOXED_AUXILIARY_NAVIGATION);
8438
8439 if (isDocumentAuxSandboxed) {
8440 return NS_ERROR_DOM_INVALID_ACCESS_ERR;
8441 }
8442
8443 nsCOMPtr<nsPIDOMWindowOuter> win = GetWindow();
8444 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"
, 8444); return NS_ERROR_NOT_AVAILABLE; } } while (false)
;
8445
8446 RefPtr<BrowsingContext> newBC;
8447 nsAutoCString spec;
8448 aLoadState->URI()->GetSpec(spec);
8449
8450 // If we are a noopener load, we just hand the whole thing over to our
8451 // window.
8452 if (aLoadState->HasInternalLoadFlags(INTERNAL_LOAD_FLAGS_NO_OPENER) ||
8453 NoopenerForceEnabled()) {
8454 // Various asserts that we know to hold because NO_OPENER loads can only
8455 // happen for links.
8456 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"
, 8456); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aLoadState->LoadReplace()"
")"); do { *((volatile int*)__null) = 8456; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8457 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"
, 8458); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->PrincipalToInherit() == aLoadState->TriggeringPrincipal()"
")"); do { *((volatile int*)__null) = 8458; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
8458 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"
, 8458); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->PrincipalToInherit() == aLoadState->TriggeringPrincipal()"
")"); do { *((volatile int*)__null) = 8458; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8459 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"
, 8463); 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) = 8463; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
8460 ~(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"
, 8463); 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) = 8463; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
8461 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"
, 8463); 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) = 8463; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
8462 "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"
, 8463); 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) = 8463; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
8463 "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"
, 8463); 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) = 8463; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8464 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"
, 8465); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->IsFormSubmission()"
")"); do { *((volatile int*)__null) = 8465; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
8465 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"
, 8465); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->IsFormSubmission()"
")"); do { *((volatile int*)__null) = 8465; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
8466 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"
, 8466); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aLoadState->HeadersStream()"
")"); do { *((volatile int*)__null) = 8466; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8467 // If OnLinkClickSync was invoked inside the onload handler, the load
8468 // type would be set to LOAD_NORMAL_REPLACE; otherwise it should be
8469 // LOAD_LINK.
8470 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"
, 8471); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->LoadType() == LOAD_LINK || aLoadState->LoadType() == LOAD_NORMAL_REPLACE"
")"); do { *((volatile int*)__null) = 8471; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
8471 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"
, 8471); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->LoadType() == LOAD_LINK || aLoadState->LoadType() == LOAD_NORMAL_REPLACE"
")"); do { *((volatile int*)__null) = 8471; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8472 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"
, 8472); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aLoadState->LoadIsFromSessionHistory()"
")"); do { *((volatile int*)__null) = 8472; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8473 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"
, 8473); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->FirstParty()"
")"); do { *((volatile int*)__null) = 8473; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
; // Windowwatcher will assume this.
8474
8475 RefPtr<nsDocShellLoadState> loadState =
8476 new nsDocShellLoadState(aLoadState->URI());
8477
8478 // Set up our loadinfo so it will do the load as much like we would have
8479 // as possible.
8480 loadState->SetReferrerInfo(aLoadState->GetReferrerInfo());
8481 loadState->SetOriginalURI(aLoadState->OriginalURI());
8482
8483 Maybe<nsCOMPtr<nsIURI>> resultPrincipalURI;
8484 aLoadState->GetMaybeResultPrincipalURI(resultPrincipalURI);
8485
8486 loadState->SetMaybeResultPrincipalURI(resultPrincipalURI);
8487 loadState->SetKeepResultPrincipalURIIfSet(
8488 aLoadState->KeepResultPrincipalURIIfSet());
8489 // LoadReplace will always be false due to asserts above, skip setting
8490 // it.
8491 loadState->SetTriggeringPrincipal(aLoadState->TriggeringPrincipal());
8492 loadState->SetTriggeringSandboxFlags(
8493 aLoadState->TriggeringSandboxFlags());
8494 loadState->SetTriggeringWindowId(aLoadState->TriggeringWindowId());
8495 loadState->SetTriggeringStorageAccess(
8496 aLoadState->TriggeringStorageAccess());
8497 loadState->SetCsp(aLoadState->Csp());
8498 loadState->SetInheritPrincipal(aLoadState->HasInternalLoadFlags(
8499 INTERNAL_LOAD_FLAGS_INHERIT_PRINCIPAL));
8500 // Explicit principal because we do not want any guesses as to what the
8501 // principal to inherit is: it should be aTriggeringPrincipal.
8502 loadState->SetPrincipalIsExplicit(true);
8503 loadState->SetLoadType(aLoadState->LoadType());
8504 loadState->SetForceAllowDataURI(aLoadState->HasInternalLoadFlags(
8505 INTERNAL_LOAD_FLAGS_FORCE_ALLOW_DATA_URI));
8506
8507 loadState->SetHasValidUserGestureActivation(
8508 aLoadState->HasValidUserGestureActivation());
8509
8510 // Propagate POST data to the new load.
8511 loadState->SetPostDataStream(aLoadState->PostDataStream());
8512 loadState->SetIsFormSubmission(aLoadState->IsFormSubmission());
8513
8514 rv = win->Open(NS_ConvertUTF8toUTF16(spec),
8515 aLoadState->Target(), // window name
8516 u""_ns, // Features
8517 loadState,
8518 true, // aForceNoOpener
8519 getter_AddRefs(newBC));
8520 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"
, 8520); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!newBC" ")"
); do { *((volatile int*)__null) = 8520; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8521 return rv;
8522 }
8523
8524 rv = win->OpenNoNavigate(NS_ConvertUTF8toUTF16(spec),
8525 aLoadState->Target(), // window name
8526 u""_ns, // Features
8527 getter_AddRefs(newBC));
8528
8529 // In some cases the Open call doesn't actually result in a new
8530 // window being opened. We can detect these cases by examining the
8531 // document in |newBC|, if any.
8532 nsCOMPtr<nsPIDOMWindowOuter> piNewWin =
8533 newBC ? newBC->GetDOMWindow() : nullptr;
8534 if (piNewWin) {
8535 RefPtr<Document> newDoc = piNewWin->GetExtantDoc();
8536 if (!newDoc || newDoc->IsInitialDocument()) {
8537 aLoadState->SetInternalLoadFlag(INTERNAL_LOAD_FLAGS_FIRST_LOAD);
8538 }
8539 }
8540
8541 if (newBC) {
8542 targetContext = newBC;
8543 }
8544 }
8545 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"
, 8545); return rv; } } while (false)
;
8546 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"
, 8546); return rv; } } while (false)
;
8547
8548 // If our target BrowsingContext is still pending initialization, ignore the
8549 // navigation request targeting it.
8550 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"
, 8550)
) {
8551 return NS_OK;
8552 }
8553
8554 aLoadState->SetTargetBrowsingContext(targetContext);
8555 if (aLoadState->IsFormSubmission()) {
8556 aLoadState->SetLoadType(
8557 GetLoadTypeForFormSubmission(targetContext, aLoadState));
8558 }
8559
8560 //
8561 // Transfer the load to the target BrowsingContext... Clear the window target
8562 // name to the empty string to prevent recursive retargeting!
8563 //
8564 // No window target
8565 aLoadState->SetTarget(u""_ns);
8566 // No forced download
8567 aLoadState->SetFileName(VoidString());
8568 return targetContext->InternalLoad(aLoadState);
8569}
8570
8571static nsAutoCString RefMaybeNull(nsIURI* aURI) {
8572 nsAutoCString result;
8573 if (NS_FAILED(aURI->GetRef(result))((bool)(__builtin_expect(!!(NS_FAILED_impl(aURI->GetRef(result
))), 0)))
) {
8574 result.SetIsVoid(true);
8575 }
8576 return result;
8577}
8578
8579uint32_t nsDocShell::GetSameDocumentNavigationFlags(nsIURI* aNewURI) {
8580 uint32_t flags = LOCATION_CHANGE_SAME_DOCUMENT;
8581
8582 bool equal = false;
8583 if (mCurrentURI &&
8584 NS_SUCCEEDED(mCurrentURI->EqualsExceptRef(aNewURI, &equal))((bool)(__builtin_expect(!!(!NS_FAILED_impl(mCurrentURI->EqualsExceptRef
(aNewURI, &equal))), 1)))
&& equal &&
8585 RefMaybeNull(mCurrentURI) != RefMaybeNull(aNewURI)) {
8586 flags |= LOCATION_CHANGE_HASHCHANGE;
8587 }
8588
8589 return flags;
8590}
8591
8592bool nsDocShell::IsSameDocumentNavigation(nsDocShellLoadState* aLoadState,
8593 SameDocumentNavigationState& aState) {
8594 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"
, 8594); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState"
")"); do { *((volatile int*)__null) = 8594; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8595 if (!(aLoadState->LoadType() == LOAD_NORMAL ||
8596 aLoadState->LoadType() == LOAD_STOP_CONTENT ||
8597 LOAD_TYPE_HAS_FLAGS(aLoadState->LoadType(),((aLoadState->LoadType()) & ((LOAD_FLAGS_REPLACE_HISTORY
) << 16))
8598 LOAD_FLAGS_REPLACE_HISTORY)((aLoadState->LoadType()) & ((LOAD_FLAGS_REPLACE_HISTORY
) << 16))
||
8599 aLoadState->LoadType() == LOAD_HISTORY ||
8600 aLoadState->LoadType() == LOAD_LINK)) {
8601 return false;
8602 }
8603
8604 nsCOMPtr<nsIURI> currentURI = mCurrentURI;
8605
8606 nsresult rvURINew = aLoadState->URI()->GetRef(aState.mNewHash);
8607 if (NS_SUCCEEDED(rvURINew)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rvURINew)), 1)))) {
8608 rvURINew = aLoadState->URI()->GetHasRef(&aState.mNewURIHasRef);
8609 }
8610
8611 if (currentURI && NS_SUCCEEDED(rvURINew)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rvURINew)), 1)))) {
8612 nsresult rvURIOld = currentURI->GetRef(aState.mCurrentHash);
8613 if (NS_SUCCEEDED(rvURIOld)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rvURIOld)), 1)))) {
8614 rvURIOld = currentURI->GetHasRef(&aState.mCurrentURIHasRef);
8615 }
8616 if (NS_SUCCEEDED(rvURIOld)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rvURIOld)), 1)))) {
8617 if (NS_FAILED(currentURI->EqualsExceptRef(aLoadState->URI(),((bool)(__builtin_expect(!!(NS_FAILED_impl(currentURI->EqualsExceptRef
(aLoadState->URI(), &aState.mSameExceptHashes))), 0)))
8618 &aState.mSameExceptHashes))((bool)(__builtin_expect(!!(NS_FAILED_impl(currentURI->EqualsExceptRef
(aLoadState->URI(), &aState.mSameExceptHashes))), 0)))
) {
8619 aState.mSameExceptHashes = false;
8620 }
8621 }
8622 }
8623
8624 if (!aState.mSameExceptHashes && currentURI && NS_SUCCEEDED(rvURINew)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rvURINew)), 1)))) {
8625 // Maybe aLoadState->URI() came from the exposable form of currentURI?
8626 nsCOMPtr<nsIURI> currentExposableURI =
8627 nsIOService::CreateExposableURI(currentURI);
8628 nsresult rvURIOld = currentExposableURI->GetRef(aState.mCurrentHash);
8629 if (NS_SUCCEEDED(rvURIOld)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rvURIOld)), 1)))) {
8630 rvURIOld = currentExposableURI->GetHasRef(&aState.mCurrentURIHasRef);
8631 }
8632 if (NS_SUCCEEDED(rvURIOld)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rvURIOld)), 1)))) {
8633 if (NS_FAILED(currentExposableURI->EqualsExceptRef(((bool)(__builtin_expect(!!(NS_FAILED_impl(currentExposableURI
->EqualsExceptRef( aLoadState->URI(), &aState.mSameExceptHashes
))), 0)))
8634 aLoadState->URI(), &aState.mSameExceptHashes))((bool)(__builtin_expect(!!(NS_FAILED_impl(currentExposableURI
->EqualsExceptRef( aLoadState->URI(), &aState.mSameExceptHashes
))), 0)))
) {
8635 aState.mSameExceptHashes = false;
8636 }
8637 // HTTPS-Only Mode upgrades schemes from http to https in Necko, hence we
8638 // have to perform a special check here to avoid an actual navigation. If
8639 // HTTPS-Only Mode is enabled and the two URIs are same-origin (modulo the
8640 // fact that the new URI is currently http), then set mSameExceptHashes to
8641 // true and only perform a fragment navigation.
8642 if (!aState.mSameExceptHashes) {
8643 if (nsCOMPtr<nsIChannel> docChannel = GetCurrentDocChannel()) {
8644 nsCOMPtr<nsILoadInfo> docLoadInfo = docChannel->LoadInfo();
8645 if (!docLoadInfo->GetLoadErrorPage() &&
8646 nsHTTPSOnlyUtils::IsEqualURIExceptSchemeAndRef(
8647 currentExposableURI, aLoadState->URI(), docLoadInfo)) {
8648 uint32_t status = docLoadInfo->GetHttpsOnlyStatus();
8649 if (status & (nsILoadInfo::HTTPS_ONLY_UPGRADED_LISTENER_REGISTERED |
8650 nsILoadInfo::HTTPS_ONLY_UPGRADED_HTTPS_FIRST)) {
8651 // At this point the requested URI is for sure a fragment
8652 // navigation via HTTP and HTTPS-Only mode or HTTPS-First is
8653 // enabled. Also it is not interfering the upgrade order of
8654 // https://searchfox.org/mozilla-central/source/netwerk/base/nsNetUtil.cpp#2948-2953.
8655 // Since we are on an HTTPS site the fragment
8656 // navigation should also be an HTTPS.
8657 // For that reason we should upgrade the URI to HTTPS.
8658 aState.mSecureUpgradeURI = true;
8659 aState.mSameExceptHashes = true;
8660 }
8661 }
8662 }
8663 }
8664 }
8665 }
8666
8667 if (mozilla::SessionHistoryInParent()) {
8668 if (mActiveEntry && aLoadState->LoadIsFromSessionHistory()) {
8669 aState.mHistoryNavBetweenSameDoc = mActiveEntry->SharesDocumentWith(
8670 aLoadState->GetLoadingSessionHistoryInfo()->mInfo);
8671 }
8672 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)
8673 ("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)
8674 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)
;
8675 } else {
8676 if (mOSHE && aLoadState->LoadIsFromSessionHistory()) {
8677 // We're doing a history load.
8678
8679 mOSHE->SharesDocumentWith(aLoadState->SHEntry(),
8680 &aState.mHistoryNavBetweenSameDoc);
8681 }
8682 }
8683
8684 // A same document navigation happens when we navigate between two SHEntries
8685 // for the same document. We do a same document navigation under two
8686 // circumstances. Either
8687 //
8688 // a) we're navigating between two different SHEntries which share a
8689 // document, or
8690 //
8691 // b) we're navigating to a new shentry whose URI differs from the
8692 // current URI only in its hash, the new hash is non-empty, and
8693 // we're not doing a POST.
8694 //
8695 // The restriction that the SHEntries in (a) must be different ensures
8696 // that history.go(0) and the like trigger full refreshes, rather than
8697 // same document navigations.
8698 if (!mozilla::SessionHistoryInParent()) {
8699 bool doSameDocumentNavigation =
8700 (aState.mHistoryNavBetweenSameDoc && mOSHE != aLoadState->SHEntry()) ||
8701 (!aLoadState->SHEntry() && !aLoadState->PostDataStream() &&
8702 aState.mSameExceptHashes && aState.mNewURIHasRef);
8703 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)
8704 ("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)
8705 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)
;
8706 return doSameDocumentNavigation;
8707 }
8708
8709 if (aState.mHistoryNavBetweenSameDoc &&
8710 !aLoadState->GetLoadingSessionHistoryInfo()->mLoadingCurrentEntry) {
8711 return true;
8712 }
8713
8714 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)
8715 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)
8716 ("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)
8717 "!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)
8718 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)
8719 !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)
8720 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)
8721 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)
;
8722 return !aLoadState->LoadIsFromSessionHistory() &&
8723 !aLoadState->PostDataStream() && aState.mSameExceptHashes &&
8724 aState.mNewURIHasRef;
8725}
8726
8727nsresult nsDocShell::HandleSameDocumentNavigation(
8728 nsDocShellLoadState* aLoadState, SameDocumentNavigationState& aState,
8729 bool& aSameDocument) {
8730 aSameDocument = true;
8731#ifdef DEBUG1
8732 SameDocumentNavigationState state;
8733 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"
, 8733); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsSameDocumentNavigation(aLoadState, state)"
")"); do { *((volatile int*)__null) = 8733; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8734#endif
8735
8736 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)
8737 ("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)
8738 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)
8739 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)
;
8740
8741 RefPtr<Document> doc = GetDocument();
8742 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"
, 8742); return NS_ERROR_FAILURE; } } while (false)
;
8743 doc->DoNotifyPossibleTitleChange();
8744
8745 nsCOMPtr<nsIURI> currentURI = mCurrentURI;
8746
8747 // We need to upgrade the new URI from http: to https:
8748 nsCOMPtr<nsIURI> newURI = aLoadState->URI();
8749 if (aState.mSecureUpgradeURI) {
8750 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)
;
8751 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)
8752 ("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)
;
8753 }
8754
8755 if (StaticPrefs::dom_security_setdocumenturi()) {
8756 // check if aLoadState->URI(), principalURI, mCurrentURI are same origin
8757 // skip handling otherwise
8758 nsCOMPtr<nsIPrincipal> origPrincipal = doc->NodePrincipal();
8759 nsCOMPtr<nsIURI> principalURI = origPrincipal->GetURI();
8760 if (origPrincipal->GetIsNullPrincipal()) {
8761 nsCOMPtr<nsIPrincipal> precursor = origPrincipal->GetPrecursorPrincipal();
8762 if (precursor) {
8763 principalURI = precursor->GetURI();
8764 }
8765 }
8766
8767 auto isLoadableViaInternet = [](nsIURI* uri) {
8768 return (uri && (net::SchemeIsHTTP(uri) || net::SchemeIsHTTPS(uri)));
8769 };
8770
8771 if (isLoadableViaInternet(principalURI) &&
8772 isLoadableViaInternet(mCurrentURI) && isLoadableViaInternet(newURI)) {
8773 nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager();
8774 if (!NS_SUCCEEDED(((bool)(__builtin_expect(!!(!NS_FAILED_impl(ssm->CheckSameOriginURI
(newURI, principalURI, false, false))), 1)))
8775 ssm->CheckSameOriginURI(newURI, principalURI, false, false))((bool)(__builtin_expect(!!(!NS_FAILED_impl(ssm->CheckSameOriginURI
(newURI, principalURI, false, false))), 1)))
||
8776 !NS_SUCCEEDED(ssm->CheckSameOriginURI(mCurrentURI, principalURI,((bool)(__builtin_expect(!!(!NS_FAILED_impl(ssm->CheckSameOriginURI
(mCurrentURI, principalURI, false, false))), 1)))
8777 false, false))((bool)(__builtin_expect(!!(!NS_FAILED_impl(ssm->CheckSameOriginURI
(mCurrentURI, principalURI, false, false))), 1)))
) {
8778 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)
8779 ("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)
8780 "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)
8781 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)
;
8782 aSameDocument = false;
8783 return NS_OK;
8784 }
8785 }
8786 }
8787
8788#ifdef DEBUG1
8789 if (aState.mSameExceptHashes) {
8790 bool sameExceptHashes = false;
8791 currentURI->EqualsExceptRef(newURI, &sameExceptHashes);
8792 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"
, 8792); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sameExceptHashes"
")"); do { *((volatile int*)__null) = 8792; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8793 }
8794#endif
8795
8796 // Save the position of the scrollers.
8797 nsPoint scrollPos = GetCurScrollPos();
8798
8799 // Reset mLoadType to its original value once we exit this block, because this
8800 // same document navigation might have started after a normal, network load,
8801 // and we don't want to clobber its load type. See bug 737307.
8802 AutoRestore<uint32_t> loadTypeResetter(mLoadType);
8803
8804 // If a non-same-document-navigation (i.e., a network load) is pending, make
8805 // this a replacement load, so that we don't add a SHEntry here and the
8806 // network load goes into the SHEntry it expects to.
8807 if (JustStartedNetworkLoad() && (aLoadState->LoadType() & LOAD_CMD_NORMAL)) {
8808 mLoadType = LOAD_NORMAL_REPLACE;
8809 } else {
8810 mLoadType = aLoadState->LoadType();
8811 }
8812
8813 mURIResultedInDocument = true;
8814
8815 nsCOMPtr<nsISHEntry> oldLSHE = mLSHE;
8816
8817 // we need to assign aLoadState->SHEntry() to mLSHE right here, so that on
8818 // History loads, SetCurrentURI() called from OnNewURI() will send proper
8819 // onLocationChange() notifications to the browser to update back/forward
8820 // buttons.
8821 SetHistoryEntryAndUpdateBC(Some<nsISHEntry*>(aLoadState->SHEntry()),
8822 Nothing());
8823 UniquePtr<mozilla::dom::LoadingSessionHistoryInfo> oldLoadingEntry;
8824 mLoadingEntry.swap(oldLoadingEntry);
8825 if (aLoadState->GetLoadingSessionHistoryInfo()) {
8826 mLoadingEntry = MakeUnique<LoadingSessionHistoryInfo>(
8827 *aLoadState->GetLoadingSessionHistoryInfo());
8828 mNeedToReportActiveAfterLoadingBecomesActive = false;
8829 }
8830
8831 // Set the doc's URI according to the new history entry's URI.
8832 doc->SetDocumentURI(newURI);
8833
8834 /* This is a anchor traversal within the same page.
8835 * call OnNewURI() so that, this traversal will be
8836 * recorded in session and global history.
8837 */
8838 nsCOMPtr<nsIPrincipal> newURITriggeringPrincipal, newURIPrincipalToInherit,
8839 newURIPartitionedPrincipalToInherit;
8840 nsCOMPtr<nsIContentSecurityPolicy> newCsp;
8841 if (mozilla::SessionHistoryInParent() ? !!mActiveEntry : !!mOSHE) {
8842 if (mozilla::SessionHistoryInParent()) {
8843 newURITriggeringPrincipal = mActiveEntry->GetTriggeringPrincipal();
8844 newURIPrincipalToInherit = mActiveEntry->GetPrincipalToInherit();
8845 newURIPartitionedPrincipalToInherit =
8846 mActiveEntry->GetPartitionedPrincipalToInherit();
8847 newCsp = mActiveEntry->GetCsp();
8848 } else {
8849 newURITriggeringPrincipal = mOSHE->GetTriggeringPrincipal();
8850 newURIPrincipalToInherit = mOSHE->GetPrincipalToInherit();
8851 newURIPartitionedPrincipalToInherit =
8852 mOSHE->GetPartitionedPrincipalToInherit();
8853 newCsp = mOSHE->GetCsp();
8854 }
8855 } else {
8856 newURITriggeringPrincipal = aLoadState->TriggeringPrincipal();
8857 newURIPrincipalToInherit = doc->NodePrincipal();
8858 newURIPartitionedPrincipalToInherit = doc->PartitionedPrincipal();
8859 newCsp = doc->GetCsp();
8860 }
8861
8862 uint32_t locationChangeFlags = GetSameDocumentNavigationFlags(newURI);
8863
8864 // Pass true for aCloneSHChildren, since we're not
8865 // changing documents here, so all of our subframes are
8866 // still relevant to the new session history entry.
8867 //
8868 // It also makes OnNewURI(...) set LOCATION_CHANGE_SAME_DOCUMENT
8869 // flag on firing onLocationChange(...).
8870 // Anyway, aCloneSHChildren param is simply reflecting
8871 // doSameDocumentNavigation in this scope.
8872 //
8873 // Note: we'll actually fire onLocationChange later, in order to preserve
8874 // ordering of HistoryCommit() in the parent vs onLocationChange (bug
8875 // 1668126)
8876 bool locationChangeNeeded = OnNewURI(
8877 newURI, nullptr, newURITriggeringPrincipal, newURIPrincipalToInherit,
8878 newURIPartitionedPrincipalToInherit, newCsp, true, true);
8879
8880 nsCOMPtr<nsIInputStream> postData;
8881 uint32_t cacheKey = 0;
8882
8883 bool scrollRestorationIsManual = false;
8884 if (!mozilla::SessionHistoryInParent()) {
8885 if (mOSHE) {
8886 /* save current position of scroller(s) (bug 59774) */
8887 mOSHE->SetScrollPosition(scrollPos.x, scrollPos.y);
8888 scrollRestorationIsManual = mOSHE->GetScrollRestorationIsManual();
8889 // Get the postdata and page ident from the current page, if
8890 // the new load is being done via normal means. Note that
8891 // "normal means" can be checked for just by checking for
8892 // LOAD_CMD_NORMAL, given the loadType and allowScroll check
8893 // above -- it filters out some LOAD_CMD_NORMAL cases that we
8894 // wouldn't want here.
8895 if (aLoadState->LoadType() & LOAD_CMD_NORMAL) {
8896 postData = mOSHE->GetPostData();
8897 cacheKey = mOSHE->GetCacheKey();
8898 }
8899
8900 // Link our new SHEntry to the old SHEntry's back/forward
8901 // cache data, since the two SHEntries correspond to the
8902 // same document.
8903 if (mLSHE) {
8904 if (!aLoadState->LoadIsFromSessionHistory()) {
8905 // If we're not doing a history load, scroll restoration
8906 // should be inherited from the previous session history entry.
8907 SetScrollRestorationIsManualOnHistoryEntry(mLSHE,
8908 scrollRestorationIsManual);
8909 }
8910 mLSHE->AdoptBFCacheEntry(mOSHE);
8911 }
8912 }
8913 } else {
8914 if (mActiveEntry) {
8915 mActiveEntry->SetScrollPosition(scrollPos.x, scrollPos.y);
8916 if (mBrowsingContext) {
8917 CollectWireframe();
8918 if (XRE_IsParentProcess()) {
8919 SessionHistoryEntry* entry =
8920 mBrowsingContext->Canonical()->GetActiveSessionHistoryEntry();
8921 if (entry) {
8922 entry->SetScrollPosition(scrollPos.x, scrollPos.y);
8923 }
8924 } else {
8925 mozilla::Unused << ContentChild::GetSingleton()
8926 ->SendSessionHistoryEntryScrollPosition(
8927 mBrowsingContext, scrollPos.x,
8928 scrollPos.y);
8929 }
8930 }
8931 }
8932 if (mLoadingEntry) {
8933 if (!mLoadingEntry->mLoadIsFromSessionHistory) {
8934 // If we're not doing a history load, scroll restoration
8935 // should be inherited from the previous session history entry.
8936 // XXX This needs most probably tweaks once fragment navigation is
8937 // fixed to work with session-history-in-parent.
8938 SetScrollRestorationIsManualOnHistoryEntry(nullptr,
8939 scrollRestorationIsManual);
8940 }
8941 }
8942 }
8943
8944 // If we're doing a history load, use its scroll restoration state.
8945 if (aLoadState->LoadIsFromSessionHistory()) {
8946 if (mozilla::SessionHistoryInParent()) {
8947 scrollRestorationIsManual = aLoadState->GetLoadingSessionHistoryInfo()
8948 ->mInfo.GetScrollRestorationIsManual();
8949 } else {
8950 scrollRestorationIsManual =
8951 aLoadState->SHEntry()->GetScrollRestorationIsManual();
8952 }
8953 }
8954
8955 /* Assign mLSHE to mOSHE. This will either be a new entry created
8956 * by OnNewURI() for normal loads or aLoadState->SHEntry() for history
8957 * loads.
8958 */
8959 if (!mozilla::SessionHistoryInParent()) {
8960 if (mLSHE) {
8961 SetHistoryEntryAndUpdateBC(Nothing(), Some<nsISHEntry*>(mLSHE));
8962 // Save the postData obtained from the previous page
8963 // in to the session history entry created for the
8964 // anchor page, so that any history load of the anchor
8965 // page will restore the appropriate postData.
8966 if (postData) {
8967 mOSHE->SetPostData(postData);
8968 }
8969
8970 // Make sure we won't just repost without hitting the
8971 // cache first
8972 if (cacheKey != 0) {
8973 mOSHE->SetCacheKey(cacheKey);
8974 }
8975 }
8976
8977 /* Set the title for the SH entry for this target url so that
8978 * SH menus in go/back/forward buttons won't be empty for this.
8979 * Note, this happens on mOSHE (and mActiveEntry in the future) because of
8980 * the code above.
8981 * Note, when session history lives in the parent process, this does not
8982 * update the title there.
8983 */
8984 SetTitleOnHistoryEntry(false);
8985 } else {
8986 if (aLoadState->LoadIsFromSessionHistory()) {
8987 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)
8988 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)
8989 ("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)
8990 "%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)
8991 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)
;
8992
8993 nsCOMPtr<nsILayoutHistoryState> currentLayoutHistoryState;
8994 if (mActiveEntry) {
8995 currentLayoutHistoryState = mActiveEntry->GetLayoutHistoryState();
8996 }
8997
8998 UniquePtr<SessionHistoryInfo> previousActiveEntry(mActiveEntry.release());
8999 mActiveEntry = MakeUnique<SessionHistoryInfo>(mLoadingEntry->mInfo);
9000 if (currentLayoutHistoryState) {
9001 // Restore the existing nsILayoutHistoryState object, since it is
9002 // possibly being used by the layout. When doing a new load, the
9003 // shared state is copied from the existing active entry, so this
9004 // special case is needed only with the history loads.
9005 mActiveEntry->SetLayoutHistoryState(currentLayoutHistoryState);
9006 }
9007
9008 if (cacheKey != 0) {
9009 mActiveEntry->SetCacheKey(cacheKey);
9010 }
9011 // We're passing in mCurrentURI, which could be null. SessionHistoryCommit
9012 // does require a non-null uri if this is for a refresh load of the same
9013 // URI, but in that case mCurrentURI won't be null here.
9014 mBrowsingContext->SessionHistoryCommit(
9015 *mLoadingEntry, mLoadType, mCurrentURI, previousActiveEntry.get(),
9016 true, true,
9017 /* No expiration update on the same document loads*/
9018 false, cacheKey);
9019 // FIXME Need to set postdata.
9020
9021 // Set the title for the SH entry for this target url so that
9022 // SH menus in go/back/forward buttons won't be empty for this.
9023 // Note, when session history lives in the parent process, this does not
9024 // update the title there.
9025 SetTitleOnHistoryEntry(false);
9026 } else {
9027 Maybe<bool> scrollRestorationIsManual;
9028 if (mActiveEntry) {
9029 scrollRestorationIsManual.emplace(
9030 mActiveEntry->GetScrollRestorationIsManual());
9031
9032 // Get the postdata and page ident from the current page, if the new
9033 // load is being done via normal means. Note that "normal means" can be
9034 // checked for just by checking for LOAD_CMD_NORMAL, given the loadType
9035 // and allowScroll check above -- it filters out some LOAD_CMD_NORMAL
9036 // cases that we wouldn't want here.
9037 if (aLoadState->LoadType() & LOAD_CMD_NORMAL) {
9038 postData = mActiveEntry->GetPostData();
9039 cacheKey = mActiveEntry->GetCacheKey();
9040 }
9041 }
9042
9043 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)
9044 ("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)
9045 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)
;
9046 if (mActiveEntry) {
9047 mActiveEntry = MakeUnique<SessionHistoryInfo>(*mActiveEntry, newURI);
9048 } else {
9049 mActiveEntry = MakeUnique<SessionHistoryInfo>(
9050 newURI, newURITriggeringPrincipal, newURIPrincipalToInherit,
9051 newURIPartitionedPrincipalToInherit, newCsp, mContentTypeHint);
9052 }
9053
9054 // Save the postData obtained from the previous page in to the session
9055 // history entry created for the anchor page, so that any history load of
9056 // the anchor page will restore the appropriate postData.
9057 if (postData) {
9058 mActiveEntry->SetPostData(postData);
9059 }
9060
9061 // Make sure we won't just repost without hitting the
9062 // cache first
9063 if (cacheKey != 0) {
9064 mActiveEntry->SetCacheKey(cacheKey);
9065 }
9066
9067 // Set the title for the SH entry for this target url so that
9068 // SH menus in go/back/forward buttons won't be empty for this.
9069 mActiveEntry->SetTitle(mTitle);
9070
9071 if (scrollRestorationIsManual.isSome()) {
9072 mActiveEntry->SetScrollRestorationIsManual(
9073 scrollRestorationIsManual.value());
9074 }
9075
9076 if (LOAD_TYPE_HAS_FLAGS(mLoadType, LOAD_FLAGS_REPLACE_HISTORY)((mLoadType) & ((LOAD_FLAGS_REPLACE_HISTORY) << 16)
)
) {
9077 mBrowsingContext->ReplaceActiveSessionHistoryEntry(mActiveEntry.get());
9078 } else {
9079 mBrowsingContext->IncrementHistoryEntryCountForBrowsingContext();
9080 // FIXME We should probably just compute mChildOffset in the parent
9081 // instead of passing it over IPC here.
9082 mBrowsingContext->SetActiveSessionHistoryEntry(
9083 Some(scrollPos), mActiveEntry.get(), mLoadType, cacheKey);
9084 // FIXME Do we need to update mPreviousEntryIndex and mLoadedEntryIndex?
9085 }
9086 }
9087 }
9088
9089 if (locationChangeNeeded) {
9090 FireOnLocationChange(this, nullptr, newURI, locationChangeFlags);
9091 }
9092
9093 /* Restore the original LSHE if we were loading something
9094 * while same document navigation was initiated.
9095 */
9096 SetHistoryEntryAndUpdateBC(Some<nsISHEntry*>(oldLSHE), Nothing());
9097 mLoadingEntry.swap(oldLoadingEntry);
9098
9099 /* Set the title for the Global History entry for this anchor url.
9100 */
9101 UpdateGlobalHistoryTitle(newURI);
9102
9103 SetDocCurrentStateObj(mOSHE, mActiveEntry.get());
9104
9105 // Inform the favicon service that the favicon for oldURI also
9106 // applies to newURI.
9107 CopyFavicon(currentURI, newURI, UsePrivateBrowsing());
9108
9109 RefPtr<nsGlobalWindowOuter> scriptGlobal = mScriptGlobal;
9110 nsCOMPtr<nsPIDOMWindowInner> win =
9111 scriptGlobal ? scriptGlobal->GetCurrentInnerWindow() : nullptr;
9112
9113 // ScrollToAnchor doesn't necessarily cause us to scroll the window;
9114 // the function decides whether a scroll is appropriate based on the
9115 // arguments it receives. But even if we don't end up scrolling,
9116 // ScrollToAnchor performs other important tasks, such as informing
9117 // the presShell that we have a new hash. See bug 680257.
9118 nsresult rv = ScrollToAnchor(aState.mCurrentURIHasRef, aState.mNewURIHasRef,
9119 aState.mNewHash, aLoadState->LoadType());
9120 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"
, 9120); return rv; } } while (false)
;
9121
9122 /* restore previous position of scroller(s), if we're moving
9123 * back in history (bug 59774)
9124 */
9125 nscoord bx = 0;
9126 nscoord by = 0;
9127 bool needsScrollPosUpdate = false;
9128 if ((mozilla::SessionHistoryInParent() ? !!mActiveEntry : !!mOSHE) &&
9129 (aLoadState->LoadType() == LOAD_HISTORY ||
9130 aLoadState->LoadType() == LOAD_RELOAD_NORMAL) &&
9131 !scrollRestorationIsManual) {
9132 needsScrollPosUpdate = true;
9133 if (mozilla::SessionHistoryInParent()) {
9134 mActiveEntry->GetScrollPosition(&bx, &by);
9135 } else {
9136 mOSHE->GetScrollPosition(&bx, &by);
9137 }
9138 }
9139
9140 // Dispatch the popstate and hashchange events, as appropriate.
9141 //
9142 // The event dispatch below can cause us to re-enter script and
9143 // destroy the docshell, nulling out mScriptGlobal. Hold a stack
9144 // reference to avoid null derefs. See bug 914521.
9145 if (win) {
9146 // Fire a hashchange event URIs differ, and only in their hashes.
9147 bool doHashchange = aState.mSameExceptHashes &&
9148 (aState.mCurrentURIHasRef != aState.mNewURIHasRef ||
9149 !aState.mCurrentHash.Equals(aState.mNewHash));
9150
9151 if (aState.mHistoryNavBetweenSameDoc || doHashchange) {
9152 win->DispatchSyncPopState();
9153 }
9154
9155 if (needsScrollPosUpdate && win->HasActiveDocument()) {
9156 SetCurScrollPosEx(bx, by);
9157 }
9158
9159 if (doHashchange) {
9160 // Note that currentURI hasn't changed because it's on the
9161 // stack, so we can just use it directly as the old URI.
9162 win->DispatchAsyncHashchange(currentURI, newURI);
9163 }
9164 }
9165
9166 return NS_OK;
9167}
9168
9169static bool NavigationShouldTakeFocus(nsDocShell* aDocShell,
9170 nsDocShellLoadState* aLoadState) {
9171 if (!aLoadState->AllowFocusMove()) {
9172 return false;
9173 }
9174 if (!aLoadState->HasValidUserGestureActivation()) {
9175 return false;
9176 }
9177 const auto& sourceBC = aLoadState->SourceBrowsingContext();
9178 if (!sourceBC || !sourceBC->IsActive()) {
9179 // If the navigation didn't come from a foreground tab, then we don't steal
9180 // focus.
9181 return false;
9182 }
9183 auto* bc = aDocShell->GetBrowsingContext();
9184 if (sourceBC.get() == bc) {
9185 // If it comes from the same tab / frame, don't steal focus either.
9186 return false;
9187 }
9188 auto* fm = nsFocusManager::GetFocusManager();
9189 if (fm && bc->IsActive() && fm->IsInActiveWindow(bc)) {
9190 // If we're already on the foreground tab of the foreground window, then we
9191 // don't need to do this. This helps to e.g. not steal focus from the
9192 // browser chrome unnecessarily.
9193 return false;
9194 }
9195 if (auto* doc = aDocShell->GetExtantDocument()) {
9196 if (doc->IsInitialDocument()) {
9197 // If we're the initial load for the browsing context, the browser
9198 // chrome determines what to focus. This is important because the
9199 // browser chrome may want to e.g focus the url-bar
9200 return false;
9201 }
9202 }
9203 // Take loadDivertedInBackground into account so the behavior would be the
9204 // same as how the tab first opened.
9205 return !Preferences::GetBool("browser.tabs.loadDivertedInBackground", false);
9206}
9207
9208uint32_t nsDocShell::GetLoadTypeForFormSubmission(
9209 BrowsingContext* aTargetBC, nsDocShellLoadState* aLoadState) {
9210 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"
, 9210); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->IsFormSubmission()"
")"); do { *((volatile int*)__null) = 9210; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9211
9212 // https://html.spec.whatwg.org/#form-submission-algorithm
9213 // 22. Let historyHandling be "push".
9214 // 23. If form document equals targetNavigable's active document, and
9215 // form document has not yet completely loaded, then set
9216 // historyHandling to "replace".
9217 return GetBrowsingContext() == aTargetBC && !mEODForCurrentDocument
9218 ? LOAD_NORMAL_REPLACE
9219 : LOAD_LINK;
9220}
9221
9222nsresult nsDocShell::InternalLoad(nsDocShellLoadState* aLoadState,
9223 Maybe<uint32_t> aCacheKey) {
9224 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"
, 9224); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState"
") (" "need a load state!" ")"); do { *((volatile int*)__null
) = 9224; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
;
9225 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"
, 9226); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->TriggeringPrincipal()"
") (" "need a valid TriggeringPrincipal" ")"); do { *((volatile
int*)__null) = 9226; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
9226 "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"
, 9226); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->TriggeringPrincipal()"
") (" "need a valid TriggeringPrincipal" ")"); do { *((volatile
int*)__null) = 9226; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
9227
9228 if (!aLoadState->TriggeringPrincipal()) {
9229 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"
, 9229); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"InternalLoad needs a valid triggeringPrincipal" ")"); do { *
((volatile int*)__null) = 9229; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
;
9230 return NS_ERROR_FAILURE;
9231 }
9232 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"
, 9232)
) {
9233 return NS_ERROR_NOT_AVAILABLE;
9234 }
9235
9236 const bool shouldTakeFocus = NavigationShouldTakeFocus(this, aLoadState);
9237
9238 mOriginalUriString.Truncate();
9239
9240 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)
9241 ("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)
9242 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)
;
9243
9244 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"
, 9244); return NS_ERROR_INVALID_ARG; } } while (false)
;
9245
9246 // Cancel loads coming from Docshells that are being destroyed.
9247 if (mIsBeingDestroyed) {
9248 return NS_ERROR_NOT_AVAILABLE;
9249 }
9250
9251 nsresult rv = EnsureScriptEnvironment();
9252 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
9253 return rv;
9254 }
9255
9256 // If we have a target to move to, do that now.
9257 if (!aLoadState->Target().IsEmpty()) {
9258 return PerformRetargeting(aLoadState);
9259 }
9260
9261 // This is the non-retargeting load path, we've already set the right loadtype
9262 // for form submissions in nsDocShell::OnLinkClickSync.
9263 if (aLoadState->TargetBrowsingContext().IsNull()) {
9264 aLoadState->SetTargetBrowsingContext(GetBrowsingContext());
9265 }
9266
9267 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"
, 9269); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "aLoadState->TargetBrowsingContext() == GetBrowsingContext()"
") (" "Load must be targeting this BrowsingContext" ")"); do
{ *((volatile int*)__null) = 9269; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
9268 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"
, 9269); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "aLoadState->TargetBrowsingContext() == GetBrowsingContext()"
") (" "Load must be targeting this BrowsingContext" ")"); do
{ *((volatile int*)__null) = 9269; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
9269 "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"
, 9269); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "aLoadState->TargetBrowsingContext() == GetBrowsingContext()"
") (" "Load must be targeting this BrowsingContext" ")"); do
{ *((volatile int*)__null) = 9269; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
9270
9271 MOZ_TRY(CheckDisallowedJavascriptLoad(aLoadState))do { auto mozTryTempResult_ = ::mozilla::ToResult(CheckDisallowedJavascriptLoad
(aLoadState)); if ((__builtin_expect(!!(mozTryTempResult_.isErr
()), 0))) { return mozTryTempResult_.propagateErr(); } } while
(0)
;
9272
9273 // If we don't have a target, we're loading into ourselves, and our load
9274 // delegate may want to intercept that load.
9275 SameDocumentNavigationState sameDocumentNavigationState;
9276 bool sameDocument =
9277 IsSameDocumentNavigation(aLoadState, sameDocumentNavigationState) &&
9278 !aLoadState->GetPendingRedirectedChannel();
9279
9280 // Note: We do this check both here and in BrowsingContext::
9281 // LoadURI/InternalLoad, since document-specific sandbox flags are only
9282 // available in the process triggering the load, and we don't want the target
9283 // process to have to trust the triggering process to do the appropriate
9284 // checks for the BrowsingContext's sandbox flags.
9285 MOZ_TRY(mBrowsingContext->CheckSandboxFlags(aLoadState))do { auto mozTryTempResult_ = ::mozilla::ToResult(mBrowsingContext
->CheckSandboxFlags(aLoadState)); if ((__builtin_expect(!!
(mozTryTempResult_.isErr()), 0))) { return mozTryTempResult_.
propagateErr(); } } while (0)
;
9286
9287 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"
, 9287); return NS_ERROR_UNEXPECTED; } } while (false)
;
9288
9289 rv = CheckLoadingPermissions();
9290 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
9291 return rv;
9292 }
9293
9294 if (mFiredUnloadEvent) {
9295 if (IsOKToLoadURI(aLoadState->URI())) {
9296 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"
, 9297); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->Target().IsEmpty()"
") (" "Shouldn't have a window target here!" ")"); do { *((volatile
int*)__null) = 9297; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
9297 "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"
, 9297); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->Target().IsEmpty()"
") (" "Shouldn't have a window target here!" ")"); do { *((volatile
int*)__null) = 9297; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
9298
9299 // If this is a replace load, make whatever load triggered
9300 // the unload event also a replace load, so we don't
9301 // create extra history entries.
9302 if (LOAD_TYPE_HAS_FLAGS(aLoadState->LoadType(),((aLoadState->LoadType()) & ((LOAD_FLAGS_REPLACE_HISTORY
) << 16))
9303 LOAD_FLAGS_REPLACE_HISTORY)((aLoadState->LoadType()) & ((LOAD_FLAGS_REPLACE_HISTORY
) << 16))
) {
9304 mLoadType = LOAD_NORMAL_REPLACE;
9305 }
9306
9307 // Do this asynchronously
9308 nsCOMPtr<nsIRunnable> ev = new InternalLoadEvent(this, aLoadState);
9309 return Dispatch(ev.forget());
9310 }
9311
9312 // Just ignore this load attempt
9313 return NS_OK;
9314 }
9315
9316 // If we are loading a URI that should inherit a security context (basically
9317 // javascript: at this point), and the caller has said that principal
9318 // inheritance is allowed, there are a few possible cases:
9319 //
9320 // 1) We are provided with the principal to inherit. In that case, we just use
9321 // it.
9322 //
9323 // 2) The load is coming from some other application. In this case we don't
9324 // want to inherit from whatever document we have loaded now, since the
9325 // load is unrelated to it.
9326 //
9327 // 3) It's a load from our application, but does not provide an explicit
9328 // principal to inherit. In that case, we want to inherit the principal of
9329 // our current document, or of our parent document (if any) if we don't
9330 // have a current document.
9331 {
9332 bool inherits;
9333
9334 if (!aLoadState->HasLoadFlags(LOAD_FLAGS_FROM_EXTERNAL) &&
9335 !aLoadState->PrincipalToInherit() &&
9336 (aLoadState->HasInternalLoadFlags(
9337 INTERNAL_LOAD_FLAGS_INHERIT_PRINCIPAL)) &&
9338 NS_SUCCEEDED(nsContentUtils::URIInheritsSecurityContext(((bool)(__builtin_expect(!!(!NS_FAILED_impl(nsContentUtils::URIInheritsSecurityContext
( aLoadState->URI(), &inherits))), 1)))
9339 aLoadState->URI(), &inherits))((bool)(__builtin_expect(!!(!NS_FAILED_impl(nsContentUtils::URIInheritsSecurityContext
( aLoadState->URI(), &inherits))), 1)))
&&
9340 inherits) {
9341 aLoadState->SetPrincipalToInherit(GetInheritedPrincipal(true));
9342 }
9343 // If principalToInherit is still null (e.g. if some of the conditions of
9344 // were not satisfied), then no inheritance of any sort will happen: the
9345 // load will just get a principal based on the URI being loaded.
9346 }
9347
9348 // If this docshell is owned by a frameloader, make sure to cancel
9349 // possible frameloader initialization before loading a new page.
9350 nsCOMPtr<nsIDocShellTreeItem> parent = GetInProcessParentDocshell();
9351 if (parent) {
9352 RefPtr<Document> doc = parent->GetDocument();
9353 if (doc) {
9354 doc->TryCancelFrameLoaderInitialization(this);
9355 }
9356 }
9357
9358 // Before going any further vet loads initiated by external programs.
9359 if (aLoadState->HasLoadFlags(LOAD_FLAGS_FROM_EXTERNAL)) {
9360 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"
, 9360); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "aLoadState->LoadType() == LOAD_NORMAL"
")"); do { *((volatile int*)__null) = 9360; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9361
9362 // Disallow external chrome: loads targetted at content windows
9363 if (SchemeIsChrome(aLoadState->URI())) {
9364 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"
, 9364)
;
9365 return NS_ERROR_FAILURE;
9366 }
9367
9368 // clear the decks to prevent context bleed-through (bug 298255)
9369 rv = CreateAboutBlankDocumentViewer(nullptr, nullptr, nullptr, nullptr,
9370 /* aIsInitialDocument */ false);
9371 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
9372 return NS_ERROR_FAILURE;
9373 }
9374 }
9375
9376 mAllowKeywordFixup = aLoadState->HasInternalLoadFlags(
9377 INTERNAL_LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP);
9378 mURIResultedInDocument = false; // reset the clock...
9379
9380 // See if this is actually a load between two history entries for the same
9381 // document. If the process fails, or if we successfully navigate within the
9382 // same document, return.
9383 if (sameDocument) {
9384 nsresult rv = HandleSameDocumentNavigation(
9385 aLoadState, sameDocumentNavigationState, sameDocument);
9386 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"
, 9386); return rv; } } while (false)
;
9387 if (shouldTakeFocus) {
9388 mBrowsingContext->Focus(CallerType::System, IgnoreErrors());
9389 }
9390 if (sameDocument) {
9391 return rv;
9392 }
9393 }
9394
9395 // mDocumentViewer->PermitUnload can destroy |this| docShell, which
9396 // causes the next call of CanSavePresentation to crash.
9397 // Hold onto |this| until we return, to prevent a crash from happening.
9398 // (bug#331040)
9399 nsCOMPtr<nsIDocShell> kungFuDeathGrip(this);
9400
9401 // Don't init timing for javascript:, since it generally doesn't
9402 // actually start a load or anything. If it does, we'll init
9403 // timing then, from OnStateChange.
9404
9405 // XXXbz mTiming should know what channel it's for, so we don't
9406 // need this hackery.
9407 bool toBeReset = false;
9408 bool isJavaScript = SchemeIsJavascript(aLoadState->URI());
9409
9410 if (!isJavaScript) {
9411 toBeReset = MaybeInitTiming();
9412 }
9413 bool isNotDownload = aLoadState->FileName().IsVoid();
9414 if (mTiming && isNotDownload) {
9415 mTiming->NotifyBeforeUnload();
9416 }
9417 // Check if the page doesn't want to be unloaded. The javascript:
9418 // protocol handler deals with this for javascript: URLs.
9419 if (!isJavaScript && isNotDownload &&
9420 !aLoadState->NotifiedBeforeUnloadListeners() && mDocumentViewer) {
9421 bool okToUnload;
9422
9423 // Check if request is exempted from HTTPSOnlyMode and if https-first is
9424 // enabled, if so it means:
9425 // * https-first failed to upgrade request to https
9426 // * we already asked for permission to unload and the user accepted
9427 // otherwise we wouldn't be here.
9428 bool isPrivateWin = GetOriginAttributes().mPrivateBrowsingId > 0;
9429 bool isHistoryOrReload = false;
9430 uint32_t loadType = aLoadState->LoadType();
9431
9432 // Check if request is a reload.
9433 if (loadType == LOAD_RELOAD_NORMAL ||
9434 loadType == LOAD_RELOAD_BYPASS_CACHE ||
9435 loadType == LOAD_RELOAD_BYPASS_PROXY ||
9436 loadType == LOAD_RELOAD_BYPASS_PROXY_AND_CACHE ||
9437 loadType == LOAD_HISTORY) {
9438 isHistoryOrReload = true;
9439 }
9440
9441 // If it isn't a reload, the request already failed to be upgraded and
9442 // https-first is enabled then don't ask the user again for permission to
9443 // unload and just unload.
9444 if (!isHistoryOrReload && aLoadState->IsExemptFromHTTPSFirstMode() &&
9445 nsHTTPSOnlyUtils::IsHttpsFirstModeEnabled(isPrivateWin)) {
9446 rv = mDocumentViewer->PermitUnload(
9447 nsIDocumentViewer::PermitUnloadAction::eDontPromptAndUnload,
9448 &okToUnload);
9449 } else {
9450 rv = mDocumentViewer->PermitUnload(&okToUnload);
9451 }
9452
9453 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && !okToUnload) {
9454 // The user chose not to unload the page, interrupt the
9455 // load.
9456 MaybeResetInitTiming(toBeReset);
9457 return NS_OK;
9458 }
9459 }
9460
9461 if (mTiming && isNotDownload) {
9462 mTiming->NotifyUnloadAccepted(mCurrentURI);
9463 }
9464
9465 // In e10s, in the parent process, we refuse to load anything other than
9466 // "safe" resources that we ship or trust enough to give "special" URLs.
9467 // Similar check will be performed by the ParentProcessDocumentChannel if in
9468 // use.
9469 if (XRE_IsE10sParentProcess() &&
9470 !DocumentChannel::CanUseDocumentChannel(aLoadState->URI()) &&
9471 !CanLoadInParentProcess(aLoadState->URI())) {
9472 return NS_ERROR_FAILURE;
9473 }
9474
9475 // Whenever a top-level browsing context is navigated, the user agent MUST
9476 // lock the orientation of the document to the document's default
9477 // orientation. We don't explicitly check for a top-level browsing context
9478 // here because orientation is only set on top-level browsing contexts.
9479 if (mBrowsingContext->GetOrientationLock() != hal::ScreenOrientation::None) {
9480 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"
, 9480); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mBrowsingContext->IsTop()"
")"); do { *((volatile int*)__null) = 9480; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9481 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"
, 9482); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "false"
") (" "NS_SUCCEEDED(mBrowsingContext->SetOrientationLock(hal::ScreenOrientation::None))"
")"); do { *((volatile int*)__null) = 9482; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
9482 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"
, 9482); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "false"
") (" "NS_SUCCEEDED(mBrowsingContext->SetOrientationLock(hal::ScreenOrientation::None))"
")"); do { *((volatile int*)__null) = 9482; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
9483 if (mBrowsingContext->IsActive()) {
9484 ScreenOrientation::UpdateActiveOrientationLock(
9485 hal::ScreenOrientation::None);
9486 }
9487 }
9488
9489 // Check for saving the presentation here, before calling Stop().
9490 // This is necessary so that we can catch any pending requests.
9491 // Since the new request has not been created yet, we pass null for the
9492 // new request parameter.
9493 // Also pass nullptr for the document, since it doesn't affect the return
9494 // value for our purposes here.
9495 bool savePresentation =
9496 CanSavePresentation(aLoadState->LoadType(), nullptr, nullptr,
9497 /* aReportBFCacheComboTelemetry */ true);
9498
9499 // nsDocShell::CanSavePresentation is for non-SHIP version only. Do a
9500 // separate check for SHIP so that we know if there are ongoing requests
9501 // before calling Stop() below.
9502 if (mozilla::SessionHistoryInParent()) {
9503 Document* document = GetDocument();
9504 uint32_t flags = 0;
9505 if (document && !document->CanSavePresentation(nullptr, flags, true)) {
9506 // This forces some flags into the WindowGlobalParent's mBFCacheStatus,
9507 // which we'll then use in CanonicalBrowsingContext::AllowedInBFCache,
9508 // and in particular we'll store BFCacheStatus::REQUEST if needed.
9509 // Also, we want to report all the flags to the parent process here (and
9510 // not just BFCacheStatus::NOT_ALLOWED), so that it can update the
9511 // telemetry data correctly.
9512 document->DisallowBFCaching(flags);
9513 }
9514 }
9515
9516 // Don't stop current network activity for javascript: URL's since
9517 // they might not result in any data, and thus nothing should be
9518 // stopped in those cases. In the case where they do result in
9519 // data, the javascript: URL channel takes care of stopping
9520 // current network activity.
9521 if (!isJavaScript && isNotDownload) {
9522 // Stop any current network activity.
9523 // Also stop content if this is a zombie doc. otherwise
9524 // the onload will be delayed by other loads initiated in the
9525 // background by the first document that
9526 // didn't fully load before the next load was initiated.
9527 // If not a zombie, don't stop content until data
9528 // starts arriving from the new URI...
9529
9530 if ((mDocumentViewer && mDocumentViewer->GetPreviousViewer()) ||
9531 LOAD_TYPE_HAS_FLAGS(aLoadState->LoadType(), LOAD_FLAGS_STOP_CONTENT)((aLoadState->LoadType()) & ((LOAD_FLAGS_STOP_CONTENT)
<< 16))
) {
9532 rv = Stop(nsIWebNavigation::STOP_ALL);
9533 } else {
9534 rv = Stop(nsIWebNavigation::STOP_NETWORK);
9535 }
9536
9537 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
9538 return rv;
9539 }
9540 }
9541
9542 mLoadType = aLoadState->LoadType();
9543
9544 // aLoadState->SHEntry() should be assigned to mLSHE, only after Stop() has
9545 // been called. But when loading an error page, do not clear the
9546 // mLSHE for the real page.
9547 if (mLoadType != LOAD_ERROR_PAGE) {
9548 SetHistoryEntryAndUpdateBC(Some<nsISHEntry*>(aLoadState->SHEntry()),
9549 Nothing());
9550 if (aLoadState->LoadIsFromSessionHistory() &&
9551 !mozilla::SessionHistoryInParent()) {
9552 // We're making history navigation or a reload. Make sure our history ID
9553 // points to the same ID as SHEntry's docshell ID.
9554 nsID historyID = {};
9555 aLoadState->SHEntry()->GetDocshellID(historyID);
9556
9557 Unused << mBrowsingContext->SetHistoryID(historyID);
9558 }
9559 }
9560
9561 mSavingOldViewer = savePresentation;
9562
9563 // If we have a saved content viewer in history, restore and show it now.
9564 if (aLoadState->LoadIsFromSessionHistory() &&
9565 (mLoadType & LOAD_CMD_HISTORY)) {
9566 // https://html.spec.whatwg.org/#history-traversal:
9567 // To traverse the history
9568 // "If entry has a different Document object than the current entry, then
9569 // run the following substeps: Remove any tasks queued by the history
9570 // traversal task source..."
9571 // Same document object case was handled already above with
9572 // HandleSameDocumentNavigation call.
9573 RefPtr<ChildSHistory> shistory = GetRootSessionHistory();
9574 if (shistory) {
9575 shistory->RemovePendingHistoryNavigations();
9576 }
9577 if (!mozilla::SessionHistoryInParent()) {
9578 // It's possible that the previous viewer of mDocumentViewer is the
9579 // viewer that will end up in aLoadState->SHEntry() when it gets closed.
9580 // If that's the case, we need to go ahead and force it into its shentry
9581 // so we can restore it.
9582 if (mDocumentViewer) {
9583 nsCOMPtr<nsIDocumentViewer> prevViewer =
9584 mDocumentViewer->GetPreviousViewer();
9585 if (prevViewer) {
9586#ifdef DEBUG1
9587 nsCOMPtr<nsIDocumentViewer> prevPrevViewer =
9588 prevViewer->GetPreviousViewer();
9589 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"
, 9589); MOZ_PretendNoReturn(); } } while (0)
;
9590#endif
9591 nsCOMPtr<nsISHEntry> viewerEntry;
9592 prevViewer->GetHistoryEntry(getter_AddRefs(viewerEntry));
9593 if (viewerEntry == aLoadState->SHEntry()) {
9594 // Make sure this viewer ends up in the right place
9595 mDocumentViewer->SetPreviousViewer(nullptr);
9596 prevViewer->Destroy();
9597 }
9598 }
9599 }
9600 nsCOMPtr<nsISHEntry> oldEntry = mOSHE;
9601 bool restoring;
9602 rv = RestorePresentation(aLoadState->SHEntry(), &restoring);
9603 if (restoring) {
9604 Telemetry::Accumulate(Telemetry::BFCACHE_PAGE_RESTORED, true);
9605 return rv;
9606 }
9607 Telemetry::Accumulate(Telemetry::BFCACHE_PAGE_RESTORED, false);
9608
9609 // We failed to restore the presentation, so clean up.
9610 // Both the old and new history entries could potentially be in
9611 // an inconsistent state.
9612 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
9613 if (oldEntry) {
9614 oldEntry->SyncPresentationState();
9615 }
9616
9617 aLoadState->SHEntry()->SyncPresentationState();
9618 }
9619 }
9620 }
9621
9622 bool isTopLevelDoc = mBrowsingContext->IsTopContent();
9623
9624 OriginAttributes attrs = GetOriginAttributes();
9625 attrs.SetFirstPartyDomain(isTopLevelDoc, aLoadState->URI());
9626
9627 PredictorLearn(aLoadState->URI(), nullptr,
9628 nsINetworkPredictor::LEARN_LOAD_TOPLEVEL, attrs);
9629 PredictorPredict(aLoadState->URI(), nullptr,
9630 nsINetworkPredictor::PREDICT_LOAD, attrs, nullptr);
9631
9632 nsCOMPtr<nsIRequest> req;
9633 rv = DoURILoad(aLoadState, aCacheKey, getter_AddRefs(req));
9634
9635 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
9636 if (shouldTakeFocus) {
9637 mBrowsingContext->Focus(CallerType::System, IgnoreErrors());
9638 }
9639 }
9640
9641 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
9642 nsCOMPtr<nsIChannel> chan(do_QueryInterface(req));
9643 UnblockEmbedderLoadEventForFailure();
9644 nsCOMPtr<nsIURI> uri = aLoadState->URI();
9645 if (DisplayLoadError(rv, uri, nullptr, chan) &&
9646 // FIXME: At this point code was using internal load flags, but checking
9647 // non-internal load flags?
9648 aLoadState->HasLoadFlags(LOAD_FLAGS_ERROR_LOAD_CHANGES_RV)) {
9649 return NS_ERROR_LOAD_SHOWED_ERRORPAGE;
9650 }
9651
9652 // We won't report any error if this is an unknown protocol error. The
9653 // reason behind this is that it will allow enumeration of external
9654 // protocols if we report an error for each unknown protocol.
9655 if (NS_ERROR_UNKNOWN_PROTOCOL == rv) {
9656 return NS_OK;
9657 }
9658 }
9659
9660 return rv;
9661}
9662
9663/* static */
9664bool nsDocShell::CanLoadInParentProcess(nsIURI* aURI) {
9665 nsCOMPtr<nsIURI> uri = aURI;
9666 // In e10s, in the parent process, we refuse to load anything other than
9667 // "safe" resources that we ship or trust enough to give "special" URLs.
9668 bool canLoadInParent = false;
9669 if (NS_SUCCEEDED(NS_URIChainHasFlags(((bool)(__builtin_expect(!!(!NS_FAILED_impl(NS_URIChainHasFlags
( uri, nsIProtocolHandler::URI_IS_UI_RESOURCE, &canLoadInParent
))), 1)))
9670 uri, nsIProtocolHandler::URI_IS_UI_RESOURCE, &canLoadInParent))((bool)(__builtin_expect(!!(!NS_FAILED_impl(NS_URIChainHasFlags
( uri, nsIProtocolHandler::URI_IS_UI_RESOURCE, &canLoadInParent
))), 1)))
&&
9671 canLoadInParent) {
9672 // We allow UI resources.
9673 return true;
9674 }
9675 // For about: and extension-based URIs, which don't get
9676 // URI_IS_UI_RESOURCE, first remove layers of view-source:, if present.
9677 while (uri && uri->SchemeIs("view-source")) {
9678 nsCOMPtr<nsINestedURI> nested = do_QueryInterface(uri);
9679 if (nested) {
9680 nested->GetInnerURI(getter_AddRefs(uri));
9681 } else {
9682 break;
9683 }
9684 }
9685 // Allow about: URIs, and allow moz-extension ones if we're running
9686 // extension content in the parent process.
9687 if (!uri || uri->SchemeIs("about") ||
9688 (!StaticPrefs::extensions_webextensions_remote() &&
9689 uri->SchemeIs("moz-extension"))) {
9690 return true;
9691 }
9692#ifdef MOZ_THUNDERBIRD
9693 if (uri->SchemeIs("imap") || uri->SchemeIs("mailbox") ||
9694 uri->SchemeIs("news") || uri->SchemeIs("nntp") ||
9695 uri->SchemeIs("snews")) {
9696 return true;
9697 }
9698#endif
9699 nsAutoCString scheme;
9700 uri->GetScheme(scheme);
9701 // Allow ext+foo URIs (extension-registered custom protocols). See
9702 // https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/protocol_handlers
9703 if (StringBeginsWith(scheme, "ext+"_ns) &&
9704 !StaticPrefs::extensions_webextensions_remote()) {
9705 return true;
9706 }
9707 // Final exception for some legacy automated tests:
9708 if (xpc::IsInAutomation() &&
9709 StaticPrefs::security_allow_unsafe_parent_loads()) {
9710 return true;
9711 }
9712 return false;
9713}
9714
9715nsIPrincipal* nsDocShell::GetInheritedPrincipal(
9716 bool aConsiderCurrentDocument, bool aConsiderPartitionedPrincipal) {
9717 RefPtr<Document> document;
9718 bool inheritedFromCurrent = false;
9719
9720 if (aConsiderCurrentDocument && mDocumentViewer) {
9721 document = mDocumentViewer->GetDocument();
9722 inheritedFromCurrent = true;
9723 }
9724
9725 if (!document) {
9726 nsCOMPtr<nsIDocShellTreeItem> parentItem;
9727 GetInProcessSameTypeParent(getter_AddRefs(parentItem));
9728 if (parentItem) {
9729 document = parentItem->GetDocument();
9730 }
9731 }
9732
9733 if (!document) {
9734 if (!aConsiderCurrentDocument) {
9735 return nullptr;
9736 }
9737
9738 // Make sure we end up with _something_ as the principal no matter
9739 // what.If this fails, we'll just get a null docViewer and bail.
9740 EnsureDocumentViewer();
9741 if (!mDocumentViewer) {
9742 return nullptr;
9743 }
9744 document = mDocumentViewer->GetDocument();
9745 }
9746
9747 //-- Get the document's principal
9748 if (document) {
9749 nsIPrincipal* docPrincipal = aConsiderPartitionedPrincipal
9750 ? document->PartitionedPrincipal()
9751 : document->NodePrincipal();
9752
9753 // Don't allow loads in typeContent docShells to inherit the system
9754 // principal from existing documents.
9755 if (inheritedFromCurrent && mItemType == typeContent &&
9756 docPrincipal->IsSystemPrincipal()) {
9757 return nullptr;
9758 }
9759
9760 return docPrincipal;
9761 }
9762
9763 return nullptr;
9764}
9765
9766/* static */ nsresult nsDocShell::CreateRealChannelForDocument(
9767 nsIChannel** aChannel, nsIURI* aURI, nsILoadInfo* aLoadInfo,
9768 nsIInterfaceRequestor* aCallbacks, nsLoadFlags aLoadFlags,
9769 const nsAString& aSrcdoc, nsIURI* aBaseURI) {
9770 nsCOMPtr<nsIChannel> channel;
9771 if (aSrcdoc.IsVoid()) {
9772 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)
9773 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)
9774 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)
9775 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)
;
9776
9777 if (aBaseURI) {
9778 nsCOMPtr<nsIViewSourceChannel> vsc = do_QueryInterface(channel);
9779 if (vsc) {
9780 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"
, 9780); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "false"
") (" "NS_SUCCEEDED(vsc->SetBaseURI(aBaseURI))" ")"); do {
*((volatile int*)__null) = 9780; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false); } } while (false
)
;
9781 }
9782 }
9783 } else if (SchemeIsViewSource(aURI)) {
9784 // Instantiate view source handler protocol, if it doesn't exist already.
9785 nsCOMPtr<nsIIOService> io(do_GetIOService());
9786 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"
, 9786); AnnotateMozCrashReason("MOZ_ASSERT" "(" "io" ")"); do
{ *((volatile int*)__null) = 9786; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
9787 nsCOMPtr<nsIProtocolHandler> handler;
9788 nsresult rv =
9789 io->GetProtocolHandler("view-source", getter_AddRefs(handler));
9790 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
9791 return rv;
9792 }
9793
9794 nsViewSourceHandler* vsh = nsViewSourceHandler::GetInstance();
9795 if (!vsh) {
9796 return NS_ERROR_FAILURE;
9797 }
9798
9799 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)
9800 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)
;
9801 } else {
9802 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)
9803 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)
9804 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)
;
9805 nsCOMPtr<nsIInputStreamChannel> isc = do_QueryInterface(channel);
9806 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"
, 9806); AnnotateMozCrashReason("MOZ_ASSERT" "(" "isc" ")"); do
{ *((volatile int*)__null) = 9806; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
9807 isc->SetBaseURI(aBaseURI);
9808 }
9809
9810 if (aLoadFlags != nsIRequest::LOAD_NORMAL) {
9811 nsresult rv = channel->SetLoadFlags(aLoadFlags);
9812 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"
, 9812); return rv; } } while (false)
;
9813 }
9814
9815 channel.forget(aChannel);
9816 return NS_OK;
9817}
9818
9819/* static */ bool nsDocShell::CreateAndConfigureRealChannelForLoadState(
9820 BrowsingContext* aBrowsingContext, nsDocShellLoadState* aLoadState,
9821 LoadInfo* aLoadInfo, nsIInterfaceRequestor* aCallbacks,
9822 nsDocShell* aDocShell, const OriginAttributes& aOriginAttributes,
9823 nsLoadFlags aLoadFlags, uint32_t aCacheKey, nsresult& aRv,
9824 nsIChannel** aChannel) {
9825 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"
, 9825); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadInfo" ")"
); do { *((volatile int*)__null) = 9825; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9826
9827 nsString srcdoc = VoidString();
9828 bool isSrcdoc =
9829 aLoadState->HasInternalLoadFlags(INTERNAL_LOAD_FLAGS_IS_SRCDOC);
9830 if (isSrcdoc) {
9831 srcdoc = aLoadState->SrcdocData();
9832 }
9833
9834 aLoadInfo->SetTriggeringRemoteType(
9835 aLoadState->GetEffectiveTriggeringRemoteType());
9836
9837 if (aLoadState->PrincipalToInherit()) {
9838 aLoadInfo->SetPrincipalToInherit(aLoadState->PrincipalToInherit());
9839 }
9840 aLoadInfo->SetLoadTriggeredFromExternal(
9841 aLoadState->HasLoadFlags(LOAD_FLAGS_FROM_EXTERNAL));
9842 aLoadInfo->SetForceAllowDataURI(aLoadState->HasInternalLoadFlags(
9843 INTERNAL_LOAD_FLAGS_FORCE_ALLOW_DATA_URI));
9844 aLoadInfo->SetOriginalFrameSrcLoad(
9845 aLoadState->HasInternalLoadFlags(INTERNAL_LOAD_FLAGS_ORIGINAL_FRAME_SRC));
9846
9847 bool inheritAttrs = false;
9848 if (aLoadState->PrincipalToInherit()) {
9849 inheritAttrs = nsContentUtils::ChannelShouldInheritPrincipal(
9850 aLoadState->PrincipalToInherit(), aLoadState->URI(),
9851 true, // aInheritForAboutBlank
9852 isSrcdoc);
9853 }
9854
9855 // Strip the target query parameters before creating the channel.
9856 aLoadState->MaybeStripTrackerQueryStrings(aBrowsingContext);
9857
9858 OriginAttributes attrs;
9859
9860 // Inherit origin attributes from PrincipalToInherit if inheritAttrs is
9861 // true. Otherwise we just use the origin attributes from docshell.
9862 if (inheritAttrs) {
9863 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"
, 9864); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->PrincipalToInherit()"
") (" "We should have PrincipalToInherit here." ")"); do { *
((volatile int*)__null) = 9864; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
9864 "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"
, 9864); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->PrincipalToInherit()"
") (" "We should have PrincipalToInherit here." ")"); do { *
((volatile int*)__null) = 9864; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
;
9865 attrs = aLoadState->PrincipalToInherit()->OriginAttributesRef();
9866 // If firstPartyIsolation is not enabled, then PrincipalToInherit should
9867 // have the same origin attributes with docshell.
9868 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"
, 9869); AnnotateMozCrashReason("MOZ_ASSERT" "(" "attrs == aOriginAttributes"
")"); do { *((volatile int*)__null) = 9869; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
9869 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"
, 9869); AnnotateMozCrashReason("MOZ_ASSERT" "(" "attrs == aOriginAttributes"
")"); do { *((volatile int*)__null) = 9869; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
9870 } else {
9871 attrs = aOriginAttributes;
9872 attrs.SetFirstPartyDomain(IsTopLevelDoc(aBrowsingContext, aLoadInfo),
9873 aLoadState->URI());
9874 }
9875
9876 aRv = aLoadInfo->SetOriginAttributes(attrs);
9877 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"
, 9877)
) {
9878 return false;
9879 }
9880
9881 if (aLoadState->GetIsFromProcessingFrameAttributes()) {
9882 aLoadInfo->SetIsFromProcessingFrameAttributes();
9883 }
9884
9885 // Propagate the IsFormSubmission flag to the loadInfo.
9886 if (aLoadState->IsFormSubmission()) {
9887 aLoadInfo->SetIsFormSubmission(true);
9888 }
9889
9890 aLoadInfo->SetUnstrippedURI(aLoadState->GetUnstrippedURI());
9891
9892 nsCOMPtr<nsIChannel> channel;
9893 aRv = CreateRealChannelForDocument(getter_AddRefs(channel), aLoadState->URI(),
9894 aLoadInfo, aCallbacks, aLoadFlags, srcdoc,
9895 aLoadState->BaseURI());
9896 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"
, 9896); return false; } } while (false)
;
9897
9898 if (!channel) {
9899 return false;
9900 }
9901
9902 // If the HTTPS-Only mode is enabled, every insecure request gets upgraded to
9903 // HTTPS by default. This behavior can be disabled through the loadinfo flag
9904 // HTTPS_ONLY_EXEMPT.
9905 nsHTTPSOnlyUtils::TestSitePermissionAndPotentiallyAddExemption(channel);
9906
9907 // hack
9908 nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(channel));
9909 nsCOMPtr<nsIHttpChannelInternal> httpChannelInternal(
9910 do_QueryInterface(channel));
9911 nsCOMPtr<nsIURI> referrer;
9912 nsIReferrerInfo* referrerInfo = aLoadState->GetReferrerInfo();
9913 if (referrerInfo) {
9914 referrerInfo->GetOriginalReferrer(getter_AddRefs(referrer));
9915 }
9916 if (httpChannelInternal) {
9917 if (aLoadState->HasInternalLoadFlags(
9918 INTERNAL_LOAD_FLAGS_FORCE_ALLOW_COOKIES)) {
9919 aRv = httpChannelInternal->SetThirdPartyFlags(
9920 nsIHttpChannelInternal::THIRD_PARTY_FORCE_ALLOW);
9921 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"
, 9921); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(aRv)), 1)))"
")"); do { *((volatile int*)__null) = 9921; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9922 }
9923 if (aLoadState->FirstParty()) {
9924 aRv = httpChannelInternal->SetDocumentURI(aLoadState->URI());
9925 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"
, 9925); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(aRv)), 1)))"
")"); do { *((volatile int*)__null) = 9925; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9926 } else {
9927 aRv = httpChannelInternal->SetDocumentURI(referrer);
9928 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"
, 9928); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(aRv)), 1)))"
")"); do { *((volatile int*)__null) = 9928; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9929 }
9930 aRv = httpChannelInternal->SetRedirectMode(
9931 nsIHttpChannelInternal::REDIRECT_MODE_MANUAL);
9932 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"
, 9932); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(aRv)), 1)))"
")"); do { *((volatile int*)__null) = 9932; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9933 }
9934
9935 if (httpChannel) {
9936 if (aLoadState->HeadersStream()) {
9937 aRv = AddHeadersToChannel(aLoadState->HeadersStream(), httpChannel);
9938 }
9939 // Set the referrer explicitly
9940 // Referrer is currenly only set for link clicks here.
9941 if (referrerInfo) {
9942 aRv = httpChannel->SetReferrerInfo(referrerInfo);
9943 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"
, 9943); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(aRv)), 1)))"
")"); do { *((volatile int*)__null) = 9943; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9944 }
9945
9946 // Mark the http channel as UrgentStart for top level document loading in
9947 // active tab.
9948 if (IsUrgentStart(aBrowsingContext, aLoadInfo, aLoadState->LoadType())) {
9949 nsCOMPtr<nsIClassOfService> cos(do_QueryInterface(channel));
9950 if (cos) {
9951 cos->AddClassFlags(nsIClassOfService::UrgentStart);
9952 }
9953 }
9954 }
9955
9956 channel->SetOriginalURI(aLoadState->OriginalURI() ? aLoadState->OriginalURI()
9957 : aLoadState->URI());
9958
9959 const nsACString& typeHint = aLoadState->TypeHint();
9960 if (!typeHint.IsVoid()) {
9961 channel->SetContentType(typeHint);
9962 }
9963
9964 const nsAString& fileName = aLoadState->FileName();
9965 if (!fileName.IsVoid()) {
9966 aRv = channel->SetContentDisposition(nsIChannel::DISPOSITION_ATTACHMENT);
9967 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"
, 9967); return false; } } while (false)
;
9968 if (!fileName.IsEmpty()) {
9969 aRv = channel->SetContentDispositionFilename(fileName);
9970 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"
, 9970); return false; } } while (false)
;
9971 }
9972 }
9973
9974 if (nsCOMPtr<nsIWritablePropertyBag2> props = do_QueryInterface(channel)) {
9975 nsCOMPtr<nsIURI> referrer;
9976 nsIReferrerInfo* referrerInfo = aLoadState->GetReferrerInfo();
9977 if (referrerInfo) {
9978 referrerInfo->GetOriginalReferrer(getter_AddRefs(referrer));
9979 }
9980 // save true referrer for those who need it (e.g. xpinstall whitelisting)
9981 // Currently only http and ftp channels support this.
9982 props->SetPropertyAsInterface(u"docshell.internalReferrer"_ns, referrer);
9983
9984 if (aLoadState->HasInternalLoadFlags(INTERNAL_LOAD_FLAGS_FIRST_LOAD)) {
9985 props->SetPropertyAsBool(u"docshell.newWindowTarget"_ns, true);
9986 }
9987 }
9988
9989 nsCOMPtr<nsICacheInfoChannel> cacheChannel(do_QueryInterface(channel));
9990 auto loadType = aLoadState->LoadType();
9991
9992 if (loadType == LOAD_RELOAD_NORMAL &&
9993 StaticPrefs::
9994 browser_soft_reload_only_force_validate_top_level_document()) {
9995 nsCOMPtr<nsICacheInfoChannel> cachingChannel = do_QueryInterface(channel);
9996 if (cachingChannel) {
9997 cachingChannel->SetForceValidateCacheContent(true);
9998 }
9999 }
10000
10001 // figure out if we need to set the post data stream on the channel...
10002 if (aLoadState->PostDataStream()) {
10003 if (nsCOMPtr<nsIFormPOSTActionChannel> postChannel =
10004 do_QueryInterface(channel)) {
10005 // XXX it's a bit of a hack to rewind the postdata stream here but
10006 // it has to be done in case the post data is being reused multiple
10007 // times.
10008 nsCOMPtr<nsISeekableStream> postDataSeekable =
10009 do_QueryInterface(aLoadState->PostDataStream());
10010 if (postDataSeekable) {
10011 aRv = postDataSeekable->Seek(nsISeekableStream::NS_SEEK_SET, 0);
10012 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"
, 10012); return false; } } while (false)
;
10013 }
10014
10015 // we really need to have a content type associated with this stream!!
10016 postChannel->SetUploadStream(aLoadState->PostDataStream(), ""_ns, -1);
10017
10018 // Ownership of the stream has transferred to the channel, clear our
10019 // reference.
10020 aLoadState->SetPostDataStream(nullptr);
10021 }
10022
10023 /* If there is a valid postdata *and* it is a History Load,
10024 * set up the cache key on the channel, to retrieve the
10025 * data *only* from the cache. If it is a normal reload, the
10026 * cache is free to go to the server for updated postdata.
10027 */
10028 if (cacheChannel && aCacheKey != 0) {
10029 if (loadType == LOAD_HISTORY || loadType == LOAD_RELOAD_CHARSET_CHANGE) {
10030 cacheChannel->SetCacheKey(aCacheKey);
10031 uint32_t loadFlags;
10032 if (NS_SUCCEEDED(channel->GetLoadFlags(&loadFlags))((bool)(__builtin_expect(!!(!NS_FAILED_impl(channel->GetLoadFlags
(&loadFlags))), 1)))
) {
10033 channel->SetLoadFlags(loadFlags |
10034 nsICachingChannel::LOAD_ONLY_FROM_CACHE);
10035 }
10036 } else if (loadType == LOAD_RELOAD_NORMAL) {
10037 cacheChannel->SetCacheKey(aCacheKey);
10038 }
10039 }
10040 } else {
10041 /* If there is no postdata, set the cache key on the channel, and
10042 * do not set the LOAD_ONLY_FROM_CACHE flag, so that the channel
10043 * will be free to get it from net if it is not found in cache.
10044 * New cache may use it creatively on CGI pages with GET
10045 * method and even on those that say "no-cache"
10046 */
10047 if (loadType == LOAD_HISTORY || loadType == LOAD_RELOAD_NORMAL ||
10048 loadType == LOAD_RELOAD_CHARSET_CHANGE ||
10049 loadType == LOAD_RELOAD_CHARSET_CHANGE_BYPASS_CACHE ||
10050 loadType == LOAD_RELOAD_CHARSET_CHANGE_BYPASS_PROXY_AND_CACHE) {
10051 if (cacheChannel && aCacheKey != 0) {
10052 cacheChannel->SetCacheKey(aCacheKey);
10053 }
10054 }
10055 }
10056
10057 if (nsCOMPtr<nsIScriptChannel> scriptChannel = do_QueryInterface(channel)) {
10058 // Allow execution against our context if the principals match
10059 scriptChannel->SetExecutionPolicy(nsIScriptChannel::EXECUTE_NORMAL);
10060 }
10061
10062 if (nsCOMPtr<nsITimedChannel> timedChannel = do_QueryInterface(channel)) {
10063 timedChannel->SetTimingEnabled(true);
10064
10065 nsString initiatorType;
10066 switch (aLoadInfo->InternalContentPolicyType()) {
10067 case nsIContentPolicy::TYPE_INTERNAL_EMBED:
10068 initiatorType = u"embed"_ns;
10069 break;
10070 case nsIContentPolicy::TYPE_INTERNAL_OBJECT:
10071 initiatorType = u"object"_ns;
10072 break;
10073 default: {
10074 const auto& embedderElementType =
10075 aBrowsingContext->GetEmbedderElementType();
10076 if (embedderElementType) {
10077 initiatorType = *embedderElementType;
10078 }
10079 break;
10080 }
10081 }
10082
10083 if (!initiatorType.IsEmpty()) {
10084 timedChannel->SetInitiatorType(initiatorType);
10085 }
10086 }
10087
10088 nsCOMPtr<nsIURI> rpURI;
10089 aLoadInfo->GetResultPrincipalURI(getter_AddRefs(rpURI));
10090 Maybe<nsCOMPtr<nsIURI>> originalResultPrincipalURI;
10091 aLoadState->GetMaybeResultPrincipalURI(originalResultPrincipalURI);
10092 if (originalResultPrincipalURI &&
10093 (!aLoadState->KeepResultPrincipalURIIfSet() || !rpURI)) {
10094 // Unconditionally override, we want the replay to be equal to what has
10095 // been captured.
10096 aLoadInfo->SetResultPrincipalURI(originalResultPrincipalURI.ref());
10097 }
10098
10099 if (aLoadState->OriginalURI() && aLoadState->LoadReplace()) {
10100 // The LOAD_REPLACE flag and its handling here will be removed as part
10101 // of bug 1319110. For now preserve its restoration here to not break
10102 // any code expecting it being set specially on redirected channels.
10103 // If the flag has originally been set to change result of
10104 // NS_GetFinalChannelURI it won't have any effect and also won't cause
10105 // any harm.
10106 uint32_t loadFlags;
10107 aRv = channel->GetLoadFlags(&loadFlags);
10108 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"
, 10108); return false; } } while (false)
;
10109 channel->SetLoadFlags(loadFlags | nsIChannel::LOAD_REPLACE);
10110 }
10111
10112 nsCOMPtr<nsIContentSecurityPolicy> csp = aLoadState->Csp();
10113 if (csp) {
10114 // Navigational requests that are same origin need to be upgraded in case
10115 // upgrade-insecure-requests is present. Please note that for document
10116 // navigations that bit is re-computed in case we encounter a server
10117 // side redirect so the navigation is not same-origin anymore.
10118 bool upgradeInsecureRequests = false;
10119 csp->GetUpgradeInsecureRequests(&upgradeInsecureRequests);
10120 if (upgradeInsecureRequests) {
10121 // only upgrade if the navigation is same origin
10122 nsCOMPtr<nsIPrincipal> resultPrincipal;
10123 aRv = nsContentUtils::GetSecurityManager()->GetChannelResultPrincipal(
10124 channel, getter_AddRefs(resultPrincipal));
10125 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"
, 10125); return false; } } while (false)
;
10126 if (nsContentSecurityUtils::IsConsideredSameOriginForUIR(
10127 aLoadState->TriggeringPrincipal(), resultPrincipal)) {
10128 aLoadInfo->SetUpgradeInsecureRequests(true);
10129 }
10130 }
10131
10132 // For document loads we store the CSP that potentially needs to
10133 // be inherited by the new document, e.g. in case we are loading
10134 // an opaque origin like a data: URI. The actual inheritance
10135 // check happens within Document::InitCSP().
10136 // Please create an actual copy of the CSP (do not share the same
10137 // reference) otherwise a Meta CSP of an opaque origin will
10138 // incorrectly be propagated to the embedding document.
10139 RefPtr<nsCSPContext> cspToInherit = new nsCSPContext();
10140 cspToInherit->InitFromOther(static_cast<nsCSPContext*>(csp.get()));
10141 aLoadInfo->SetCSPToInherit(cspToInherit);
10142 }
10143
10144 channel.forget(aChannel);
10145 return true;
10146}
10147
10148bool nsDocShell::IsAboutBlankLoadOntoInitialAboutBlank(
10149 nsIURI* aURI, bool aInheritPrincipal, nsIPrincipal* aPrincipalToInherit) {
10150 return NS_IsAboutBlank(aURI) && aInheritPrincipal &&
10151 (aPrincipalToInherit == GetInheritedPrincipal(false)) &&
10152 (!mDocumentViewer || !mDocumentViewer->GetDocument() ||
10153 mDocumentViewer->GetDocument()->IsInitialDocument());
10154}
10155
10156nsresult nsDocShell::DoURILoad(nsDocShellLoadState* aLoadState,
10157 Maybe<uint32_t> aCacheKey,
10158 nsIRequest** aRequest) {
10159 // Double-check that we're still around to load this URI.
10160 if (mIsBeingDestroyed) {
10161 // Return NS_OK despite not doing anything to avoid throwing exceptions
10162 // from nsLocation::SetHref if the unload handler of the existing page
10163 // tears us down.
10164 return NS_OK;
10165 }
10166
10167 nsCOMPtr<nsIURILoader> uriLoader = components::URILoader::Service();
10168 if (NS_WARN_IF(!uriLoader)NS_warn_if_impl(!uriLoader, "!uriLoader", "/var/lib/jenkins/workspace/firefox-scan-build/docshell/base/nsDocShell.cpp"
, 10168)
) {
10169 return NS_ERROR_UNEXPECTED;
10170 }
10171
10172 // Persist and sync layout history state before we load a new uri, as this
10173 // might be our last chance to do so, in the content process.
10174 PersistLayoutHistoryState();
10175 SynchronizeLayoutHistoryState();
10176
10177 nsresult rv;
10178 nsContentPolicyType contentPolicyType = DetermineContentType();
10179
10180 if (IsSubframe()) {
10181 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"
, 10183); 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) = 10183; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
10182 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"
, 10183); 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) = 10183; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
10183 "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"
, 10183); 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) = 10183; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10184
10185 if (StaticPrefs::dom_block_external_protocol_in_iframes()) {
10186 // Only allow URLs able to return data in iframes.
10187 if (nsContentUtils::IsExternalProtocol(aLoadState->URI())) {
10188 // The context to check user-interaction with for the purposes of
10189 // popup-blocking.
10190 //
10191 // We generally want to check the context that initiated the navigation.
10192 WindowContext* sourceWindowContext = [&] {
10193 const MaybeDiscardedBrowsingContext& sourceBC =
10194 aLoadState->SourceBrowsingContext();
10195 if (!sourceBC.IsNullOrDiscarded()) {
10196 if (WindowContext* wc = sourceBC.get()->GetCurrentWindowContext()) {
10197 return wc;
10198 }
10199 }
10200 return mBrowsingContext->GetParentWindowContext();
10201 }();
10202
10203 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"
, 10203); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sourceWindowContext"
")"); do { *((volatile int*)__null) = 10203; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10204 // FIXME: We can't check user-interaction against an OOP window. This is
10205 // the next best thing we can really do. The load state keeps whether
10206 // the navigation had a user interaction in process
10207 // (aLoadState->HasValidUserGestureActivation()), but we can't really
10208 // consume it, which we want to prevent popup-spamming from the same
10209 // click event.
10210 WindowContext* context =
10211 sourceWindowContext->IsInProcess()
10212 ? sourceWindowContext
10213 : mBrowsingContext->GetCurrentWindowContext();
10214 const bool popupBlocked = [&] {
10215 const bool active = mBrowsingContext->IsActive();
10216
10217 // For same-origin-with-top windows, we grant a single free popup
10218 // without user activation, see bug 1680721.
10219 //
10220 // We consume the flag now even if there's no user activation.
10221 const bool hasFreePass = [&] {
10222 if (!active ||
10223 !(context->IsInProcess() && context->SameOriginWithTop())) {
10224 return false;
10225 }
10226 nsGlobalWindowInner* win =
10227 context->TopWindowContext()->GetInnerWindow();
10228 return win && win->TryOpenExternalProtocolIframe();
10229 }();
10230
10231 if (context->IsInProcess() &&
10232 context->ConsumeTransientUserGestureActivation()) {
10233 // If the user has interacted with the page, consume it.
10234 return false;
10235 }
10236
10237 // TODO(emilio): Can we remove this check? It seems like what prompted
10238 // this code (bug 1514547) should be covered by transient user
10239 // activation, see bug 1514547.
10240 if (active &&
10241 PopupBlocker::ConsumeTimerTokenForExternalProtocolIframe()) {
10242 return false;
10243 }
10244
10245 if (sourceWindowContext->CanShowPopup()) {
10246 return false;
10247 }
10248
10249 if (hasFreePass) {
10250 return false;
10251 }
10252
10253 return true;
10254 }();
10255
10256 // No error must be returned when iframes are blocked.
10257 if (popupBlocked) {
10258 nsAutoString message;
10259 nsresult rv = nsContentUtils::GetLocalizedString(
10260 nsContentUtils::eDOM_PROPERTIES,
10261 "ExternalProtocolFrameBlockedNoUserActivation", message);
10262 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
10263 nsContentUtils::ReportToConsoleByWindowID(
10264 message, nsIScriptError::warningFlag, "DOM"_ns,
10265 context->InnerWindowId());
10266 }
10267 return NS_OK;
10268 }
10269 }
10270 }
10271
10272 // Only allow view-source scheme in top-level docshells. view-source is
10273 // the only scheme to which this applies at the moment due to potential
10274 // timing attacks to read data from cross-origin iframes. If this widens
10275 // we should add a protocol flag for whether the scheme is allowed in
10276 // frames and use something like nsNetUtil::NS_URIChainHasFlags.
10277 nsCOMPtr<nsIURI> tempURI = aLoadState->URI();
10278 nsCOMPtr<nsINestedURI> nestedURI = do_QueryInterface(tempURI);
10279 while (nestedURI) {
10280 // view-source should always be an nsINestedURI, loop and check the
10281 // scheme on this and all inner URIs that are also nested URIs.
10282 if (SchemeIsViewSource(tempURI)) {
10283 return NS_ERROR_UNKNOWN_PROTOCOL;
10284 }
10285 nestedURI->GetInnerURI(getter_AddRefs(tempURI));
10286 nestedURI = do_QueryInterface(tempURI);
10287 }
10288 } else {
10289 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"
, 10290); AnnotateMozCrashReason("MOZ_ASSERT" "(" "contentPolicyType == nsIContentPolicy::TYPE_DOCUMENT"
") (" "DoURILoad thinks this is a document and InternalLoad does not"
")"); do { *((volatile int*)__null) = 10290; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
10290 "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"
, 10290); AnnotateMozCrashReason("MOZ_ASSERT" "(" "contentPolicyType == nsIContentPolicy::TYPE_DOCUMENT"
") (" "DoURILoad thinks this is a document and InternalLoad does not"
")"); do { *((volatile int*)__null) = 10290; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10291 }
10292
10293 // We want to inherit aLoadState->PrincipalToInherit() when:
10294 // 1. ChannelShouldInheritPrincipal returns true.
10295 // 2. aLoadState->URI() is not data: URI, or data: URI is not
10296 // configured as unique opaque origin.
10297 bool inheritPrincipal = false;
10298
10299 if (aLoadState->PrincipalToInherit()) {
10300 bool isSrcdoc =
10301 aLoadState->HasInternalLoadFlags(INTERNAL_LOAD_FLAGS_IS_SRCDOC);
10302 bool inheritAttrs = nsContentUtils::ChannelShouldInheritPrincipal(
10303 aLoadState->PrincipalToInherit(), aLoadState->URI(),
10304 true, // aInheritForAboutBlank
10305 isSrcdoc);
10306
10307 inheritPrincipal = inheritAttrs && !SchemeIsData(aLoadState->URI());
10308 }
10309
10310 // See https://bugzilla.mozilla.org/show_bug.cgi?id=1736570
10311 const bool isAboutBlankLoadOntoInitialAboutBlank =
10312 IsAboutBlankLoadOntoInitialAboutBlank(aLoadState->URI(), inheritPrincipal,
10313 aLoadState->PrincipalToInherit());
10314
10315 // FIXME We still have a ton of codepaths that don't pass through
10316 // DocumentLoadListener, so probably need to create session history info
10317 // in more places.
10318 if (aLoadState->GetLoadingSessionHistoryInfo()) {
10319 SetLoadingSessionHistoryInfo(*aLoadState->GetLoadingSessionHistoryInfo());
10320 } else if (isAboutBlankLoadOntoInitialAboutBlank &&
10321 mozilla::SessionHistoryInParent()) {
10322 // Materialize LoadingSessionHistoryInfo here, because DocumentChannel
10323 // loads have it, and later history behavior depends on it existing.
10324 UniquePtr<SessionHistoryInfo> entry = MakeUnique<SessionHistoryInfo>(
10325 aLoadState->URI(), aLoadState->TriggeringPrincipal(),
10326 aLoadState->PrincipalToInherit(),
10327 aLoadState->PartitionedPrincipalToInherit(), aLoadState->Csp(),
10328 mContentTypeHint);
10329 mozilla::dom::LoadingSessionHistoryInfo info(*entry);
10330 SetLoadingSessionHistoryInfo(info, true);
10331 }
10332
10333 // open a channel for the url
10334
10335 // If we have a pending channel, use the channel we've already created here.
10336 // We don't need to set up load flags for our channel, as it has already been
10337 // created.
10338
10339 if (nsCOMPtr<nsIChannel> channel =
10340 aLoadState->GetPendingRedirectedChannel()) {
10341 // If we have a request outparameter, shove our channel into it.
10342 if (aRequest) {
10343 nsCOMPtr<nsIRequest> outRequest = channel;
10344 outRequest.forget(aRequest);
10345 }
10346
10347 return OpenRedirectedChannel(aLoadState);
10348 }
10349
10350 // There are two cases we care about:
10351 // * Top-level load: In this case, loadingNode is null, but loadingWindow
10352 // is our mScriptGlobal. We pass null for loadingPrincipal in this case.
10353 // * Subframe load: loadingWindow is null, but loadingNode is the frame
10354 // element for the load. loadingPrincipal is the NodePrincipal of the
10355 // frame element.
10356 nsCOMPtr<nsINode> loadingNode;
10357 nsCOMPtr<nsPIDOMWindowOuter> loadingWindow;
10358 nsCOMPtr<nsIPrincipal> loadingPrincipal;
10359 nsCOMPtr<nsISupports> topLevelLoadingContext;
10360
10361 if (contentPolicyType == nsIContentPolicy::TYPE_DOCUMENT) {
10362 loadingNode = nullptr;
10363 loadingPrincipal = nullptr;
10364 loadingWindow = mScriptGlobal;
10365 if (XRE_IsContentProcess()) {
10366 // In e10s the child process doesn't have access to the element that
10367 // contains the browsing context (because that element is in the chrome
10368 // process).
10369 nsCOMPtr<nsIBrowserChild> browserChild = GetBrowserChild();
10370 topLevelLoadingContext = ToSupports(browserChild);
10371 } else {
10372 // This is for loading non-e10s tabs and toplevel windows of various
10373 // sorts.
10374 // For the toplevel window cases, requestingElement will be null.
10375 nsCOMPtr<Element> requestingElement =
10376 loadingWindow->GetFrameElementInternal();
10377 topLevelLoadingContext = requestingElement;
10378 }
10379 } else {
10380 loadingWindow = nullptr;
10381 loadingNode = mScriptGlobal->GetFrameElementInternal();
10382 if (loadingNode) {
10383 // If we have a loading node, then use that as our loadingPrincipal.
10384 loadingPrincipal = loadingNode->NodePrincipal();
10385#ifdef DEBUG1
10386 // Get the docshell type for requestingElement.
10387 RefPtr<Document> requestingDoc = loadingNode->OwnerDoc();
10388 nsCOMPtr<nsIDocShell> elementDocShell = requestingDoc->GetDocShell();
10389 // requestingElement docshell type = current docshell type.
10390 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"
, 10392); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mItemType == elementDocShell->ItemType()"
") (" "subframes should have the same docshell type as their parent"
")"); do { *((volatile int*)__null) = 10392; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
10391 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"
, 10392); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mItemType == elementDocShell->ItemType()"
") (" "subframes should have the same docshell type as their parent"
")"); do { *((volatile int*)__null) = 10392; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
10392 "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"
, 10392); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mItemType == elementDocShell->ItemType()"
") (" "subframes should have the same docshell type as their parent"
")"); do { *((volatile int*)__null) = 10392; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10393#endif
10394 } else {
10395 if (mIsBeingDestroyed) {
10396 // If this isn't a top-level load and mScriptGlobal's frame element is
10397 // null, then the element got removed from the DOM while we were trying
10398 // to load this resource. This docshell is scheduled for destruction
10399 // already, so bail out here.
10400 return NS_OK;
10401 }
10402 // If we are not being destroyed and we do not have access to the loading
10403 // node, then we are a remote subframe. Set the loading principal
10404 // to be a null principal and then set it correctly in the parent.
10405 loadingPrincipal = NullPrincipal::Create(GetOriginAttributes(), nullptr);
10406 }
10407 }
10408
10409 if (!aLoadState->TriggeringPrincipal()) {
10410 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"
, 10410); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"DoURILoad needs a valid triggeringPrincipal" ")"); do { *((
volatile int*)__null) = 10410; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
;
10411 return NS_ERROR_FAILURE;
10412 }
10413
10414 uint32_t sandboxFlags = mBrowsingContext->GetSandboxFlags();
10415 nsSecurityFlags securityFlags =
10416 nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_SEC_CONTEXT_IS_NULL;
10417
10418 if (mLoadType == LOAD_ERROR_PAGE) {
10419 securityFlags |= nsILoadInfo::SEC_LOAD_ERROR_PAGE;
10420 }
10421
10422 if (inheritPrincipal) {
10423 securityFlags |= nsILoadInfo::SEC_FORCE_INHERIT_PRINCIPAL;
10424 }
10425
10426 // Must never have a parent for TYPE_DOCUMENT loads
10427 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"
, 10428); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mBrowsingContext->GetParent()"
")"); do { *((volatile int*)__null) = 10428; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false); } } while
(false)
10428 !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"
, 10428); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mBrowsingContext->GetParent()"
")"); do { *((volatile int*)__null) = 10428; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false); } } while
(false)
;
10429 // Subdocuments must have a parent
10430 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"
, 10431); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mBrowsingContext->GetParent()"
")"); do { *((volatile int*)__null) = 10431; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false); } } while
(false)
10431 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"
, 10431); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mBrowsingContext->GetParent()"
")"); do { *((volatile int*)__null) = 10431; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false); } } while
(false)
;
10432 mBrowsingContext->SetTriggeringAndInheritPrincipals(
10433 aLoadState->TriggeringPrincipal(), aLoadState->PrincipalToInherit(),
10434 aLoadState->GetLoadIdentifier());
10435 RefPtr<LoadInfo> loadInfo =
10436 (contentPolicyType == nsIContentPolicy::TYPE_DOCUMENT)
10437 ? new LoadInfo(loadingWindow, aLoadState->URI(),
10438 aLoadState->TriggeringPrincipal(),
10439 topLevelLoadingContext, securityFlags, sandboxFlags)
10440 : new LoadInfo(loadingPrincipal, aLoadState->TriggeringPrincipal(),
10441 loadingNode, securityFlags, contentPolicyType,
10442 Maybe<mozilla::dom::ClientInfo>(),
10443 Maybe<mozilla::dom::ServiceWorkerDescriptor>(),
10444 sandboxFlags);
10445 RefPtr<WindowContext> context = mBrowsingContext->GetCurrentWindowContext();
10446
10447 if (isAboutBlankLoadOntoInitialAboutBlank) {
10448 // Match the DocumentChannel case where the default for third-partiness
10449 // differs from the default in LoadInfo construction here.
10450 // toolkit/components/antitracking/test/browser/browser_aboutblank.js
10451 // fails without this.
10452 BrowsingContext* top = mBrowsingContext->Top();
10453 if (top == mBrowsingContext) {
10454 // If we're at the top, this must be a window.open()ed
10455 // window, and we can't be third-party relative to ourselves.
10456 loadInfo->SetIsThirdPartyContextToTopWindow(false);
10457 } else {
10458 if (Document* topDoc = top->GetDocument()) {
10459 bool thirdParty = false;
10460 mozilla::Unused << topDoc->GetPrincipal()->IsThirdPartyPrincipal(
10461 aLoadState->PrincipalToInherit(), &thirdParty);
10462 loadInfo->SetIsThirdPartyContextToTopWindow(thirdParty);
10463 } else {
10464 // If top is in a different process, we have to be third-party relative
10465 // to it.
10466 loadInfo->SetIsThirdPartyContextToTopWindow(true);
10467 }
10468 }
10469 }
10470
10471 if (mLoadType != LOAD_ERROR_PAGE && context && context->IsInProcess()) {
10472 if (context->HasValidTransientUserGestureActivation()) {
10473 aLoadState->SetHasValidUserGestureActivation(true);
10474 }
10475 if (!aLoadState->TriggeringWindowId()) {
10476 aLoadState->SetTriggeringWindowId(context->Id());
10477 }
10478 if (!aLoadState->TriggeringStorageAccess()) {
10479 Document* contextDoc = context->GetExtantDoc();
10480 if (contextDoc) {
10481 aLoadState->SetTriggeringStorageAccess(
10482 contextDoc->UsingStorageAccess());
10483 }
10484 }
10485 }
10486
10487 // in case this docshell load was triggered by a valid transient user gesture,
10488 // or also the load originates from external, then we pass that information on
10489 // to the loadinfo, which allows e.g. setting Sec-Fetch-User request headers.
10490 if (aLoadState->HasValidUserGestureActivation() ||
10491 aLoadState->HasLoadFlags(LOAD_FLAGS_FROM_EXTERNAL)) {
10492 loadInfo->SetHasValidUserGestureActivation(true);
10493 }
10494
10495 loadInfo->SetTriggeringWindowId(aLoadState->TriggeringWindowId());
10496 loadInfo->SetTriggeringStorageAccess(aLoadState->TriggeringStorageAccess());
10497 loadInfo->SetTriggeringSandboxFlags(aLoadState->TriggeringSandboxFlags());
10498 loadInfo->SetIsMetaRefresh(aLoadState->IsMetaRefresh());
10499
10500 uint32_t cacheKey = 0;
10501 if (aCacheKey) {
10502 cacheKey = *aCacheKey;
10503 } else if (mozilla::SessionHistoryInParent()) {
10504 if (mLoadingEntry) {
10505 cacheKey = mLoadingEntry->mInfo.GetCacheKey();
10506 } else if (mActiveEntry) { // for reload cases
10507 cacheKey = mActiveEntry->GetCacheKey();
10508 }
10509 } else {
10510 if (mLSHE) {
10511 cacheKey = mLSHE->GetCacheKey();
10512 } else if (mOSHE) { // for reload cases
10513 cacheKey = mOSHE->GetCacheKey();
10514 }
10515 }
10516
10517 bool uriModified;
10518 if (mLSHE || mLoadingEntry) {
10519 if (mLoadingEntry) {
10520 uriModified = mLoadingEntry->mInfo.GetURIWasModified();
10521 } else {
10522 uriModified = mLSHE->GetURIWasModified();
10523 }
10524 } else {
10525 uriModified = false;
10526 }
10527
10528 bool isEmbeddingBlockedError = false;
10529 if (mFailedChannel) {
10530 nsresult status;
10531 mFailedChannel->GetStatus(&status);
10532 isEmbeddingBlockedError = status == NS_ERROR_XFO_VIOLATION ||
10533 status == NS_ERROR_CSP_FRAME_ANCESTOR_VIOLATION;
10534 }
10535
10536 nsLoadFlags loadFlags = aLoadState->CalculateChannelLoadFlags(
10537 mBrowsingContext, Some(uriModified), Some(isEmbeddingBlockedError));
10538
10539 nsCOMPtr<nsIChannel> channel;
10540 if (DocumentChannel::CanUseDocumentChannel(aLoadState->URI()) &&
10541 !isAboutBlankLoadOntoInitialAboutBlank) {
10542 channel = DocumentChannel::CreateForDocument(
10543 aLoadState, loadInfo, loadFlags, this, cacheKey, uriModified,
10544 isEmbeddingBlockedError);
10545 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"
, 10545); AnnotateMozCrashReason("MOZ_ASSERT" "(" "channel" ")"
); do { *((volatile int*)__null) = 10545; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
10546
10547 // Disable keyword fixup when using DocumentChannel, since
10548 // DocumentLoadListener will handle this for us (in the parent process).
10549 mAllowKeywordFixup = false;
10550 } else if (!CreateAndConfigureRealChannelForLoadState(
10551 mBrowsingContext, aLoadState, loadInfo, this, this,
10552 GetOriginAttributes(), loadFlags, cacheKey, rv,
10553 getter_AddRefs(channel))) {
10554 return rv;
10555 }
10556
10557 // Make sure to give the caller a channel if we managed to create one
10558 // This is important for correct error page/session history interaction
10559 if (aRequest) {
10560 NS_ADDREF(*aRequest = channel)(*aRequest = channel)->AddRef();
10561 }
10562
10563 nsCOMPtr<nsIContentSecurityPolicy> csp = aLoadState->Csp();
10564 if (csp) {
10565 // Check CSP navigate-to
10566 bool allowsNavigateTo = false;
10567 rv = csp->GetAllowsNavigateTo(aLoadState->URI(),
10568 aLoadState->IsFormSubmission(),
10569 false, /* aWasRedirected */
10570 false, /* aEnforceWhitelist */
10571 &allowsNavigateTo);
10572 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"
, 10572); return rv; } } while (false)
;
10573
10574 if (!allowsNavigateTo) {
10575 return NS_ERROR_CSP_NAVIGATE_TO_VIOLATION;
10576 }
10577 }
10578
10579 const nsACString& typeHint = aLoadState->TypeHint();
10580 if (!typeHint.IsVoid()) {
10581 mContentTypeHint = typeHint;
10582 } else {
10583 mContentTypeHint.Truncate();
10584 }
10585
10586 // Load attributes depend on load type...
10587 if (mLoadType == LOAD_RELOAD_CHARSET_CHANGE) {
10588 // Use SetAllowStaleCacheContent (not LOAD_FROM_CACHE flag) since we
10589 // only want to force cache load for this channel, not the whole
10590 // loadGroup.
10591 nsCOMPtr<nsICacheInfoChannel> cachingChannel = do_QueryInterface(channel);
10592 if (cachingChannel) {
10593 cachingChannel->SetAllowStaleCacheContent(true);
10594 }
10595 }
10596
10597 uint32_t openFlags =
10598 nsDocShell::ComputeURILoaderFlags(mBrowsingContext, mLoadType);
10599 return OpenInitializedChannel(channel, uriLoader, openFlags);
10600}
10601
10602static nsresult AppendSegmentToString(nsIInputStream* aIn, void* aClosure,
10603 const char* aFromRawSegment,
10604 uint32_t aToOffset, uint32_t aCount,
10605 uint32_t* aWriteCount) {
10606 // aFromSegment now contains aCount bytes of data.
10607
10608 nsAutoCString* buf = static_cast<nsAutoCString*>(aClosure);
10609 buf->Append(aFromRawSegment, aCount);
10610
10611 // Indicate that we have consumed all of aFromSegment
10612 *aWriteCount = aCount;
10613 return NS_OK;
10614}
10615
10616/* static */ nsresult nsDocShell::AddHeadersToChannel(
10617 nsIInputStream* aHeadersData, nsIChannel* aGenericChannel) {
10618 nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(aGenericChannel);
10619 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"
, 10619); return NS_ERROR_UNEXPECTED; } } while (false)
;
10620
10621 uint32_t numRead;
10622 nsAutoCString headersString;
10623 nsresult rv = aHeadersData->ReadSegments(
10624 AppendSegmentToString, &headersString, UINT32_MAX(4294967295U), &numRead);
10625 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"
, 10625); return rv; } } while (false)
;
10626
10627 // used during the manipulation of the String from the InputStream
10628 nsAutoCString headerName;
10629 nsAutoCString headerValue;
10630 int32_t crlf;
10631 int32_t colon;
10632
10633 //
10634 // Iterate over the headersString: for each "\r\n" delimited chunk,
10635 // add the value as a header to the nsIHttpChannel
10636 //
10637
10638 static const char kWhitespace[] = "\b\t\r\n ";
10639 while (true) {
10640 crlf = headersString.Find("\r\n");
10641 if (crlf == kNotFound) {
10642 return NS_OK;
10643 }
10644
10645 const nsACString& oneHeader = StringHead(headersString, crlf);
10646
10647 colon = oneHeader.FindChar(':');
10648 if (colon == kNotFound) {
10649 return NS_ERROR_UNEXPECTED;
10650 }
10651
10652 headerName = StringHead(oneHeader, colon);
10653 headerValue = Substring(oneHeader, colon + 1);
10654
10655 headerName.Trim(kWhitespace);
10656 headerValue.Trim(kWhitespace);
10657
10658 headersString.Cut(0, crlf + 2);
10659
10660 //
10661 // FINALLY: we can set the header!
10662 //
10663
10664 rv = httpChannel->SetRequestHeader(headerName, headerValue, true);
10665 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"
, 10665); return rv; } } while (false)
;
10666 }
10667
10668 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"
, 10668); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "oops" ")"); do { *((volatile int
*)__null) = 10668; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
10669 return NS_ERROR_UNEXPECTED;
10670}
10671
10672/* static */ uint32_t nsDocShell::ComputeURILoaderFlags(
10673 BrowsingContext* aBrowsingContext, uint32_t aLoadType) {
10674 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"
, 10674); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aBrowsingContext"
")"); do { *((volatile int*)__null) = 10674; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10675
10676 uint32_t openFlags = 0;
10677 if (aLoadType == LOAD_LINK) {
10678 openFlags |= nsIURILoader::IS_CONTENT_PREFERRED;
10679 }
10680 if (!aBrowsingContext->GetAllowContentRetargeting()) {
10681 openFlags |= nsIURILoader::DONT_RETARGET;
10682 }
10683
10684 return openFlags;
10685}
10686
10687nsresult nsDocShell::OpenInitializedChannel(nsIChannel* aChannel,
10688 nsIURILoader* aURILoader,
10689 uint32_t aOpenFlags) {
10690 nsresult rv = NS_OK;
10691
10692 // If anything fails here, make sure to clear our initial ClientSource.
10693 auto cleanupInitialClient =
10694 MakeScopeExit([&] { mInitialClientSource.reset(); });
10695
10696 nsCOMPtr<nsPIDOMWindowOuter> win = GetWindow();
10697 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"
, 10697); return NS_ERROR_FAILURE; } } while (false)
;
10698
10699 MaybeCreateInitialClientSource();
10700
10701 // Let the client channel helper know if we are using DocumentChannel,
10702 // since redirects get handled in the parent process in that case.
10703 RefPtr<net::DocumentChannel> docChannel = do_QueryObject(aChannel);
10704 if (docChannel && XRE_IsContentProcess()) {
10705 // Tell the content process nsDocumentOpenInfo to not try to do
10706 // any sort of targeting.
10707 aOpenFlags |= nsIURILoader::DONT_RETARGET;
10708 }
10709
10710 // Since we are loading a document we need to make sure the proper reserved
10711 // and initial client data is stored on the nsILoadInfo. The
10712 // ClientChannelHelper does this and ensures that it is propagated properly
10713 // on redirects. We pass no reserved client here so that the helper will
10714 // create the reserved ClientSource if necessary.
10715 Maybe<ClientInfo> noReservedClient;
10716 if (docChannel) {
10717 // When using DocumentChannel, all redirect handling is done in the parent,
10718 // so we just need the child variant to watch for the internal redirect
10719 // to the final channel.
10720 rv = AddClientChannelHelperInChild(aChannel,
10721 GetMainThreadSerialEventTarget());
10722 docChannel->SetInitialClientInfo(GetInitialClientInfo());
10723 } else {
10724 rv = AddClientChannelHelper(aChannel, std::move(noReservedClient),
10725 GetInitialClientInfo(),
10726 GetMainThreadSerialEventTarget());
10727 }
10728 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"
, 10728); return rv; } } while (false)
;
10729
10730 rv = aURILoader->OpenURI(aChannel, aOpenFlags, this);
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 // We're about to load a new page and it may take time before necko
10734 // gives back any data, so main thread might have a chance to process a
10735 // collector slice
10736 nsJSContext::MaybeRunNextCollectorSlice(this, JS::GCReason::DOCSHELL);
10737
10738 // Success. Keep the initial ClientSource if it exists.
10739 cleanupInitialClient.release();
10740
10741 return NS_OK;
10742}
10743
10744nsresult nsDocShell::OpenRedirectedChannel(nsDocShellLoadState* aLoadState) {
10745 nsCOMPtr<nsIChannel> channel = aLoadState->GetPendingRedirectedChannel();
10746 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"
, 10746); AnnotateMozCrashReason("MOZ_ASSERT" "(" "channel" ")"
); do { *((volatile int*)__null) = 10746; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
10747
10748 // If anything fails here, make sure to clear our initial ClientSource.
10749 auto cleanupInitialClient =
10750 MakeScopeExit([&] { mInitialClientSource.reset(); });
10751
10752 nsCOMPtr<nsPIDOMWindowOuter> win = GetWindow();
10753 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"
, 10753); return NS_ERROR_FAILURE; } } while (false)
;
10754
10755 MaybeCreateInitialClientSource();
10756
10757 nsCOMPtr<nsILoadInfo> loadInfo = channel->LoadInfo();
10758
10759 LoadInfo* li = static_cast<LoadInfo*>(loadInfo.get());
10760 if (loadInfo->GetExternalContentPolicyType() ==
10761 ExtContentPolicy::TYPE_DOCUMENT) {
10762 li->UpdateBrowsingContextID(mBrowsingContext->Id());
10763 } else if (loadInfo->GetExternalContentPolicyType() ==
10764 ExtContentPolicy::TYPE_SUBDOCUMENT) {
10765 li->UpdateFrameBrowsingContextID(mBrowsingContext->Id());
10766 }
10767 // TODO: more attributes need to be updated on the LoadInfo (bug 1561706)
10768
10769 // If we did a process switch, then we should have an existing allocated
10770 // ClientInfo, so we just need to allocate a corresponding ClientSource.
10771 CreateReservedSourceIfNeeded(channel, GetMainThreadSerialEventTarget());
10772
10773 RefPtr<nsDocumentOpenInfo> loader =
10774 new nsDocumentOpenInfo(this, nsIURILoader::DONT_RETARGET, nullptr);
10775 channel->SetLoadGroup(mLoadGroup);
10776
10777 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"
, 10777); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "false"
") (" "NS_SUCCEEDED(loader->Prepare())" ")"); do { *((volatile
int*)__null) = 10777; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false); } } while (false)
;
10778
10779 nsresult rv = NS_OK;
10780 if (XRE_IsParentProcess()) {
10781 // If we're in the parent, the we don't have an nsIChildChannel, just
10782 // the original channel, which is already open in this process.
10783
10784 // DocumentLoadListener expects to get an nsIParentChannel, so
10785 // we create a wrapper around the channel and nsIStreamListener
10786 // that forwards functionality as needed, and then we register
10787 // it under the provided identifier.
10788 RefPtr<ParentChannelWrapper> wrapper =
10789 new ParentChannelWrapper(channel, loader);
10790 wrapper->Register(aLoadState->GetPendingRedirectChannelRegistrarId());
10791
10792 mLoadGroup->AddRequest(channel, nullptr);
10793 } else if (nsCOMPtr<nsIChildChannel> childChannel =
10794 do_QueryInterface(channel)) {
10795 // Our channel was redirected from another process, so doesn't need to
10796 // be opened again. However, it does need its listener hooked up
10797 // correctly.
10798 rv = childChannel->CompleteRedirectSetup(loader);
10799 } else {
10800 // It's possible for the redirected channel to not implement
10801 // nsIChildChannel and be entirely local (like srcdoc). In that case we
10802 // can just open the local instance and it will work.
10803 rv = channel->AsyncOpen(loader);
10804 }
10805 if (rv == NS_ERROR_NO_CONTENT) {
10806 return NS_OK;
10807 }
10808 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"
, 10808); return rv; } } while (false)
;
10809
10810 // Success. Keep the initial ClientSource if it exists.
10811 cleanupInitialClient.release();
10812 return NS_OK;
10813}
10814
10815// https://html.spec.whatwg.org/#scrolling-to-a-fragment
10816nsresult nsDocShell::ScrollToAnchor(bool aCurHasRef, bool aNewHasRef,
10817 nsACString& aNewHash, uint32_t aLoadType) {
10818 if (!mCurrentURI) {
10819 return NS_OK;
10820 }
10821
10822 RefPtr<PresShell> presShell = GetPresShell();
10823 if (!presShell) {
10824 // If we failed to get the shell, or if there is no shell,
10825 // nothing left to do here.
10826 return NS_OK;
10827 }
10828
10829 nsIScrollableFrame* rootScroll = presShell->GetRootScrollFrameAsScrollable();
10830 if (rootScroll) {
10831 rootScroll->ClearDidHistoryRestore();
10832 }
10833
10834 // If we have no new anchor, we do not want to scroll, unless there is a
10835 // current anchor and we are doing a history load. So return if we have no
10836 // new anchor, and there is no current anchor or the load is not a history
10837 // load.
10838 if ((!aCurHasRef || aLoadType != LOAD_HISTORY) && !aNewHasRef) {
10839 return NS_OK;
10840 }
10841
10842 // Both the new and current URIs refer to the same page. We can now
10843 // browse to the hash stored in the new URI.
10844
10845 // If it's a load from history, we don't have any anchor jumping to do.
10846 // Scrollbar position will be restored by the caller based on positions stored
10847 // in session history.
10848 bool scroll = aLoadType != LOAD_HISTORY && aLoadType != LOAD_RELOAD_NORMAL;
10849
10850 if (aNewHash.IsEmpty()) {
10851 // 2. If fragment is the empty string, then return the special value top of
10852 // the document.
10853 //
10854 // Tell the shell it's at an anchor without scrolling.
10855 presShell->GoToAnchor(u""_ns, false);
10856
10857 if (scroll) {
10858 // Scroll to the top of the page. Ignore the return value; failure to
10859 // scroll here (e.g. if there is no root scrollframe) is not grounds for
10860 // canceling the load!
10861 SetCurScrollPosEx(0, 0);
10862 }
10863
10864 return NS_OK;
10865 }
10866
10867 // 3. Let potentialIndicatedElement be the result of finding a potential
10868 // indicated element given document and fragment.
10869 NS_ConvertUTF8toUTF16 uStr(aNewHash);
10870 auto rv = presShell->GoToAnchor(uStr, scroll, ScrollFlags::ScrollSmoothAuto);
10871
10872 // 4. If potentialIndicatedElement is not null, then return
10873 // potentialIndicatedElement.
10874 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
10875 return NS_OK;
10876 }
10877
10878 // 5. Let fragmentBytes be the result of percent-decoding fragment.
10879 nsAutoCString fragmentBytes;
10880 const bool unescaped = NS_UnescapeURL(aNewHash.Data(), aNewHash.Length(),
10881 /* aFlags = */ 0, fragmentBytes);
10882
10883 if (!unescaped) {
10884 // Another attempt is only necessary if characters were unescaped.
10885 return NS_OK;
10886 }
10887
10888 if (fragmentBytes.IsEmpty()) {
10889 // When aNewHash contains "%00", the unescaped string may be empty, and
10890 // GoToAnchor asserts if we ask it to scroll to an empty ref.
10891 presShell->GoToAnchor(u""_ns, false);
10892 return NS_OK;
10893 }
10894
10895 // 6. Let decodedFragment be the result of running UTF-8 decode without BOM on
10896 // fragmentBytes.
10897 nsAutoString decodedFragment;
10898 rv = UTF_8_ENCODING->DecodeWithoutBOMHandling(fragmentBytes, decodedFragment);
10899 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"
, 10899); return rv; } } while (false)
;
10900
10901 // 7. Set potentialIndicatedElement to the result of finding a potential
10902 // indicated element given document and decodedFragment.
10903 //
10904 // Ignore the return value of GoToAnchor, since it will return an error if
10905 // there is no such anchor in the document, which is actually a success
10906 // condition for us (we want to update the session history with the new URI no
10907 // matter whether we actually scrolled somewhere).
10908 presShell->GoToAnchor(decodedFragment, scroll, ScrollFlags::ScrollSmoothAuto);
10909
10910 return NS_OK;
10911}
10912
10913bool nsDocShell::OnNewURI(nsIURI* aURI, nsIChannel* aChannel,
10914 nsIPrincipal* aTriggeringPrincipal,
10915 nsIPrincipal* aPrincipalToInherit,
10916 nsIPrincipal* aPartitionedPrincipalToInherit,
10917 nsIContentSecurityPolicy* aCsp,
10918 bool aAddToGlobalHistory, bool aCloneSHChildren) {
10919 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"
, 10919); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aURI" ") ("
"uri is null" ")"); do { *((volatile int*)__null) = 10919; __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
;
10920 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"
, 10920); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aChannel || !aTriggeringPrincipal"
") (" "Shouldn't have both set" ")"); do { *((volatile int*)
__null) = 10920; __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
10921
10922 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"
, 10923); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aPrincipalToInherit || (aPrincipalToInherit && aTriggeringPrincipal)"
")"); do { *((volatile int*)__null) = 10923; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
10923 (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"
, 10923); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aPrincipalToInherit || (aPrincipalToInherit && aTriggeringPrincipal)"
")"); do { *((volatile int*)__null) = 10923; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10924
10925#if defined(DEBUG1)
10926 if (MOZ_LOG_TEST(gDocShellLog, LogLevel::Debug)(__builtin_expect(!!(mozilla::detail::log_test(gDocShellLog, LogLevel
::Debug)), 0))
) {
10927 nsAutoCString chanName;
10928 if (aChannel) {
10929 aChannel->GetName(chanName);
10930 } else {
10931 chanName.AssignLiteral("<no channel>");
10932 }
10933
10934 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)
10935 ("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)
10936 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)
;
10937 }
10938#endif
10939
10940 bool equalUri = false;
10941
10942 // Get the post data and the HTTP response code from the channel.
10943 uint32_t responseStatus = 0;
10944 nsCOMPtr<nsIInputStream> inputStream;
10945 if (aChannel) {
10946 nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(aChannel));
10947
10948 // Check if the HTTPChannel is hiding under a multiPartChannel
10949 if (!httpChannel) {
10950 GetHttpChannel(aChannel, getter_AddRefs(httpChannel));
10951 }
10952
10953 if (httpChannel) {
10954 nsCOMPtr<nsIUploadChannel> uploadChannel(do_QueryInterface(httpChannel));
10955 if (uploadChannel) {
10956 uploadChannel->GetUploadStream(getter_AddRefs(inputStream));
10957 }
10958
10959 // If the response status indicates an error, unlink this session
10960 // history entry from any entries sharing its document.
10961 nsresult rv = httpChannel->GetResponseStatus(&responseStatus);
10962 if (mLSHE && NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && responseStatus >= 400) {
10963 mLSHE->AbandonBFCacheEntry();
10964 // FIXME Do the same for mLoadingEntry
10965 }
10966 }
10967 }
10968
10969 // Determine if this type of load should update history.
10970 bool updateGHistory = ShouldUpdateGlobalHistory(mLoadType);
10971
10972 // We don't update session history on reload unless we're loading
10973 // an iframe in shift-reload case.
10974 bool updateSHistory = mBrowsingContext->ShouldUpdateSessionHistory(mLoadType);
10975
10976 // Create SH Entry (mLSHE) only if there is a SessionHistory object in the
10977 // root browsing context.
10978 // FIXME If session history in the parent is enabled then we only do this if
10979 // the session history object is in process, otherwise we can't really
10980 // use the mLSHE anyway. Once session history is only stored in the
10981 // parent then this code will probably be removed anyway.
10982 RefPtr<ChildSHistory> rootSH = GetRootSessionHistory();
10983 if (!rootSH) {
10984 updateSHistory = false;
10985 updateGHistory = false; // XXX Why global history too?
10986 }
10987
10988 // Check if the url to be loaded is the same as the one already loaded.
10989 if (mCurrentURI) {
10990 aURI->Equals(mCurrentURI, &equalUri);
10991 }
10992
10993#ifdef DEBUG1
10994 bool shAvailable = (rootSH != nullptr);
10995
10996 // XXX This log message is almost useless because |updateSHistory|
10997 // and |updateGHistory| are not correct at this point.
10998
10999 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)
11000 (" 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)
11001 " 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)
11002 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)
;
11003#endif
11004
11005 /* If the url to be loaded is the same as the one already there,
11006 * and the original loadType is LOAD_NORMAL, LOAD_LINK, or
11007 * LOAD_STOP_CONTENT, set loadType to LOAD_NORMAL_REPLACE so that
11008 * AddToSessionHistory() won't mess with the current SHEntry and
11009 * if this page has any frame children, it also will be handled
11010 * properly. see bug 83684
11011 *
11012 * NB: If mOSHE is null but we have a current URI, then it probably
11013 * means that we must be at the transient about:blank content viewer;
11014 * we should let the normal load continue, since there's nothing to
11015 * replace. Sometimes this happens after a session restore (eg process
11016 * switch) and mCurrentURI is not about:blank; we assume we can let the load
11017 * continue (Bug 1301399).
11018 *
11019 * XXX Hopefully changing the loadType at this time will not hurt
11020 * anywhere. The other way to take care of sequentially repeating
11021 * frameset pages is to add new methods to nsIDocShellTreeItem.
11022 * Hopefully I don't have to do that.
11023 */
11024 if (equalUri &&
11025 (mozilla::SessionHistoryInParent() ? !!mActiveEntry : !!mOSHE) &&
11026 (mLoadType == LOAD_NORMAL || mLoadType == LOAD_LINK ||
11027 mLoadType == LOAD_STOP_CONTENT) &&
11028 !inputStream) {
11029 mLoadType = LOAD_NORMAL_REPLACE;
11030 }
11031
11032 // If this is a refresh to the currently loaded url, we don't
11033 // have to update session or global history.
11034 if (mLoadType == LOAD_REFRESH && !inputStream && equalUri) {
11035 SetHistoryEntryAndUpdateBC(Some<nsISHEntry*>(mOSHE), Nothing());
11036 }
11037
11038 /* If the user pressed shift-reload, cache will create a new cache key
11039 * for the page. Save the new cacheKey in Session History.
11040 * see bug 90098
11041 */
11042 if (aChannel && IsForceReloadType(mLoadType)) {
11043 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"
, 11045); 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) = 11045; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
11044 "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"
, 11045); 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) = 11045; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
11045 " 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"
, 11045); 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) = 11045; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11046
11047 nsCOMPtr<nsICacheInfoChannel> cacheChannel(do_QueryInterface(aChannel));
11048 uint32_t cacheKey = 0;
11049 // Get the Cache Key and store it in SH.
11050 if (cacheChannel) {
11051 cacheChannel->GetCacheKey(&cacheKey);
11052 }
11053 // If we already have a loading history entry, store the new cache key
11054 // in it. Otherwise, since we're doing a reload and won't be updating
11055 // our history entry, store the cache key in our current history entry.
11056 SetCacheKeyOnHistoryEntry(mLSHE ? mLSHE : mOSHE, cacheKey);
11057
11058 if (!mozilla::SessionHistoryInParent()) {
11059 // Since we're force-reloading, clear all the sub frame history.
11060 ClearFrameHistory(mLSHE);
11061 ClearFrameHistory(mOSHE);
11062 }
11063 }
11064
11065 if (!mozilla::SessionHistoryInParent()) {
11066 // Clear subframe history on refresh.
11067 // XXX: history.go(0) won't go this path as mLoadType is LOAD_HISTORY in
11068 // this case. One should re-validate after bug 1331865 fixed.
11069 if (mLoadType == LOAD_REFRESH) {
11070 ClearFrameHistory(mLSHE);
11071 ClearFrameHistory(mOSHE);
11072 }
11073
11074 if (updateSHistory) {
11075 // Update session history if necessary...
11076 if (!mLSHE && (mItemType == typeContent) && mURIResultedInDocument) {
11077 /* This is a fresh page getting loaded for the first time
11078 *.Create a Entry for it and add it to SH, if this is the
11079 * rootDocShell
11080 */
11081 (void)AddToSessionHistory(aURI, aChannel, aTriggeringPrincipal,
11082 aPrincipalToInherit,
11083 aPartitionedPrincipalToInherit, aCsp,
11084 aCloneSHChildren, getter_AddRefs(mLSHE));
11085 }
11086 } else if (GetSessionHistory() && mLSHE && mURIResultedInDocument) {
11087 // Even if we don't add anything to SHistory, ensure the current index
11088 // points to the same SHEntry as our mLSHE.
11089
11090 GetSessionHistory()->LegacySHistory()->EnsureCorrectEntryAtCurrIndex(
11091 mLSHE);
11092 }
11093 }
11094
11095 // If this is a POST request, we do not want to include this in global
11096 // history.
11097 if (ShouldAddURIVisit(aChannel) && updateGHistory && aAddToGlobalHistory &&
11098 !net::ChannelIsPost(aChannel)) {
11099 nsCOMPtr<nsIURI> previousURI;
11100 uint32_t previousFlags = 0;
11101
11102 if (mLoadType & LOAD_CMD_RELOAD) {
11103 // On a reload request, we don't set redirecting flags.
11104 previousURI = aURI;
11105 } else {
11106 ExtractLastVisit(aChannel, getter_AddRefs(previousURI), &previousFlags);
11107 }
11108
11109 AddURIVisit(aURI, previousURI, previousFlags, responseStatus);
11110 }
11111
11112 // If this was a history load or a refresh, or it was a history load but
11113 // later changed to LOAD_NORMAL_REPLACE due to redirection, update the index
11114 // in session history.
11115 if (!mozilla::SessionHistoryInParent() && rootSH &&
11116 ((mLoadType & (LOAD_CMD_HISTORY | LOAD_CMD_RELOAD)) ||
11117 mLoadType == LOAD_NORMAL_REPLACE || mLoadType == LOAD_REFRESH_REPLACE)) {
11118 mPreviousEntryIndex = rootSH->Index();
11119 if (!mozilla::SessionHistoryInParent()) {
11120 rootSH->LegacySHistory()->UpdateIndex();
11121 }
11122 mLoadedEntryIndex = rootSH->Index();
11123 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)
11124 ("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)
11125 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)
;
11126 }
11127
11128 // aCloneSHChildren exactly means "we are not loading a new document".
11129 uint32_t locationFlags =
11130 aCloneSHChildren ? uint32_t(LOCATION_CHANGE_SAME_DOCUMENT) : 0;
11131
11132 bool onLocationChangeNeeded =
11133 SetCurrentURI(aURI, aChannel, false,
11134 /* aIsInitialAboutBlank */ false, locationFlags);
11135 // Make sure to store the referrer from the channel, if any
11136 nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(aChannel));
11137 if (httpChannel) {
11138 mReferrerInfo = httpChannel->GetReferrerInfo();
11139 }
11140 return onLocationChangeNeeded;
11141}
11142
11143Maybe<Wireframe> nsDocShell::GetWireframe() {
11144 const bool collectWireFrame =
11145 mozilla::SessionHistoryInParent() &&
11146 StaticPrefs::browser_history_collectWireframes() &&
11147 mBrowsingContext->IsTopContent() && mActiveEntry;
11148
11149 if (!collectWireFrame) {
11150 return Nothing();
11151 }
11152
11153 RefPtr<Document> doc = mDocumentViewer->GetDocument();
11154 Nullable<Wireframe> wireframe;
11155 doc->GetWireframeWithoutFlushing(false, wireframe);
11156 if (wireframe.IsNull()) {
11157 return Nothing();
11158 }
11159 return Some(wireframe.Value());
11160}
11161
11162bool nsDocShell::CollectWireframe() {
11163 Maybe<Wireframe> wireframe = GetWireframe();
11164 if (wireframe.isNothing()) {
11165 return false;
11166 }
11167
11168 if (XRE_IsParentProcess()) {
11169 SessionHistoryEntry* entry =
11170 mBrowsingContext->Canonical()->GetActiveSessionHistoryEntry();
11171 if (entry) {
11172 entry->SetWireframe(wireframe);
11173 }
11174 } else {
11175 mozilla::Unused
11176 << ContentChild::GetSingleton()->SendSessionHistoryEntryWireframe(
11177 mBrowsingContext, wireframe.ref());
11178 }
11179
11180 return true;
11181}
11182
11183//*****************************************************************************
11184// nsDocShell: Session History
11185//*****************************************************************************
11186
11187NS_IMETHODIMPnsresult
11188nsDocShell::AddState(JS::Handle<JS::Value> aData, const nsAString& aTitle,
11189 const nsAString& aURL, bool aReplace, JSContext* aCx) {
11190 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)
11191 ("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)
11192 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)
11193 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)
;
11194 // Implements History.pushState and History.replaceState
11195
11196 // Here's what we do, roughly in the order specified by HTML5. The specific
11197 // steps we are executing are at
11198 // <https://html.spec.whatwg.org/multipage/history.html#dom-history-pushstate>
11199 // and
11200 // <https://html.spec.whatwg.org/multipage/history.html#url-and-history-update-steps>.
11201 // This function basically implements #dom-history-pushstate and
11202 // UpdateURLAndHistory implements #url-and-history-update-steps.
11203 //
11204 // A. Serialize aData using structured clone. This is #dom-history-pushstate
11205 // step 5.
11206 // B. If the third argument is present, #dom-history-pushstate step 7.
11207 // 7.1. Resolve the url, relative to our document.
11208 // 7.2. If (a) fails, raise a SECURITY_ERR
11209 // 7.4. Compare the resulting absolute URL to the document's address. If
11210 // any part of the URLs difer other than the <path>, <query>, and
11211 // <fragment> components, raise a SECURITY_ERR and abort.
11212 // C. If !aReplace, #url-and-history-update-steps steps 2.1-2.3:
11213 // Remove from the session history all entries after the current entry,
11214 // as we would after a regular navigation, and save the current
11215 // entry's scroll position (bug 590573).
11216 // D. #url-and-history-update-steps step 2.4 or step 3. As apropriate,
11217 // either add a state object entry to the session history after the
11218 // current entry with the following properties, or modify the current
11219 // session history entry to set
11220 // a. cloned data as the state object,
11221 // b. if the third argument was present, the absolute URL found in
11222 // step 2
11223 // Also clear the new history entry's POST data (see bug 580069).
11224 // E. If aReplace is false (i.e. we're doing a pushState instead of a
11225 // replaceState), notify bfcache that we've navigated to a new page.
11226 // F. If the third argument is present, set the document's current address
11227 // to the absolute URL found in step B. This is
11228 // #url-and-history-update-steps step 4.
11229 //
11230 // It's important that this function not run arbitrary scripts after step A
11231 // and before completing step E. For example, if a script called
11232 // history.back() before we completed step E, bfcache might destroy an
11233 // active content viewer. Since EvictOutOfRangeDocumentViewers at the end of
11234 // step E might run script, we can't just put a script blocker around the
11235 // critical section.
11236 //
11237 // Note that we completely ignore the aTitle parameter.
11238
11239 nsresult rv;
11240
11241 // Don't clobber the load type of an existing network load.
11242 AutoRestore<uint32_t> loadTypeResetter(mLoadType);
11243
11244 // pushState effectively becomes replaceState when we've started a network
11245 // load but haven't adopted its document yet. This mirrors what we do with
11246 // changes to the hash at this stage of the game.
11247 if (JustStartedNetworkLoad()) {
11248 aReplace = true;
11249 }
11250
11251 RefPtr<Document> document = GetDocument();
11252 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"
, 11252); return NS_ERROR_FAILURE; } } while (false)
;
11253
11254 // Step A: Serialize aData using structured clone.
11255 // https://html.spec.whatwg.org/multipage/history.html#dom-history-pushstate
11256 // step 5.
11257 nsCOMPtr<nsIStructuredCloneContainer> scContainer;
11258
11259 // scContainer->Init might cause arbitrary JS to run, and this code might
11260 // navigate the page we're on, potentially to a different origin! (bug
11261 // 634834) To protect against this, we abort if our principal changes due
11262 // to the InitFromJSVal() call.
11263 {
11264 RefPtr<Document> origDocument = GetDocument();
11265 if (!origDocument) {
11266 return NS_ERROR_DOM_SECURITY_ERR;
11267 }
11268 nsCOMPtr<nsIPrincipal> origPrincipal = origDocument->NodePrincipal();
11269
11270 scContainer = new nsStructuredCloneContainer();
11271 rv = scContainer->InitFromJSVal(aData, aCx);
11272 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"
, 11272); return rv; } } while (false)
;
11273
11274 RefPtr<Document> newDocument = GetDocument();
11275 if (!newDocument) {
11276 return NS_ERROR_DOM_SECURITY_ERR;
11277 }
11278 nsCOMPtr<nsIPrincipal> newPrincipal = newDocument->NodePrincipal();
11279
11280 bool principalsEqual = false;
11281 origPrincipal->Equals(newPrincipal, &principalsEqual);
11282 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"
, 11282); return NS_ERROR_DOM_SECURITY_ERR; } } while (false)
;
11283 }
11284
11285 // Check that the state object isn't too long.
11286 int32_t maxStateObjSize = StaticPrefs::browser_history_maxStateObjectSize();
11287 if (maxStateObjSize < 0) {
11288 maxStateObjSize = 0;
11289 }
11290
11291 uint64_t scSize;
11292 rv = scContainer->GetSerializedNBytes(&scSize);
11293 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"
, 11293); return rv; } } while (false)
;
11294
11295 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"
, 11295); return NS_ERROR_ILLEGAL_VALUE; } } while (false)
;
11296
11297 // Step B: Resolve aURL.
11298 // https://html.spec.whatwg.org/multipage/history.html#dom-history-pushstate
11299 // step 7.
11300 bool equalURIs = true;
11301 nsCOMPtr<nsIURI> currentURI;
11302 if (mCurrentURI) {
11303 currentURI = nsIOService::CreateExposableURI(mCurrentURI);
11304 } else {
11305 currentURI = mCurrentURI;
11306 }
11307 nsCOMPtr<nsIURI> newURI;
11308 if (aURL.Length() == 0) {
11309 newURI = currentURI;
11310 } else {
11311 // 7.1: Resolve aURL relative to mURI
11312
11313 nsIURI* docBaseURI = document->GetDocBaseURI();
11314 if (!docBaseURI) {
11315 return NS_ERROR_FAILURE;
11316 }
11317
11318 nsAutoCString spec;
11319 docBaseURI->GetSpec(spec);
11320
11321 rv = NS_NewURI(getter_AddRefs(newURI), aURL,
11322 document->GetDocumentCharacterSet(), docBaseURI);
11323
11324 // 7.2: If 2a fails, raise a SECURITY_ERR
11325 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
11326 return NS_ERROR_DOM_SECURITY_ERR;
11327 }
11328
11329 // 7.4 and 7.5: Same-origin check.
11330 if (!nsContentUtils::URIIsLocalFile(newURI)) {
11331 // In addition to checking that the security manager says that
11332 // the new URI has the same origin as our current URI, we also
11333 // check that the two URIs have the same userpass. (The
11334 // security manager says that |http://foo.com| and
11335 // |http://me@foo.com| have the same origin.) currentURI
11336 // won't contain the password part of the userpass, so this
11337 // means that it's never valid to specify a password in a
11338 // pushState or replaceState URI.
11339
11340 nsCOMPtr<nsIScriptSecurityManager> secMan =
11341 do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID"@mozilla.org/scriptsecuritymanager;1");
11342 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"
, 11342); return NS_ERROR_FAILURE; } } while (false)
;
11343
11344 // It's very important that we check that newURI is of the same
11345 // origin as currentURI, not docBaseURI, because a page can
11346 // set docBaseURI arbitrarily to any domain.
11347 nsAutoCString currentUserPass, newUserPass;
11348 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"
, 11349); return NS_ERROR_FAILURE; } } while (false)
11349 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"
, 11349); return NS_ERROR_FAILURE; } } while (false)
;
11350 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"
, 11350); return NS_ERROR_FAILURE; } } while (false)
;
11351 bool isPrivateWin =
11352 document->NodePrincipal()->OriginAttributesRef().mPrivateBrowsingId >
11353 0;
11354 if (NS_FAILED(secMan->CheckSameOriginURI(currentURI, newURI, true,((bool)(__builtin_expect(!!(NS_FAILED_impl(secMan->CheckSameOriginURI
(currentURI, newURI, true, isPrivateWin))), 0)))
11355 isPrivateWin))((bool)(__builtin_expect(!!(NS_FAILED_impl(secMan->CheckSameOriginURI
(currentURI, newURI, true, isPrivateWin))), 0)))
||
11356 !currentUserPass.Equals(newUserPass)) {
11357 return NS_ERROR_DOM_SECURITY_ERR;
11358 }
11359 } else {
11360 // It's a file:// URI
11361 nsCOMPtr<nsIPrincipal> principal = document->GetPrincipal();
11362
11363 if (!principal || NS_FAILED(principal->CheckMayLoadWithReporting(((bool)(__builtin_expect(!!(NS_FAILED_impl(principal->CheckMayLoadWithReporting
( newURI, false, document->InnerWindowID()))), 0)))
11364 newURI, false, document->InnerWindowID()))((bool)(__builtin_expect(!!(NS_FAILED_impl(principal->CheckMayLoadWithReporting
( newURI, false, document->InnerWindowID()))), 0)))
) {
11365 return NS_ERROR_DOM_SECURITY_ERR;
11366 }
11367 }
11368
11369 if (currentURI) {
11370 currentURI->Equals(newURI, &equalURIs);
11371 } else {
11372 equalURIs = false;
11373 }
11374
11375 } // end of same-origin check
11376
11377 // Step 8: call "URL and history update steps"
11378 rv = UpdateURLAndHistory(document, newURI, scContainer, aTitle, aReplace,
11379 currentURI, equalURIs);
11380 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"
, 11380); return rv; } } while (false)
;
11381
11382 return NS_OK;
11383}
11384
11385nsresult nsDocShell::UpdateURLAndHistory(Document* aDocument, nsIURI* aNewURI,
11386 nsIStructuredCloneContainer* aData,
11387 const nsAString& aTitle, bool aReplace,
11388 nsIURI* aCurrentURI, bool aEqualURIs) {
11389 // Implements
11390 // https://html.spec.whatwg.org/multipage/history.html#url-and-history-update-steps
11391
11392 // If we have a pending title change, handle it before creating a new entry.
11393 aDocument->DoNotifyPossibleTitleChange();
11394
11395 // Step 2, if aReplace is false: Create a new entry in the session
11396 // history. This will erase all SHEntries after the new entry and make this
11397 // entry the current one. This operation may modify mOSHE, which we need
11398 // later, so we keep a reference here.
11399 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"
, 11399); return NS_ERROR_FAILURE; } } while (false)
;
11400 nsCOMPtr<nsISHEntry> oldOSHE = mOSHE;
11401
11402 // If this push/replaceState changed the document's current URI and the new
11403 // URI differs from the old URI in more than the hash, or if the old
11404 // SHEntry's URI was modified in this way by a push/replaceState call
11405 // set URIWasModified to true for the current SHEntry (bug 669671).
11406 bool sameExceptHashes = true;
11407 aNewURI->EqualsExceptRef(aCurrentURI, &sameExceptHashes);
11408 bool uriWasModified;
11409 if (sameExceptHashes) {
11410 if (mozilla::SessionHistoryInParent()) {
11411 uriWasModified = mActiveEntry && mActiveEntry->GetURIWasModified();
11412 } else {
11413 uriWasModified = oldOSHE && oldOSHE->GetURIWasModified();
11414 }
11415 } else {
11416 uriWasModified = true;
11417 }
11418
11419 mLoadType = LOAD_PUSHSTATE;
11420
11421 nsCOMPtr<nsISHEntry> newSHEntry;
11422 if (!aReplace) {
11423 // Step 2.
11424
11425 // Step 2.2, "Remove any tasks queued by the history traversal task
11426 // source that are associated with any Document objects in the
11427 // top-level browsing context's document family." This is very hard in
11428 // SessionHistoryInParent since we can't synchronously access the
11429 // pending navigations that are already sent to the parent. We can
11430 // abort any AsyncGo navigations that are waiting to be sent. If we
11431 // send a message to the parent, it would be processed after any
11432 // navigations previously sent. So long as we consider the "history
11433 // traversal task source" to be the list in this process we match the
11434 // spec. If we move the entire list to the parent, we can handle the
11435 // aborting of loads there, but we don't have a way to synchronously
11436 // remove entries as we do here for non-SHIP.
11437 RefPtr<ChildSHistory> shistory = GetRootSessionHistory();
11438 if (shistory) {
11439 shistory->RemovePendingHistoryNavigations();
11440 }
11441
11442 nsPoint scrollPos = GetCurScrollPos();
11443
11444 bool scrollRestorationIsManual;
11445 if (mozilla::SessionHistoryInParent()) {
11446 // FIXME Need to save the current scroll position on mActiveEntry.
11447 scrollRestorationIsManual = mActiveEntry->GetScrollRestorationIsManual();
11448 } else {
11449 // Save the current scroll position (bug 590573). Step 2.3.
11450 mOSHE->SetScrollPosition(scrollPos.x, scrollPos.y);
11451
11452 scrollRestorationIsManual = mOSHE->GetScrollRestorationIsManual();
11453 }
11454
11455 nsCOMPtr<nsIContentSecurityPolicy> csp = aDocument->GetCsp();
11456
11457 if (mozilla::SessionHistoryInParent()) {
11458 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)
11459 ("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)
;
11460 nsString title(mActiveEntry->GetTitle());
11461 UpdateActiveEntry(false,
11462 /* aPreviousScrollPos = */ Some(scrollPos), aNewURI,
11463 /* aOriginalURI = */ nullptr,
11464 /* aReferrerInfo = */ nullptr,
11465 /* aTriggeringPrincipal = */ aDocument->NodePrincipal(),
11466 csp, title, scrollRestorationIsManual, aData,
11467 uriWasModified);
11468 } else {
11469 // Since we're not changing which page we have loaded, pass
11470 // true for aCloneChildren.
11471 nsresult rv = AddToSessionHistory(
11472 aNewURI, nullptr,
11473 aDocument->NodePrincipal(), // triggeringPrincipal
11474 nullptr, nullptr, csp, true, getter_AddRefs(newSHEntry));
11475 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"
, 11475); return rv; } } while (false)
;
11476
11477 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"
, 11477); return NS_ERROR_FAILURE; } } while (false)
;
11478
11479 // Session history entries created by pushState inherit scroll restoration
11480 // mode from the current entry.
11481 newSHEntry->SetScrollRestorationIsManual(scrollRestorationIsManual);
11482
11483 nsString title;
11484 mOSHE->GetTitle(title);
11485
11486 // Set the new SHEntry's title (bug 655273).
11487 newSHEntry->SetTitle(title);
11488
11489 // Link the new SHEntry to the old SHEntry's BFCache entry, since the
11490 // two entries correspond to the same document.
11491 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"
, 11492); return NS_ERROR_FAILURE; } } while (false)
11492 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"
, 11492); return NS_ERROR_FAILURE; } } while (false)
;
11493
11494 // AddToSessionHistory may not modify mOSHE. In case it doesn't,
11495 // we'll just set mOSHE here.
11496 mOSHE = newSHEntry;
11497 }
11498 } else if (mozilla::SessionHistoryInParent()) {
11499 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)
11500 ("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)
11501 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)
;
11502 // Setting the resultPrincipalURI to nullptr is fine here: it will cause
11503 // NS_GetFinalChannelURI to use the originalURI as the URI, which is aNewURI
11504 // in our case. We could also set it to aNewURI, with the same result.
11505 // We don't use aTitle here, see bug 544535.
11506 nsString title;
11507 nsCOMPtr<nsIReferrerInfo> referrerInfo;
11508 if (mActiveEntry) {
11509 title = mActiveEntry->GetTitle();
11510 referrerInfo = mActiveEntry->GetReferrerInfo();
11511 } else {
11512 referrerInfo = nullptr;
11513 }
11514 UpdateActiveEntry(
11515 true, /* aPreviousScrollPos = */ Nothing(), aNewURI, aNewURI,
11516 /* aReferrerInfo = */ referrerInfo, aDocument->NodePrincipal(),
11517 aDocument->GetCsp(), title,
11518 mActiveEntry && mActiveEntry->GetScrollRestorationIsManual(), aData,
11519 uriWasModified);
11520 } else {
11521 // Step 3.
11522 newSHEntry = mOSHE;
11523
11524 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)
;
11525 // Since we're not changing which page we have loaded, pass
11526 // true for aCloneChildren.
11527 if (!newSHEntry) {
11528 nsresult rv = AddToSessionHistory(
11529 aNewURI, nullptr,
11530 aDocument->NodePrincipal(), // triggeringPrincipal
11531 nullptr, nullptr, aDocument->GetCsp(), true,
11532 getter_AddRefs(newSHEntry));
11533 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"
, 11533); return rv; } } while (false)
;
11534 mOSHE = newSHEntry;
11535 }
11536
11537 newSHEntry->SetURI(aNewURI);
11538 newSHEntry->SetOriginalURI(aNewURI);
11539 // We replaced the URI of the entry, clear the unstripped URI as it
11540 // shouldn't be used for reloads anymore.
11541 newSHEntry->SetUnstrippedURI(nullptr);
11542 // Setting the resultPrincipalURI to nullptr is fine here: it will cause
11543 // NS_GetFinalChannelURI to use the originalURI as the URI, which is aNewURI
11544 // in our case. We could also set it to aNewURI, with the same result.
11545 newSHEntry->SetResultPrincipalURI(nullptr);
11546 newSHEntry->SetLoadReplace(false);
11547 }
11548
11549 if (!mozilla::SessionHistoryInParent()) {
11550 // Step 2.4 and 3: Modify new/original session history entry and clear its
11551 // POST data, if there is any.
11552 newSHEntry->SetStateData(aData);
11553 newSHEntry->SetPostData(nullptr);
11554
11555 newSHEntry->SetURIWasModified(uriWasModified);
11556
11557 // Step E as described at the top of AddState: If aReplace is false,
11558 // indicating that we're doing a pushState rather than a replaceState,
11559 // notify bfcache that we've added a page to the history so it can evict
11560 // content viewers if appropriate. Otherwise call ReplaceEntry so that we
11561 // notify nsIHistoryListeners that an entry was replaced. We may not have a
11562 // root session history if this call is coming from a document.open() in a
11563 // docshell subtree that disables session history.
11564 RefPtr<ChildSHistory> rootSH = GetRootSessionHistory();
11565 if (rootSH) {
11566 rootSH->LegacySHistory()->EvictDocumentViewersOrReplaceEntry(newSHEntry,
11567 aReplace);
11568 }
11569 }
11570
11571 // Step 4: If the document's URI changed, update document's URI and update
11572 // global history.
11573 //
11574 // We need to call FireOnLocationChange so that the browser's address bar
11575 // gets updated and the back button is enabled, but we only need to
11576 // explicitly call FireOnLocationChange if we're not calling SetCurrentURI,
11577 // since SetCurrentURI will call FireOnLocationChange for us.
11578 //
11579 // Both SetCurrentURI(...) and FireDummyOnLocationChange() pass
11580 // nullptr for aRequest param to FireOnLocationChange(...). Such an update
11581 // notification is allowed only when we know docshell is not loading a new
11582 // document and it requires LOCATION_CHANGE_SAME_DOCUMENT flag. Otherwise,
11583 // FireOnLocationChange(...) breaks security UI.
11584 //
11585 // If the docshell is shutting down, don't update the document URI, as we
11586 // can't load into a docshell that is being destroyed.
11587 if (!aEqualURIs && !mIsBeingDestroyed) {
11588 aDocument->SetDocumentURI(aNewURI);
11589 SetCurrentURI(aNewURI, nullptr, /* aFireLocationChange */ true,
11590 /* aIsInitialAboutBlank */ false,
11591 GetSameDocumentNavigationFlags(aNewURI));
11592
11593 AddURIVisit(aNewURI, aCurrentURI, 0);
11594
11595 // AddURIVisit doesn't set the title for the new URI in global history,
11596 // so do that here.
11597 UpdateGlobalHistoryTitle(aNewURI);
11598
11599 // Inform the favicon service that our old favicon applies to this new
11600 // URI.
11601 CopyFavicon(aCurrentURI, aNewURI, UsePrivateBrowsing());
11602 } else {
11603 FireDummyOnLocationChange();
11604 }
11605 aDocument->SetStateObject(aData);
11606
11607 return NS_OK;
11608}
11609
11610NS_IMETHODIMPnsresult
11611nsDocShell::GetCurrentScrollRestorationIsManual(bool* aIsManual) {
11612 if (mozilla::SessionHistoryInParent()) {
11613 *aIsManual = mActiveEntry && mActiveEntry->GetScrollRestorationIsManual();
11614 return NS_OK;
11615 }
11616
11617 *aIsManual = false;
11618 if (mOSHE) {
11619 return mOSHE->GetScrollRestorationIsManual(aIsManual);
11620 }
11621
11622 return NS_OK;
11623}
11624
11625NS_IMETHODIMPnsresult
11626nsDocShell::SetCurrentScrollRestorationIsManual(bool aIsManual) {
11627 SetScrollRestorationIsManualOnHistoryEntry(mOSHE, aIsManual);
11628
11629 return NS_OK;
11630}
11631
11632void nsDocShell::SetScrollRestorationIsManualOnHistoryEntry(
11633 nsISHEntry* aSHEntry, bool aIsManual) {
11634 if (aSHEntry) {
11635 aSHEntry->SetScrollRestorationIsManual(aIsManual);
11636 }
11637
11638 if (mActiveEntry && mBrowsingContext) {
11639 mActiveEntry->SetScrollRestorationIsManual(aIsManual);
11640 if (XRE_IsParentProcess()) {
11641 SessionHistoryEntry* entry =
11642 mBrowsingContext->Canonical()->GetActiveSessionHistoryEntry();
11643 if (entry) {
11644 entry->SetScrollRestorationIsManual(aIsManual);
11645 }
11646 } else {
11647 mozilla::Unused << ContentChild::GetSingleton()
11648 ->SendSessionHistoryEntryScrollRestorationIsManual(
11649 mBrowsingContext, aIsManual);
11650 }
11651 }
11652}
11653
11654void nsDocShell::SetCacheKeyOnHistoryEntry(nsISHEntry* aSHEntry,
11655 uint32_t aCacheKey) {
11656 if (aSHEntry) {
11657 aSHEntry->SetCacheKey(aCacheKey);
11658 }
11659
11660 if (mActiveEntry && mBrowsingContext) {
11661 mActiveEntry->SetCacheKey(aCacheKey);
11662 if (XRE_IsParentProcess()) {
11663 SessionHistoryEntry* entry =
11664 mBrowsingContext->Canonical()->GetActiveSessionHistoryEntry();
11665 if (entry) {
11666 entry->SetCacheKey(aCacheKey);
11667 }
11668 } else {
11669 mozilla::Unused
11670 << ContentChild::GetSingleton()->SendSessionHistoryEntryCacheKey(
11671 mBrowsingContext, aCacheKey);
11672 }
11673 }
11674}
11675
11676/* static */
11677bool nsDocShell::ShouldAddToSessionHistory(nsIURI* aURI, nsIChannel* aChannel) {
11678 // I believe none of the about: urls should go in the history. But then
11679 // that could just be me... If the intent is only deny about:blank then we
11680 // should just do a spec compare, rather than two gets of the scheme and
11681 // then the path. -Gagan
11682 nsresult rv;
11683 nsAutoCString buf;
11684
11685 rv = aURI->GetScheme(buf);
11686 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
11687 return false;
11688 }
11689
11690 if (buf.EqualsLiteral("about")) {
11691 rv = aURI->GetPathQueryRef(buf);
11692 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
11693 return false;
11694 }
11695
11696 if (buf.EqualsLiteral("blank")) {
11697 return false;
11698 }
11699 // We only want to add about:newtab if it's not privileged, and
11700 // if it is not configured to show the blank page.
11701 if (buf.EqualsLiteral("newtab")) {
11702 if (!StaticPrefs::browser_newtabpage_enabled()) {
11703 return false;
11704 }
11705
11706 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"
, 11706); return false; } } while (false)
;
11707 nsCOMPtr<nsIPrincipal> resultPrincipal;
11708 rv = nsContentUtils::GetSecurityManager()->GetChannelResultPrincipal(
11709 aChannel, getter_AddRefs(resultPrincipal));
11710 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"
, 11710); return false; } } while (false)
;
11711 return !resultPrincipal->IsSystemPrincipal();
11712 }
11713 }
11714
11715 return true;
11716}
11717
11718nsresult nsDocShell::AddToSessionHistory(
11719 nsIURI* aURI, nsIChannel* aChannel, nsIPrincipal* aTriggeringPrincipal,
11720 nsIPrincipal* aPrincipalToInherit,
11721 nsIPrincipal* aPartitionedPrincipalToInherit,
11722 nsIContentSecurityPolicy* aCsp, bool aCloneChildren,
11723 nsISHEntry** aNewEntry) {
11724 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"
, 11724); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aURI" ") ("
"uri is null" ")"); do { *((volatile int*)__null) = 11724; __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
;
11725 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"
, 11725); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aChannel || !aTriggeringPrincipal"
") (" "Shouldn't have both set" ")"); do { *((volatile int*)
__null) = 11725; __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
11726 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"
, 11726); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "!mozilla::SessionHistoryInParent()"
")"); do { *((volatile int*)__null) = 11726; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11727
11728#if defined(DEBUG1)
11729 if (MOZ_LOG_TEST(gDocShellLog, LogLevel::Debug)(__builtin_expect(!!(mozilla::detail::log_test(gDocShellLog, LogLevel
::Debug)), 0))
) {
11730 nsAutoCString chanName;
11731 if (aChannel) {
11732 aChannel->GetName(chanName);
11733 } else {
11734 chanName.AssignLiteral("<no channel>");
11735 }
11736
11737 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)
11738 ("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)
11739 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)
;
11740 }
11741#endif
11742
11743 nsresult rv = NS_OK;
11744 nsCOMPtr<nsISHEntry> entry;
11745
11746 /*
11747 * If this is a LOAD_FLAGS_REPLACE_HISTORY in a subframe, we use
11748 * the existing SH entry in the page and replace the url and
11749 * other vitalities.
11750 */
11751 if (LOAD_TYPE_HAS_FLAGS(mLoadType, LOAD_FLAGS_REPLACE_HISTORY)((mLoadType) & ((LOAD_FLAGS_REPLACE_HISTORY) << 16)
)
&&
11752 !mBrowsingContext->IsTop()) {
11753 // This is a subframe
11754 entry = mOSHE;
11755 if (entry) {
11756 entry->ClearEntry();
11757 }
11758 }
11759
11760 // Create a new entry if necessary.
11761 if (!entry) {
11762 entry = new nsSHEntry();
11763 }
11764
11765 // Get the post data & referrer
11766 nsCOMPtr<nsIInputStream> inputStream;
11767 nsCOMPtr<nsIURI> originalURI;
11768 nsCOMPtr<nsIURI> resultPrincipalURI;
11769 nsCOMPtr<nsIURI> unstrippedURI;
11770 bool loadReplace = false;
11771 nsCOMPtr<nsIReferrerInfo> referrerInfo;
11772 uint32_t cacheKey = 0;
11773 nsCOMPtr<nsIPrincipal> triggeringPrincipal = aTriggeringPrincipal;
11774 nsCOMPtr<nsIPrincipal> principalToInherit = aPrincipalToInherit;
11775 nsCOMPtr<nsIPrincipal> partitionedPrincipalToInherit =
11776 aPartitionedPrincipalToInherit;
11777 nsCOMPtr<nsIContentSecurityPolicy> csp = aCsp;
11778 bool expired = false; // by default the page is not expired
11779 bool discardLayoutState = false;
11780 nsCOMPtr<nsICacheInfoChannel> cacheChannel;
11781 bool userActivation = false;
11782
11783 if (aChannel) {
11784 cacheChannel = do_QueryInterface(aChannel);
11785
11786 /* If there is a caching channel, get the Cache Key and store it
11787 * in SH.
11788 */
11789 if (cacheChannel) {
11790 cacheChannel->GetCacheKey(&cacheKey);
11791 }
11792 nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(aChannel));
11793
11794 // Check if the httpChannel is hiding under a multipartChannel
11795 if (!httpChannel) {
11796 GetHttpChannel(aChannel, getter_AddRefs(httpChannel));
11797 }
11798 if (httpChannel) {
11799 nsCOMPtr<nsIUploadChannel> uploadChannel(do_QueryInterface(httpChannel));
11800 if (uploadChannel) {
11801 uploadChannel->GetUploadStream(getter_AddRefs(inputStream));
11802 }
11803 httpChannel->GetOriginalURI(getter_AddRefs(originalURI));
11804 uint32_t loadFlags;
11805 aChannel->GetLoadFlags(&loadFlags);
11806 loadReplace = loadFlags & nsIChannel::LOAD_REPLACE;
11807 rv = httpChannel->GetReferrerInfo(getter_AddRefs(referrerInfo));
11808 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"
, 11808); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { *((volatile int*)__null) = 11808; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11809
11810 discardLayoutState = ShouldDiscardLayoutState(httpChannel);
11811 }
11812
11813 nsCOMPtr<nsILoadInfo> loadInfo = aChannel->LoadInfo();
11814 if (!triggeringPrincipal) {
11815 triggeringPrincipal = loadInfo->TriggeringPrincipal();
11816 }
11817 if (!csp) {
11818 csp = loadInfo->GetCspToInherit();
11819 }
11820
11821 loadInfo->GetResultPrincipalURI(getter_AddRefs(resultPrincipalURI));
11822
11823 loadInfo->GetUnstrippedURI(getter_AddRefs(unstrippedURI));
11824
11825 userActivation = loadInfo->GetHasValidUserGestureActivation();
11826
11827 // For now keep storing just the principal in the SHEntry.
11828 if (!principalToInherit) {
11829 if (loadInfo->GetLoadingSandboxed()) {
11830 if (loadInfo->GetLoadingPrincipal()) {
11831 principalToInherit = NullPrincipal::CreateWithInheritedAttributes(
11832 loadInfo->GetLoadingPrincipal());
11833 } else {
11834 // get the OriginAttributes
11835 OriginAttributes attrs;
11836 loadInfo->GetOriginAttributes(&attrs);
11837 principalToInherit = NullPrincipal::Create(attrs);
11838 }
11839 } else {
11840 principalToInherit = loadInfo->PrincipalToInherit();
11841 }
11842 }
11843
11844 if (!partitionedPrincipalToInherit) {
11845 // XXXehsan is it correct to fall back to the principal to inherit in all
11846 // cases? For example, what about the cases where we are using the load
11847 // info's principal to inherit? Do we need to add a similar concept to
11848 // load info for partitioned principal?
11849 partitionedPrincipalToInherit = principalToInherit;
11850 }
11851 }
11852
11853 nsAutoString srcdoc;
11854 bool srcdocEntry = false;
11855 nsCOMPtr<nsIURI> baseURI;
11856
11857 nsCOMPtr<nsIInputStreamChannel> inStrmChan = do_QueryInterface(aChannel);
11858 if (inStrmChan) {
11859 bool isSrcdocChannel;
11860 inStrmChan->GetIsSrcdocChannel(&isSrcdocChannel);
11861 if (isSrcdocChannel) {
11862 inStrmChan->GetSrcdocData(srcdoc);
11863 srcdocEntry = true;
11864 inStrmChan->GetBaseURI(getter_AddRefs(baseURI));
11865 } else {
11866 srcdoc.SetIsVoid(true);
11867 }
11868 }
11869 /* If cache got a 'no-store', ask SH not to store
11870 * HistoryLayoutState. By default, SH will set this
11871 * flag to true and save HistoryLayoutState.
11872 */
11873 bool saveLayoutState = !discardLayoutState;
11874
11875 if (cacheChannel) {
11876 // Check if the page has expired from cache
11877 uint32_t expTime = 0;
11878 cacheChannel->GetCacheTokenExpirationTime(&expTime);
11879 uint32_t now = PRTimeToSeconds(PR_Now());
11880 if (expTime <= now) {
11881 expired = true;
11882 }
11883 }
11884
11885 // Title is set in nsDocShell::SetTitle()
11886 entry->Create(aURI, // uri
11887 u""_ns, // Title
11888 inputStream, // Post data stream
11889 cacheKey, // CacheKey
11890 mContentTypeHint, // Content-type
11891 triggeringPrincipal, // Channel or provided principal
11892 principalToInherit, partitionedPrincipalToInherit, csp,
11893 HistoryID(), GetCreatedDynamically(), originalURI,
11894 resultPrincipalURI, unstrippedURI, loadReplace, referrerInfo,
11895 srcdoc, srcdocEntry, baseURI, saveLayoutState, expired,
11896 userActivation);
11897
11898 if (mBrowsingContext->IsTop() && GetSessionHistory()) {
11899 bool shouldPersist = ShouldAddToSessionHistory(aURI, aChannel);
11900 Maybe<int32_t> previousEntryIndex;
11901 Maybe<int32_t> loadedEntryIndex;
11902 rv = GetSessionHistory()->LegacySHistory()->AddToRootSessionHistory(
11903 aCloneChildren, mOSHE, mBrowsingContext, entry, mLoadType,
11904 shouldPersist, &previousEntryIndex, &loadedEntryIndex);
11905
11906 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"
, 11906); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
") (" "Could not add entry to root session history" ")"); do
{ *((volatile int*)__null) = 11906; __attribute__((nomerge))
::abort(); } while (false); } } while (false)
;
11907 if (previousEntryIndex.isSome()) {
11908 mPreviousEntryIndex = previousEntryIndex.value();
11909 }
11910 if (loadedEntryIndex.isSome()) {
11911 mLoadedEntryIndex = loadedEntryIndex.value();
11912 }
11913
11914 // aCloneChildren implies that we are retaining the same document, thus we
11915 // need to signal to the top WC that the new SHEntry may receive a fresh
11916 // user interaction flag.
11917 if (aCloneChildren) {
11918 WindowContext* topWc = mBrowsingContext->GetTopWindowContext();
11919 if (topWc && !topWc->IsDiscarded()) {
11920 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"
, 11920); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "false"
") (" "NS_SUCCEEDED(topWc->SetSHEntryHasUserInteraction(false))"
")"); do { *((volatile int*)__null) = 11920; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false); } } while
(false)
;
11921 }
11922 }
11923 } else {
11924 // This is a subframe, make sure that this new SHEntry will be
11925 // marked with user interaction.
11926 WindowContext* topWc = mBrowsingContext->GetTopWindowContext();
11927 if (topWc && !topWc->IsDiscarded()) {
11928 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"
, 11928); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "false"
") (" "NS_SUCCEEDED(topWc->SetSHEntryHasUserInteraction(false))"
")"); do { *((volatile int*)__null) = 11928; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false); } } while
(false)
;
11929 }
11930 if (!mOSHE || !LOAD_TYPE_HAS_FLAGS(mLoadType, LOAD_FLAGS_REPLACE_HISTORY)((mLoadType) & ((LOAD_FLAGS_REPLACE_HISTORY) << 16)
)
) {
11931 rv = AddChildSHEntryToParent(entry, mBrowsingContext->ChildOffset(),
11932 aCloneChildren);
11933 }
11934 }
11935
11936 // Return the new SH entry...
11937 if (aNewEntry) {
11938 *aNewEntry = nullptr;
11939 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
11940 entry.forget(aNewEntry);
11941 }
11942 }
11943
11944 return rv;
11945}
11946
11947void nsDocShell::UpdateActiveEntry(
11948 bool aReplace, const Maybe<nsPoint>& aPreviousScrollPos, nsIURI* aURI,
11949 nsIURI* aOriginalURI, nsIReferrerInfo* aReferrerInfo,
11950 nsIPrincipal* aTriggeringPrincipal, nsIContentSecurityPolicy* aCsp,
11951 const nsAString& aTitle, bool aScrollRestorationIsManual,
11952 nsIStructuredCloneContainer* aData, bool aURIWasModified) {
11953 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"
, 11953); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mozilla::SessionHistoryInParent()"
")"); do { *((volatile int*)__null) = 11953; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11954 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"
, 11954); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aURI" ") ("
"uri is null" ")"); do { *((volatile int*)__null) = 11954; __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
;
11955 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"
, 11956); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mLoadType == LOAD_PUSHSTATE"
") (" "This code only deals with pushState" ")"); do { *((volatile
int*)__null) = 11956; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
11956 "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"
, 11956); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mLoadType == LOAD_PUSHSTATE"
") (" "This code only deals with pushState" ")"); do { *((volatile
int*)__null) = 11956; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
11957 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"
, 11957); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aReplace"
")"); do { *((volatile int*)__null) = 11957; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false); } } while
(false)
;
11958
11959 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)
11960 ("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)
11961 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)
;
11962
11963 // Even if we're replacing an existing entry we create new a
11964 // SessionHistoryInfo. In the parent process we'll keep the existing
11965 // SessionHistoryEntry, but just replace its SessionHistoryInfo, that way the
11966 // entry keeps identity but its data is replaced.
11967 bool replace = aReplace && mActiveEntry;
11968
11969 if (!replace) {
11970 CollectWireframe();
11971 }
11972
11973 if (mActiveEntry) {
11974 // Link this entry to the previous active entry.
11975 mActiveEntry = MakeUnique<SessionHistoryInfo>(*mActiveEntry, aURI);
11976 } else {
11977 mActiveEntry = MakeUnique<SessionHistoryInfo>(
11978 aURI, aTriggeringPrincipal, nullptr, nullptr, aCsp, mContentTypeHint);
11979 }
11980 mActiveEntry->SetOriginalURI(aOriginalURI);
11981 mActiveEntry->SetUnstrippedURI(nullptr);
11982 mActiveEntry->SetReferrerInfo(aReferrerInfo);
11983 mActiveEntry->SetTitle(aTitle);
11984 mActiveEntry->SetStateData(static_cast<nsStructuredCloneContainer*>(aData));
11985 mActiveEntry->SetURIWasModified(aURIWasModified);
11986 mActiveEntry->SetScrollRestorationIsManual(aScrollRestorationIsManual);
11987
11988 if (replace) {
11989 mBrowsingContext->ReplaceActiveSessionHistoryEntry(mActiveEntry.get());
11990 } else {
11991 mBrowsingContext->IncrementHistoryEntryCountForBrowsingContext();
11992 // FIXME We should probably just compute mChildOffset in the parent
11993 // instead of passing it over IPC here.
11994 mBrowsingContext->SetActiveSessionHistoryEntry(
11995 aPreviousScrollPos, mActiveEntry.get(), mLoadType,
11996 /* aCacheKey = */ 0);
11997 // FIXME Do we need to update mPreviousEntryIndex and mLoadedEntryIndex?
11998 }
11999}
12000
12001nsresult nsDocShell::LoadHistoryEntry(nsISHEntry* aEntry, uint32_t aLoadType,
12002 bool aUserActivation) {
12003 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"
, 12003); return NS_ERROR_FAILURE; } } while (false)
;
12004
12005 nsresult rv;
12006 RefPtr<nsDocShellLoadState> loadState;
12007 rv = aEntry->CreateLoadInfo(getter_AddRefs(loadState));
12008 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"
, 12008); return rv; } } while (false)
;
12009
12010 // Calling CreateAboutBlankDocumentViewer can set mOSHE to null, and if
12011 // that's the only thing holding a ref to aEntry that will cause aEntry to
12012 // die while we're loading it. So hold a strong ref to aEntry here, just
12013 // in case.
12014 nsCOMPtr<nsISHEntry> kungFuDeathGrip(aEntry);
12015
12016 loadState->SetHasValidUserGestureActivation(
12017 loadState->HasValidUserGestureActivation() || aUserActivation);
12018
12019 return LoadHistoryEntry(loadState, aLoadType, aEntry == mOSHE);
12020}
12021
12022nsresult nsDocShell::LoadHistoryEntry(const LoadingSessionHistoryInfo& aEntry,
12023 uint32_t aLoadType,
12024 bool aUserActivation) {
12025 RefPtr<nsDocShellLoadState> loadState = aEntry.CreateLoadInfo();
12026 loadState->SetHasValidUserGestureActivation(
12027 loadState->HasValidUserGestureActivation() || aUserActivation);
12028
12029 return LoadHistoryEntry(loadState, aLoadType, aEntry.mLoadingCurrentEntry);
12030}
12031
12032nsresult nsDocShell::LoadHistoryEntry(nsDocShellLoadState* aLoadState,
12033 uint32_t aLoadType,
12034 bool aLoadingCurrentEntry) {
12035 if (!IsNavigationAllowed()) {
12036 return NS_OK;
12037 }
12038
12039 // We are setting load type afterwards so we don't have to
12040 // send it in an IPC message
12041 aLoadState->SetLoadType(aLoadType);
12042
12043 nsresult rv;
12044 if (SchemeIsJavascript(aLoadState->URI())) {
12045 // We're loading a URL that will execute script from inside asyncOpen.
12046 // Replace the current document with about:blank now to prevent
12047 // anything from the current document from leaking into any JavaScript
12048 // code in the URL.
12049 // Don't cache the presentation if we're going to just reload the
12050 // current entry. Caching would lead to trying to save the different
12051 // content viewers in the same nsISHEntry object.
12052 rv = CreateAboutBlankDocumentViewer(
12053 aLoadState->PrincipalToInherit(),
12054 aLoadState->PartitionedPrincipalToInherit(), nullptr, nullptr,
12055 /* aIsInitialDocument */ false, Nothing(), !aLoadingCurrentEntry);
12056
12057 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
12058 // The creation of the intermittent about:blank content
12059 // viewer failed for some reason (potentially because the
12060 // user prevented it). Interrupt the history load.
12061 return NS_OK;
12062 }
12063
12064 if (!aLoadState->TriggeringPrincipal()) {
12065 // Ensure that we have a triggeringPrincipal. Otherwise javascript:
12066 // URIs will pick it up from the about:blank page we just loaded,
12067 // and we don't really want even that in this case.
12068 nsCOMPtr<nsIPrincipal> principal =
12069 NullPrincipal::Create(GetOriginAttributes());
12070 aLoadState->SetTriggeringPrincipal(principal);
12071 }
12072 }
12073
12074 /* If there is a valid postdata *and* the user pressed
12075 * reload or shift-reload, take user's permission before we
12076 * repost the data to the server.
12077 */
12078 if ((aLoadType & LOAD_CMD_RELOAD) && aLoadState->PostDataStream()) {
12079 bool repost;
12080 rv = ConfirmRepost(&repost);
12081 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
12082 return rv;
12083 }
12084
12085 // If the user pressed cancel in the dialog, return. We're done here.
12086 if (!repost) {
12087 return NS_BINDING_ABORTED;
12088 }
12089 }
12090
12091 // If there is no valid triggeringPrincipal, we deny the load
12092 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"
, 12093); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->TriggeringPrincipal()"
") (" "need a valid triggeringPrincipal to load from history"
")"); do { *((volatile int*)__null) = 12093; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
12093 "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"
, 12093); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->TriggeringPrincipal()"
") (" "need a valid triggeringPrincipal to load from history"
")"); do { *((volatile int*)__null) = 12093; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12094 if (!aLoadState->TriggeringPrincipal()) {
12095 return NS_ERROR_FAILURE;
12096 }
12097
12098 return InternalLoad(aLoadState); // No nsIRequest
12099}
12100
12101NS_IMETHODIMPnsresult
12102nsDocShell::PersistLayoutHistoryState() {
12103 nsresult rv = NS_OK;
12104
12105 if (mozilla::SessionHistoryInParent() ? !!mActiveEntry : !!mOSHE) {
12106 bool scrollRestorationIsManual;
12107 if (mozilla::SessionHistoryInParent()) {
12108 scrollRestorationIsManual = mActiveEntry->GetScrollRestorationIsManual();
12109 } else {
12110 scrollRestorationIsManual = mOSHE->GetScrollRestorationIsManual();
12111 }
12112 nsCOMPtr<nsILayoutHistoryState> layoutState;
12113 if (RefPtr<PresShell> presShell = GetPresShell()) {
12114 rv = presShell->CaptureHistoryState(getter_AddRefs(layoutState));
12115 } else if (scrollRestorationIsManual) {
12116 // Even if we don't have layout anymore, we may want to reset the
12117 // current scroll state in layout history.
12118 GetLayoutHistoryState(getter_AddRefs(layoutState));
12119 }
12120
12121 if (scrollRestorationIsManual && layoutState) {
12122 layoutState->ResetScrollState();
12123 }
12124 }
12125
12126 return rv;
12127}
12128
12129void nsDocShell::SwapHistoryEntries(nsISHEntry* aOldEntry,
12130 nsISHEntry* aNewEntry) {
12131 if (aOldEntry == mOSHE) {
12132 mOSHE = aNewEntry;
12133 }
12134
12135 if (aOldEntry == mLSHE) {
12136 mLSHE = aNewEntry;
12137 }
12138}
12139
12140void nsDocShell::SetHistoryEntryAndUpdateBC(const Maybe<nsISHEntry*>& aLSHE,
12141 const Maybe<nsISHEntry*>& aOSHE) {
12142 // We want to hold on to the reference in mLSHE before we update it.
12143 // Otherwise, SetHistoryEntry could release the last reference to
12144 // the entry while aOSHE is pointing to it.
12145 nsCOMPtr<nsISHEntry> deathGripOldLSHE;
12146 if (aLSHE.isSome()) {
12147 deathGripOldLSHE = SetHistoryEntry(&mLSHE, aLSHE.value());
12148 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"
, 12148); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mLSHE.get() == aLSHE.value()"
")"); do { *((volatile int*)__null) = 12148; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12149 }
12150 nsCOMPtr<nsISHEntry> deathGripOldOSHE;
12151 if (aOSHE.isSome()) {
12152 deathGripOldOSHE = SetHistoryEntry(&mOSHE, aOSHE.value());
12153 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"
, 12153); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mOSHE.get() == aOSHE.value()"
")"); do { *((volatile int*)__null) = 12153; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12154 }
12155}
12156
12157already_AddRefed<nsISHEntry> nsDocShell::SetHistoryEntry(
12158 nsCOMPtr<nsISHEntry>* aPtr, nsISHEntry* aEntry) {
12159 // We need to sync up the docshell and session history trees for
12160 // subframe navigation. If the load was in a subframe, we forward up to
12161 // the root docshell, which will then recursively sync up all docshells
12162 // to their corresponding entries in the new session history tree.
12163 // If we don't do this, then we can cache a content viewer on the wrong
12164 // cloned entry, and subsequently restore it at the wrong time.
12165 RefPtr<BrowsingContext> topBC = mBrowsingContext->Top();
12166 if (topBC->IsDiscarded()) {
12167 topBC = nullptr;
12168 }
12169 RefPtr<BrowsingContext> currBC =
12170 mBrowsingContext->IsDiscarded() ? nullptr : mBrowsingContext;
12171 if (topBC && *aPtr) {
12172 (*aPtr)->SyncTreesForSubframeNavigation(aEntry, topBC, currBC);
12173 }
12174 nsCOMPtr<nsISHEntry> entry(aEntry);
12175 entry.swap(*aPtr);
12176 return entry.forget();
12177}
12178
12179already_AddRefed<ChildSHistory> nsDocShell::GetRootSessionHistory() {
12180 RefPtr<ChildSHistory> childSHistory =
12181 mBrowsingContext->Top()->GetChildSessionHistory();
12182 return childSHistory.forget();
12183}
12184
12185nsresult nsDocShell::GetHttpChannel(nsIChannel* aChannel,
12186 nsIHttpChannel** aReturn) {
12187 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"
, 12187); return NS_ERROR_INVALID_POINTER; } } while (false)
;
12188 if (!aChannel) {
12189 return NS_ERROR_FAILURE;
12190 }
12191
12192 nsCOMPtr<nsIMultiPartChannel> multiPartChannel(do_QueryInterface(aChannel));
12193 if (multiPartChannel) {
12194 nsCOMPtr<nsIChannel> baseChannel;
12195 multiPartChannel->GetBaseChannel(getter_AddRefs(baseChannel));
12196 nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(baseChannel));
12197 *aReturn = httpChannel;
12198 NS_IF_ADDREF(*aReturn)ns_if_addref(*aReturn);
12199 }
12200 return NS_OK;
12201}
12202
12203bool nsDocShell::ShouldDiscardLayoutState(nsIHttpChannel* aChannel) {
12204 // By default layout State will be saved.
12205 if (!aChannel) {
12206 return false;
12207 }
12208
12209 // figure out if SH should be saving layout state
12210 bool noStore = false;
12211 Unused << aChannel->IsNoStoreResponse(&noStore);
12212 return noStore;
12213}
12214
12215NS_IMETHODIMPnsresult
12216nsDocShell::GetEditor(nsIEditor** aEditor) {
12217 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"
, 12217); return NS_ERROR_INVALID_POINTER; } } while (false)
;
12218 RefPtr<HTMLEditor> htmlEditor = GetHTMLEditorInternal();
12219 htmlEditor.forget(aEditor);
12220 return NS_OK;
12221}
12222
12223NS_IMETHODIMPnsresult
12224nsDocShell::SetEditor(nsIEditor* aEditor) {
12225 HTMLEditor* htmlEditor = aEditor ? aEditor->GetAsHTMLEditor() : nullptr;
12226 // If TextEditor comes, throw an error.
12227 if (aEditor && !htmlEditor) {
12228 return NS_ERROR_INVALID_ARG;
12229 }
12230 return SetHTMLEditorInternal(htmlEditor);
12231}
12232
12233HTMLEditor* nsDocShell::GetHTMLEditorInternal() {
12234 return mEditorData ? mEditorData->GetHTMLEditor() : nullptr;
12235}
12236
12237nsresult nsDocShell::SetHTMLEditorInternal(HTMLEditor* aHTMLEditor) {
12238 if (!aHTMLEditor && !mEditorData) {
12239 return NS_OK;
12240 }
12241
12242 nsresult rv = EnsureEditorData();
12243 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
12244 return rv;
12245 }
12246
12247 return mEditorData->SetHTMLEditor(aHTMLEditor);
12248}
12249
12250NS_IMETHODIMPnsresult
12251nsDocShell::GetEditable(bool* aEditable) {
12252 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"
, 12252); return NS_ERROR_INVALID_POINTER; } } while (false)
;
12253 *aEditable = mEditorData && mEditorData->GetEditable();
12254 return NS_OK;
12255}
12256
12257NS_IMETHODIMPnsresult
12258nsDocShell::GetHasEditingSession(bool* aHasEditingSession) {
12259 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"
, 12259); return NS_ERROR_INVALID_POINTER; } } while (false)
;
12260
12261 if (mEditorData) {
12262 *aHasEditingSession = !!mEditorData->GetEditingSession();
12263 } else {
12264 *aHasEditingSession = false;
12265 }
12266
12267 return NS_OK;
12268}
12269
12270NS_IMETHODIMPnsresult
12271nsDocShell::MakeEditable(bool aInWaitForUriLoad) {
12272 nsresult rv = EnsureEditorData();
12273 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
12274 return rv;
12275 }
12276
12277 return mEditorData->MakeEditable(aInWaitForUriLoad);
12278}
12279
12280/* static */ bool nsDocShell::ShouldAddURIVisit(nsIChannel* aChannel) {
12281 bool needToAddURIVisit = true;
12282 nsCOMPtr<nsIPropertyBag2> props(do_QueryInterface(aChannel));
12283 if (props) {
12284 mozilla::Unused << props->GetPropertyAsBool(
12285 u"docshell.needToAddURIVisit"_ns, &needToAddURIVisit);
12286 }
12287
12288 return needToAddURIVisit;
12289}
12290
12291/* static */ void nsDocShell::ExtractLastVisit(
12292 nsIChannel* aChannel, nsIURI** aURI, uint32_t* aChannelRedirectFlags) {
12293 nsCOMPtr<nsIPropertyBag2> props(do_QueryInterface(aChannel));
12294 if (!props) {
12295 return;
12296 }
12297
12298 nsresult rv;
12299 nsCOMPtr<nsIURI> uri(do_GetProperty(props, u"docshell.previousURI"_ns, &rv));
12300 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
12301 uri.forget(aURI);
12302
12303 rv = props->GetPropertyAsUint32(u"docshell.previousFlags"_ns,
12304 aChannelRedirectFlags);
12305
12306 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"
, 12308); } } while (false)
12307 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"
, 12308); } } while (false)
12308 "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"
, 12308); } } while (false)
;
12309
12310 } else {
12311 // There is no last visit for this channel, so this must be the first
12312 // link. Link the visit to the referrer of this request, if any.
12313 // Treat referrer as null if there is an error getting it.
12314 NS_GetReferrerFromChannel(aChannel, aURI);
12315 }
12316}
12317
12318void nsDocShell::SaveLastVisit(nsIChannel* aChannel, nsIURI* aURI,
12319 uint32_t aChannelRedirectFlags) {
12320 nsCOMPtr<nsIWritablePropertyBag2> props(do_QueryInterface(aChannel));
12321 if (!props || !aURI) {
12322 return;
12323 }
12324
12325 props->SetPropertyAsInterface(u"docshell.previousURI"_ns, aURI);
12326 props->SetPropertyAsUint32(u"docshell.previousFlags"_ns,
12327 aChannelRedirectFlags);
12328}
12329
12330/* static */ void nsDocShell::InternalAddURIVisit(
12331 nsIURI* aURI, nsIURI* aPreviousURI, uint32_t aChannelRedirectFlags,
12332 uint32_t aResponseStatus, BrowsingContext* aBrowsingContext,
12333 nsIWidget* aWidget, uint32_t aLoadType, bool aWasUpgraded) {
12334 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"
, 12334); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aURI" ") ("
"Visited URI is null!" ")"); do { *((volatile int*)__null) =
12334; __attribute__((nomerge)) ::abort(); } while (false); }
} while (false)
;
12335 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"
, 12336); 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) = 12336; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
12336 "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"
, 12336); 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) = 12336; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
12337
12338 bool usePrivateBrowsing = false;
12339 aBrowsingContext->GetUsePrivateBrowsing(&usePrivateBrowsing);
12340
12341 // Only content-type docshells save URI visits. Also don't do
12342 // anything here if we're not supposed to use global history.
12343 if (!aBrowsingContext->IsContent() ||
12344 !aBrowsingContext->GetUseGlobalHistory() || usePrivateBrowsing) {
12345 return;
12346 }
12347
12348 nsCOMPtr<IHistory> history = components::History::Service();
12349
12350 if (history) {
12351 uint32_t visitURIFlags = 0;
12352
12353 if (aBrowsingContext->IsTop()) {
12354 visitURIFlags |= IHistory::TOP_LEVEL;
12355 }
12356
12357 if (aChannelRedirectFlags & nsIChannelEventSink::REDIRECT_TEMPORARY) {
12358 visitURIFlags |= IHistory::REDIRECT_TEMPORARY;
12359 } else if (aChannelRedirectFlags &
12360 nsIChannelEventSink::REDIRECT_PERMANENT) {
12361 visitURIFlags |= IHistory::REDIRECT_PERMANENT;
12362 } else {
12363 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"
, 12365); 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) = 12365; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
12364 "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"
, 12365); 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) = 12365; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
12365 "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"
, 12365); 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) = 12365; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
;
12366 }
12367
12368 if (aResponseStatus >= 300 && aResponseStatus < 400) {
12369 visitURIFlags |= IHistory::REDIRECT_SOURCE;
12370 if (aResponseStatus == 301 || aResponseStatus == 308) {
12371 visitURIFlags |= IHistory::REDIRECT_SOURCE_PERMANENT;
12372 }
12373 }
12374 // Errors 400-501 and 505 are considered unrecoverable, in the sense a
12375 // simple retry attempt by the user is unlikely to solve them.
12376 // 408 is special cased, since may actually indicate a temporary
12377 // connection problem.
12378 else if (aResponseStatus != 408 &&
12379 ((aResponseStatus >= 400 && aResponseStatus <= 501) ||
12380 aResponseStatus == 505)) {
12381 visitURIFlags |= IHistory::UNRECOVERABLE_ERROR;
12382 }
12383
12384 if (aWasUpgraded) {
12385 visitURIFlags |=
12386 IHistory::REDIRECT_SOURCE | IHistory::REDIRECT_SOURCE_UPGRADED;
12387 }
12388
12389 mozilla::Unused << history->VisitURI(aWidget, aURI, aPreviousURI,
12390 visitURIFlags,
12391 aBrowsingContext->BrowserId());
12392 }
12393}
12394
12395void nsDocShell::AddURIVisit(nsIURI* aURI, nsIURI* aPreviousURI,
12396 uint32_t aChannelRedirectFlags,
12397 uint32_t aResponseStatus) {
12398 nsPIDOMWindowOuter* outer = GetWindow();
12399 nsCOMPtr<nsIWidget> widget = widget::WidgetUtils::DOMWindowToWidget(outer);
12400
12401 InternalAddURIVisit(aURI, aPreviousURI, aChannelRedirectFlags,
12402 aResponseStatus, mBrowsingContext, widget, mLoadType,
12403 false);
12404}
12405
12406//*****************************************************************************
12407// nsDocShell: Helper Routines
12408//*****************************************************************************
12409
12410NS_IMETHODIMPnsresult
12411nsDocShell::SetLoadType(uint32_t aLoadType) {
12412 mLoadType = aLoadType;
12413 return NS_OK;
12414}
12415
12416NS_IMETHODIMPnsresult
12417nsDocShell::GetLoadType(uint32_t* aLoadType) {
12418 *aLoadType = mLoadType;
12419 return NS_OK;
12420}
12421
12422nsresult nsDocShell::ConfirmRepost(bool* aRepost) {
12423 if (StaticPrefs::dom_confirm_repost_testing_always_accept()) {
12424 *aRepost = true;
12425 return NS_OK;
12426 }
12427
12428 nsCOMPtr<nsIPromptCollection> prompter =
12429 do_GetService("@mozilla.org/embedcomp/prompt-collection;1");
12430 if (!prompter) {
12431 return NS_ERROR_NOT_AVAILABLE;
12432 }
12433
12434 return prompter->ConfirmRepost(mBrowsingContext, aRepost);
12435}
12436
12437nsresult nsDocShell::GetPromptAndStringBundle(nsIPrompt** aPrompt,
12438 nsIStringBundle** aStringBundle) {
12439 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"
, 12440); return NS_ERROR_FAILURE; } } while (false)
12440 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"
, 12440); return NS_ERROR_FAILURE; } } while (false)
;
12441
12442 nsCOMPtr<nsIStringBundleService> stringBundleService =
12443 mozilla::components::StringBundle::Service();
12444 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"
, 12444); return NS_ERROR_FAILURE; } } while (false)
;
12445
12446 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"
, 12448); return NS_ERROR_FAILURE; } } while (false)
12447 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"
, 12448); return NS_ERROR_FAILURE; } } while (false)
12448 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"
, 12448); return NS_ERROR_FAILURE; } } while (false)
;
12449
12450 return NS_OK;
12451}
12452
12453nsIScrollableFrame* nsDocShell::GetRootScrollFrame() {
12454 PresShell* presShell = GetPresShell();
12455 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"
, 12455); return nullptr; } } while (false)
;
12456
12457 return presShell->GetRootScrollFrameAsScrollable();
12458}
12459
12460nsresult nsDocShell::EnsureScriptEnvironment() {
12461 if (mScriptGlobal) {
12462 return NS_OK;
12463 }
12464
12465 if (mIsBeingDestroyed) {
12466 return NS_ERROR_NOT_AVAILABLE;
12467 }
12468
12469#ifdef DEBUG1
12470 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"
, 12472); MOZ_PretendNoReturn(); } } while (0)
12471 "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"
, 12472); MOZ_PretendNoReturn(); } } while (0)
12472 "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"
, 12472); MOZ_PretendNoReturn(); } } while (0)
;
12473
12474 // Yeah, this isn't re-entrant safe, but that's ok since if we
12475 // re-enter this method, we'll infinitely loop...
12476 AutoRestore<bool> boolSetter(mInEnsureScriptEnv);
12477 mInEnsureScriptEnv = true;
12478#endif
12479
12480 nsCOMPtr<nsIWebBrowserChrome> browserChrome(do_GetInterface(mTreeOwner));
12481 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"
, 12481); return NS_ERROR_NOT_AVAILABLE; } } while (false)
;
12482
12483 uint32_t chromeFlags;
12484 browserChrome->GetChromeFlags(&chromeFlags);
12485
12486 // If our window is modal and we're not opened as chrome, make
12487 // this window a modal content window.
12488 mScriptGlobal = nsGlobalWindowOuter::Create(this, mItemType == typeChrome);
12489 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"
, 12489); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mScriptGlobal"
")"); do { *((volatile int*)__null) = 12489; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12490
12491 // Ensure the script object is set up to run script.
12492 return mScriptGlobal->EnsureScriptEnvironment();
12493}
12494
12495nsresult nsDocShell::EnsureEditorData() {
12496 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"
, 12496); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mIsBeingDestroyed"
")"); do { *((volatile int*)__null) = 12496; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12497
12498 bool openDocHasDetachedEditor = mOSHE && mOSHE->HasDetachedEditor();
12499 if (!mEditorData && !mIsBeingDestroyed && !openDocHasDetachedEditor) {
12500 // We shouldn't recreate the editor data if it already exists, or
12501 // we're shutting down, or we already have a detached editor data
12502 // stored in the session history. We should only have one editordata
12503 // per docshell.
12504 mEditorData = MakeUnique<nsDocShellEditorData>(this);
12505 }
12506
12507 return mEditorData ? NS_OK : NS_ERROR_NOT_AVAILABLE;
12508}
12509
12510nsresult nsDocShell::EnsureFind() {
12511 if (!mFind) {
12512 mFind = new nsWebBrowserFind();
12513 }
12514
12515 // we promise that the nsIWebBrowserFind that we return has been set
12516 // up to point to the focused, or content window, so we have to
12517 // set that up each time.
12518
12519 nsIScriptGlobalObject* scriptGO = GetScriptGlobalObject();
12520 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"
, 12520); return NS_ERROR_UNEXPECTED; } } while (false)
;
12521
12522 // default to our window
12523 nsCOMPtr<nsPIDOMWindowOuter> ourWindow = do_QueryInterface(scriptGO);
12524 nsCOMPtr<nsPIDOMWindowOuter> windowToSearch;
12525 nsFocusManager::GetFocusedDescendant(ourWindow,
12526 nsFocusManager::eIncludeAllDescendants,
12527 getter_AddRefs(windowToSearch));
12528
12529 nsCOMPtr<nsIWebBrowserFindInFrames> findInFrames = do_QueryInterface(mFind);
12530 if (!findInFrames) {
12531 return NS_ERROR_NO_INTERFACE;
12532 }
12533
12534 nsresult rv = findInFrames->SetRootSearchFrame(ourWindow);
12535 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
12536 return rv;
12537 }
12538 rv = findInFrames->SetCurrentSearchFrame(windowToSearch);
12539 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
12540 return rv;
12541 }
12542
12543 return NS_OK;
12544}
12545
12546NS_IMETHODIMPnsresult
12547nsDocShell::IsBeingDestroyed(bool* aDoomed) {
12548 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"
, 12548); return NS_ERROR_INVALID_ARG; } } while (false)
;
12549 *aDoomed = mIsBeingDestroyed;
12550 return NS_OK;
12551}
12552
12553NS_IMETHODIMPnsresult
12554nsDocShell::GetIsExecutingOnLoadHandler(bool* aResult) {
12555 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"
, 12555); return NS_ERROR_INVALID_ARG; } } while (false)
;
12556 *aResult = mIsExecutingOnLoadHandler;
12557 return NS_OK;
12558}
12559
12560NS_IMETHODIMPnsresult
12561nsDocShell::GetLayoutHistoryState(nsILayoutHistoryState** aLayoutHistoryState) {
12562 nsCOMPtr<nsILayoutHistoryState> state;
12563 if (mozilla::SessionHistoryInParent()) {
12564 if (mActiveEntry) {
12565 state = mActiveEntry->GetLayoutHistoryState();
12566 }
12567 } else {
12568 if (mOSHE) {
12569 state = mOSHE->GetLayoutHistoryState();
12570 }
12571 }
12572 state.forget(aLayoutHistoryState);
12573 return NS_OK;
12574}
12575
12576NS_IMETHODIMPnsresult
12577nsDocShell::SetLayoutHistoryState(nsILayoutHistoryState* aLayoutHistoryState) {
12578 if (mOSHE) {
12579 mOSHE->SetLayoutHistoryState(aLayoutHistoryState);
12580 }
12581 if (mActiveEntry) {
12582 mActiveEntry->SetLayoutHistoryState(aLayoutHistoryState);
12583 }
12584 return NS_OK;
12585}
12586
12587nsDocShell::InterfaceRequestorProxy::InterfaceRequestorProxy(
12588 nsIInterfaceRequestor* aRequestor) {
12589 if (aRequestor) {
12590 mWeakPtr = do_GetWeakReference(aRequestor);
12591 }
12592}
12593
12594nsDocShell::InterfaceRequestorProxy::~InterfaceRequestorProxy() {
12595 mWeakPtr = nullptr;
12596}
12597
12598NS_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"
, 12598); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { *((volatile int*)__null) =
12598; __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"
, 12598); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"nsDocShell::InterfaceRequestorProxy\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 12598; __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"
, 12598); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { *((volatile int*)__null) = 12598
; __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"
, 12598); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"nsDocShell::InterfaceRequestorProxy\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 12598; __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"
, 12598); 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; }
12599
12600NS_IMETHODIMPnsresult
12601nsDocShell::InterfaceRequestorProxy::GetInterface(const nsIID& aIID,
12602 void** aSink) {
12603 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"
, 12603); return NS_ERROR_INVALID_POINTER; } } while (false)
;
12604 nsCOMPtr<nsIInterfaceRequestor> ifReq = do_QueryReferent(mWeakPtr);
12605 if (ifReq) {
12606 return ifReq->GetInterface(aIID, aSink);
12607 }
12608 *aSink = nullptr;
12609 return NS_NOINTERFACE;
12610}
12611
12612//*****************************************************************************
12613// nsDocShell::nsIAuthPromptProvider
12614//*****************************************************************************
12615
12616NS_IMETHODIMPnsresult
12617nsDocShell::GetAuthPrompt(uint32_t aPromptReason, const nsIID& aIID,
12618 void** aResult) {
12619 // a priority prompt request will override a false mAllowAuth setting
12620 bool priorityPrompt = (aPromptReason == PROMPT_PROXY);
12621
12622 if (!mAllowAuth && !priorityPrompt) {
12623 return NS_ERROR_NOT_AVAILABLE;
12624 }
12625
12626 // we're either allowing auth, or it's a proxy request
12627 nsresult rv;
12628 nsCOMPtr<nsIPromptFactory> wwatch =
12629 do_GetService(NS_WINDOWWATCHER_CONTRACTID"@mozilla.org/embedcomp/window-watcher;1", &rv);
12630 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"
, 12630); return rv; } } while (false)
;
12631
12632 rv = EnsureScriptEnvironment();
12633 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"
, 12633); return rv; } } while (false)
;
12634
12635 // Get the an auth prompter for our window so that the parenting
12636 // of the dialogs works as it should when using tabs.
12637
12638 return wwatch->GetPrompt(mScriptGlobal, aIID,
12639 reinterpret_cast<void**>(aResult));
12640}
12641
12642//*****************************************************************************
12643// nsDocShell::nsILoadContext
12644//*****************************************************************************
12645
12646NS_IMETHODIMPnsresult
12647nsDocShell::GetAssociatedWindow(mozIDOMWindowProxy** aWindow) {
12648 CallGetInterface(this, aWindow);
12649 return NS_OK;
12650}
12651
12652NS_IMETHODIMPnsresult
12653nsDocShell::GetTopWindow(mozIDOMWindowProxy** aWindow) {
12654 return mBrowsingContext->GetTopWindow(aWindow);
12655}
12656
12657NS_IMETHODIMPnsresult
12658nsDocShell::GetTopFrameElement(Element** aElement) {
12659 return mBrowsingContext->GetTopFrameElement(aElement);
12660}
12661
12662NS_IMETHODIMPnsresult
12663nsDocShell::GetUseTrackingProtection(bool* aUseTrackingProtection) {
12664 return mBrowsingContext->GetUseTrackingProtection(aUseTrackingProtection);
12665}
12666
12667NS_IMETHODIMPnsresult
12668nsDocShell::SetUseTrackingProtection(bool aUseTrackingProtection) {
12669 return mBrowsingContext->SetUseTrackingProtection(aUseTrackingProtection);
12670}
12671
12672NS_IMETHODIMPnsresult
12673nsDocShell::GetIsContent(bool* aIsContent) {
12674 *aIsContent = (mItemType == typeContent);
12675 return NS_OK;
12676}
12677
12678bool nsDocShell::IsOKToLoadURI(nsIURI* aURI) {
12679 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"
, 12679); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aURI" ") ("
"Must have a URI!" ")"); do { *((volatile int*)__null) = 12679
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
;
12680
12681 if (!mFiredUnloadEvent) {
12682 return true;
12683 }
12684
12685 if (!mLoadingURI) {
12686 return false;
12687 }
12688
12689 bool isPrivateWin = false;
12690 Document* doc = GetDocument();
12691 if (doc) {
12692 isPrivateWin =
12693 doc->NodePrincipal()->OriginAttributesRef().mPrivateBrowsingId > 0;
12694 }
12695
12696 nsCOMPtr<nsIScriptSecurityManager> secMan =
12697 do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID"@mozilla.org/scriptsecuritymanager;1");
12698 return secMan && NS_SUCCEEDED(secMan->CheckSameOriginURI(((bool)(__builtin_expect(!!(!NS_FAILED_impl(secMan->CheckSameOriginURI
( aURI, mLoadingURI, false, isPrivateWin))), 1)))
12699 aURI, mLoadingURI, false, isPrivateWin))((bool)(__builtin_expect(!!(!NS_FAILED_impl(secMan->CheckSameOriginURI
( aURI, mLoadingURI, false, isPrivateWin))), 1)))
;
12700}
12701
12702//
12703// Routines for selection and clipboard
12704//
12705nsresult nsDocShell::GetControllerForCommand(const char* aCommand,
12706 nsIController** aResult) {
12707 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"
, 12707); return NS_ERROR_INVALID_POINTER; } } while (false)
;
12708 *aResult = nullptr;
12709
12710 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"
, 12710); return NS_ERROR_FAILURE; } } while (false)
;
12711
12712 nsCOMPtr<nsPIWindowRoot> root = mScriptGlobal->GetTopWindowRoot();
12713 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"
, 12713); return NS_ERROR_FAILURE; } } while (false)
;
12714
12715 return root->GetControllerForCommand(aCommand, false /* for any window */,
12716 aResult);
12717}
12718
12719NS_IMETHODIMPnsresult
12720nsDocShell::IsCommandEnabled(const char* aCommand, bool* aResult) {
12721 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"
, 12721); return NS_ERROR_INVALID_POINTER; } } while (false)
;
12722 *aResult = false;
12723
12724 nsresult rv = NS_ERROR_FAILURE;
12725
12726 nsCOMPtr<nsIController> controller;
12727 rv = GetControllerForCommand(aCommand, getter_AddRefs(controller));
12728 if (controller) {
12729 rv = controller->IsCommandEnabled(aCommand, aResult);
12730 }
12731
12732 return rv;
12733}
12734
12735NS_IMETHODIMPnsresult
12736nsDocShell::DoCommand(const char* aCommand) {
12737 nsresult rv = NS_ERROR_FAILURE;
12738
12739 nsCOMPtr<nsIController> controller;
12740 rv = GetControllerForCommand(aCommand, getter_AddRefs(controller));
12741 if (controller) {
12742 rv = controller->DoCommand(aCommand);
12743 }
12744
12745 return rv;
12746}
12747
12748NS_IMETHODIMPnsresult
12749nsDocShell::DoCommandWithParams(const char* aCommand,
12750 nsICommandParams* aParams) {
12751 nsCOMPtr<nsIController> controller;
12752 nsresult rv = GetControllerForCommand(aCommand, getter_AddRefs(controller));
12753 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"
, 12753)
) {
12754 return rv;
12755 }
12756
12757 nsCOMPtr<nsICommandController> commandController =
12758 do_QueryInterface(controller, &rv);
12759 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"
, 12759)
) {
12760 return rv;
12761 }
12762
12763 return commandController->DoCommandWithParams(aCommand, aParams);
12764}
12765
12766nsresult nsDocShell::EnsureCommandHandler() {
12767 if (!mCommandManager) {
12768 if (nsCOMPtr<nsPIDOMWindowOuter> domWindow = GetWindow()) {
12769 mCommandManager = new nsCommandManager(domWindow);
12770 }
12771 }
12772 return mCommandManager ? NS_OK : NS_ERROR_FAILURE;
12773}
12774
12775// link handling
12776
12777class OnLinkClickEvent : public Runnable {
12778 public:
12779 OnLinkClickEvent(nsDocShell* aHandler, nsIContent* aContent,
12780 nsDocShellLoadState* aLoadState, bool aNoOpenerImplied,
12781 bool aIsTrusted, nsIPrincipal* aTriggeringPrincipal);
12782
12783 NS_IMETHODvirtual nsresult Run() override {
12784 AutoPopupStatePusherAutoPopupStatePusherInternal popupStatePusher(mPopupState);
12785
12786 // We need to set up an AutoJSAPI here for the following reason: When we
12787 // do OnLinkClickSync we'll eventually end up in
12788 // nsGlobalWindow::OpenInternal which only does popup blocking if
12789 // !LegacyIsCallerChromeOrNativeCode(). So we need to fake things so that
12790 // we don't look like native code as far as LegacyIsCallerNativeCode() is
12791 // concerned.
12792 AutoJSAPI jsapi;
12793 if (mIsTrusted || jsapi.Init(mContent->OwnerDoc()->GetScopeObject())) {
12794 mHandler->OnLinkClickSync(mContent, mLoadState, mNoOpenerImplied,
12795 mTriggeringPrincipal);
12796 }
12797 return NS_OK;
12798 }
12799
12800 private:
12801 RefPtr<nsDocShell> mHandler;
12802 nsCOMPtr<nsIContent> mContent;
12803 RefPtr<nsDocShellLoadState> mLoadState;
12804 nsCOMPtr<nsIPrincipal> mTriggeringPrincipal;
12805 PopupBlocker::PopupControlState mPopupState;
12806 bool mNoOpenerImplied;
12807 bool mIsTrusted;
12808};
12809
12810OnLinkClickEvent::OnLinkClickEvent(nsDocShell* aHandler, nsIContent* aContent,
12811 nsDocShellLoadState* aLoadState,
12812 bool aNoOpenerImplied, bool aIsTrusted,
12813 nsIPrincipal* aTriggeringPrincipal)
12814 : mozilla::Runnable("OnLinkClickEvent"),
12815 mHandler(aHandler),
12816 mContent(aContent),
12817 mLoadState(aLoadState),
12818 mTriggeringPrincipal(aTriggeringPrincipal),
12819 mPopupState(PopupBlocker::GetPopupControlState()),
12820 mNoOpenerImplied(aNoOpenerImplied),
12821 mIsTrusted(aIsTrusted) {}
12822
12823nsresult nsDocShell::OnLinkClick(
12824 nsIContent* aContent, nsIURI* aURI, const nsAString& aTargetSpec,
12825 const nsAString& aFileName, nsIInputStream* aPostDataStream,
12826 nsIInputStream* aHeadersDataStream, bool aIsUserTriggered, bool aIsTrusted,
12827 nsIPrincipal* aTriggeringPrincipal, nsIContentSecurityPolicy* aCsp) {
12828#ifndef ANDROID
12829 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"
, 12829); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aTriggeringPrincipal"
") (" "Need a valid triggeringPrincipal" ")"); do { *((volatile
int*)__null) = 12829; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
12830#endif
12831 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"
, 12831); MOZ_PretendNoReturn(); } } while (0)
;
12832
12833 if (!IsNavigationAllowed() || !IsOKToLoadURI(aURI)) {
12834 return NS_OK;
12835 }
12836
12837 // On history navigation through Back/Forward buttons, don't execute
12838 // automatic JavaScript redirection such as |anchorElement.click()| or
12839 // |formElement.submit()|.
12840 //
12841 // XXX |formElement.submit()| bypasses this checkpoint because it calls
12842 // nsDocShell::OnLinkClickSync(...) instead.
12843 if (ShouldBlockLoadingForBackButton()) {
12844 return NS_OK;
12845 }
12846
12847 if (aContent->IsEditable()) {
12848 return NS_OK;
12849 }
12850
12851 Document* ownerDoc = aContent->OwnerDoc();
12852 if (nsContentUtils::IsExternalProtocol(aURI)) {
12853 ownerDoc->EnsureNotEnteringAndExitFullscreen();
12854 }
12855
12856 bool noOpenerImplied = false;
12857 nsAutoString target(aTargetSpec);
12858 if (aFileName.IsVoid() &&
12859 ShouldOpenInBlankTarget(aTargetSpec, aURI, aContent, aIsUserTriggered)) {
12860 target = u"_blank";
12861 if (!aTargetSpec.Equals(target)) {
12862 noOpenerImplied = true;
12863 }
12864 }
12865
12866 RefPtr<nsDocShellLoadState> loadState = new nsDocShellLoadState(aURI);
12867 loadState->SetTarget(target);
12868 loadState->SetFileName(aFileName);
12869 loadState->SetPostDataStream(aPostDataStream);
12870 loadState->SetHeadersStream(aHeadersDataStream);
12871 loadState->SetFirstParty(true);
12872 loadState->SetTriggeringPrincipal(
12873 aTriggeringPrincipal ? aTriggeringPrincipal : aContent->NodePrincipal());
12874 loadState->SetPrincipalToInherit(aContent->NodePrincipal());
12875 loadState->SetCsp(aCsp ? aCsp : aContent->GetCsp());
12876 loadState->SetAllowFocusMove(UserActivation::IsHandlingUserInput());
12877
12878 nsCOMPtr<nsIRunnable> ev =
12879 new OnLinkClickEvent(this, aContent, loadState, noOpenerImplied,
12880 aIsTrusted, aTriggeringPrincipal);
12881 return Dispatch(ev.forget());
12882}
12883
12884bool nsDocShell::ShouldOpenInBlankTarget(const nsAString& aOriginalTarget,
12885 nsIURI* aLinkURI, nsIContent* aContent,
12886 bool aIsUserTriggered) {
12887 if (net::SchemeIsJavascript(aLinkURI)) {
12888 return false;
12889 }
12890
12891 // External links from within app tabs should always open in new tabs
12892 // instead of replacing the app tab's page (Bug 575561)
12893 // nsIURI.host can throw for non-nsStandardURL nsIURIs. If we fail to
12894 // get either host, just return false to use the original target.
12895 nsAutoCString linkHost;
12896 if (NS_FAILED(aLinkURI->GetHost(linkHost))((bool)(__builtin_expect(!!(NS_FAILED_impl(aLinkURI->GetHost
(linkHost))), 0)))
) {
12897 return false;
12898 }
12899
12900 // The targetTopLevelLinkClicksToBlank property on BrowsingContext allows
12901 // privileged code to change the default targeting behaviour. In particular,
12902 // if a user-initiated link click for the (or targetting the) top-level frame
12903 // is detected, we default the target to "_blank" to give it a new
12904 // top-level BrowsingContext.
12905 if (mBrowsingContext->TargetTopLevelLinkClicksToBlank() && aIsUserTriggered &&
12906 ((aOriginalTarget.IsEmpty() && mBrowsingContext->IsTop()) ||
12907 aOriginalTarget == u"_top"_ns)) {
12908 return true;
12909 }
12910
12911 // Don't modify non-default targets.
12912 if (!aOriginalTarget.IsEmpty()) {
12913 return false;
12914 }
12915
12916 // Only check targets that are in extension panels or app tabs.
12917 // (isAppTab will be false for app tab subframes).
12918 nsString mmGroup = mBrowsingContext->Top()->GetMessageManagerGroup();
12919 if (!mmGroup.EqualsLiteral("webext-browsers") &&
12920 !mBrowsingContext->IsAppTab()) {
12921 return false;
12922 }
12923
12924 nsCOMPtr<nsIURI> docURI = aContent->OwnerDoc()->GetDocumentURIObject();
12925 if (!docURI) {
12926 return false;
12927 }
12928
12929 nsAutoCString docHost;
12930 if (NS_FAILED(docURI->GetHost(docHost))((bool)(__builtin_expect(!!(NS_FAILED_impl(docURI->GetHost
(docHost))), 0)))
) {
12931 return false;
12932 }
12933
12934 if (linkHost.Equals(docHost)) {
12935 return false;
12936 }
12937
12938 // Special case: ignore "www" prefix if it is part of host string
12939 return linkHost.Length() < docHost.Length()
12940 ? !docHost.Equals("www."_ns + linkHost)
12941 : !linkHost.Equals("www."_ns + docHost);
12942}
12943
12944static bool ElementCanHaveNoopener(nsIContent* aContent) {
12945 // Make sure we are dealing with either an <A>, <AREA>, or <FORM> element in
12946 // the HTML, XHTML, or SVG namespace.
12947 return aContent->IsAnyOfHTMLElements(nsGkAtoms::a, nsGkAtoms::area,
12948 nsGkAtoms::form) ||
12949 aContent->IsSVGElement(nsGkAtoms::a);
12950}
12951
12952nsresult nsDocShell::OnLinkClickSync(nsIContent* aContent,
12953 nsDocShellLoadState* aLoadState,
12954 bool aNoOpenerImplied,
12955 nsIPrincipal* aTriggeringPrincipal) {
12956 if (!IsNavigationAllowed() || !IsOKToLoadURI(aLoadState->URI())) {
12957 return NS_OK;
12958 }
12959
12960 // XXX When the linking node was HTMLFormElement, it is synchronous event.
12961 // That is, the caller of this method is not |OnLinkClickEvent::Run()|
12962 // but |HTMLFormElement::SubmitSubmission(...)|.
12963 if (aContent->IsHTMLElement(nsGkAtoms::form) &&
12964 ShouldBlockLoadingForBackButton()) {
12965 return NS_OK;
12966 }
12967
12968 if (aContent->IsEditable()) {
12969 return NS_OK;
12970 }
12971
12972 // if the triggeringPrincipal is not passed explicitly, then we
12973 // fall back to using doc->NodePrincipal() as the triggeringPrincipal.
12974 nsCOMPtr<nsIPrincipal> triggeringPrincipal =
12975 aTriggeringPrincipal ? aTriggeringPrincipal : aContent->NodePrincipal();
12976
12977 {
12978 // defer to an external protocol handler if necessary...
12979 nsCOMPtr<nsIExternalProtocolService> extProtService =
12980 do_GetService(NS_EXTERNALPROTOCOLSERVICE_CONTRACTID"@mozilla.org/uriloader/external-protocol-service;1");
12981 if (extProtService) {
12982 nsAutoCString scheme;
12983 aLoadState->URI()->GetScheme(scheme);
12984 if (!scheme.IsEmpty()) {
12985 // if the URL scheme does not correspond to an exposed protocol, then
12986 // we need to hand this link click over to the external protocol
12987 // handler.
12988 bool isExposed;
12989 nsresult rv =
12990 extProtService->IsExposedProtocol(scheme.get(), &isExposed);
12991 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && !isExposed) {
12992 return extProtService->LoadURI(
12993 aLoadState->URI(), triggeringPrincipal, nullptr, mBrowsingContext,
12994 /* aTriggeredExternally */
12995 false,
12996 /* aHasValidUserGestureActivation */
12997 aContent->OwnerDoc()->HasValidTransientUserGestureActivation());
12998 }
12999 }
13000 }
13001 }
13002 uint32_t triggeringSandboxFlags = 0;
13003 uint64_t triggeringWindowId = 0;
13004 bool triggeringStorageAccess = false;
13005 if (mBrowsingContext) {
13006 triggeringSandboxFlags = aContent->OwnerDoc()->GetSandboxFlags();
13007 triggeringWindowId = aContent->OwnerDoc()->InnerWindowID();
13008 triggeringStorageAccess = aContent->OwnerDoc()->UsingStorageAccess();
13009 }
13010
13011 uint32_t flags = INTERNAL_LOAD_FLAGS_NONE;
13012 bool elementCanHaveNoopener = ElementCanHaveNoopener(aContent);
13013 bool triggeringPrincipalIsSystemPrincipal =
13014 aLoadState->TriggeringPrincipal()->IsSystemPrincipal();
13015 if (elementCanHaveNoopener) {
13016 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"
, 13016); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aContent->IsHTMLElement() || aContent->IsSVGElement()"
")"); do { *((volatile int*)__null) = 13016; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
13017 nsAutoString relString;
13018 aContent->AsElement()->GetAttr(nsGkAtoms::rel, relString);
13019 nsWhitespaceTokenizerTemplate<nsContentUtils::IsHTMLWhitespace> tok(
13020 relString);
13021
13022 bool targetBlank = aLoadState->Target().LowerCaseEqualsLiteral("_blank");
13023 bool explicitOpenerSet = false;
13024
13025 // The opener behaviour follows a hierarchy, such that if a higher
13026 // priority behaviour is specified, it always takes priority. That
13027 // priority is currently: norefrerer > noopener > opener > default
13028
13029 while (tok.hasMoreTokens()) {
13030 const nsAString& token = tok.nextToken();
13031 if (token.LowerCaseEqualsLiteral("noreferrer")) {
13032 flags |= INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER |
13033 INTERNAL_LOAD_FLAGS_NO_OPENER;
13034 // noreferrer cannot be overwritten by a 'rel=opener'.
13035 explicitOpenerSet = true;
13036 break;
13037 }
13038
13039 if (token.LowerCaseEqualsLiteral("noopener")) {
13040 flags |= INTERNAL_LOAD_FLAGS_NO_OPENER;
13041 explicitOpenerSet = true;
13042 }
13043
13044 if (targetBlank && StaticPrefs::dom_targetBlankNoOpener_enabled() &&
13045 token.LowerCaseEqualsLiteral("opener") && !explicitOpenerSet) {
13046 explicitOpenerSet = true;
13047 }
13048 }
13049
13050 if (targetBlank && StaticPrefs::dom_targetBlankNoOpener_enabled() &&
13051 !explicitOpenerSet && !triggeringPrincipalIsSystemPrincipal) {
13052 flags |= INTERNAL_LOAD_FLAGS_NO_OPENER;
13053 }
13054
13055 if (aNoOpenerImplied) {
13056 flags |= INTERNAL_LOAD_FLAGS_NO_OPENER;
13057 }
13058 }
13059
13060 // Get the owner document of the link that was clicked, this will be
13061 // the document that the link is in, or the last document that the
13062 // link was in. From that document, we'll get the URI to use as the
13063 // referrer, since the current URI in this docshell may be a
13064 // new document that we're in the process of loading.
13065 RefPtr<Document> referrerDoc = aContent->OwnerDoc();
13066
13067 // Now check that the referrerDoc's inner window is the current inner
13068 // window for mScriptGlobal. If it's not, then we don't want to
13069 // follow this link.
13070 nsPIDOMWindowInner* referrerInner = referrerDoc->GetInnerWindow();
13071 if (!mScriptGlobal || !referrerInner ||
13072 mScriptGlobal->GetCurrentInnerWindow() != referrerInner) {
13073 // We're no longer the current inner window
13074 return NS_OK;
13075 }
13076
13077 // referrer could be null here in some odd cases, but that's ok,
13078 // we'll just load the link w/o sending a referrer in those cases.
13079
13080 // If this is an anchor element, grab its type property to use as a hint
13081 nsAutoString typeHint;
13082 RefPtr<HTMLAnchorElement> anchor = HTMLAnchorElement::FromNode(aContent);
13083 if (anchor) {
13084 anchor->GetType(typeHint);
13085 NS_ConvertUTF16toUTF8 utf8Hint(typeHint);
13086 nsAutoCString type, dummy;
13087 NS_ParseRequestContentType(utf8Hint, type, dummy);
13088 CopyUTF8toUTF16(type, typeHint);
13089 }
13090
13091 uint32_t loadType = LOAD_LINK;
13092 if (aLoadState->IsFormSubmission()) {
13093 if (aLoadState->Target().IsEmpty()) {
13094 // We set the right load type here for form submissions with an empty
13095 // target. Form submission with a non-empty target are handled in
13096 // nsDocShell::PerformRetargeting after we've selected the correct target
13097 // BC.
13098 loadType = GetLoadTypeForFormSubmission(GetBrowsingContext(), aLoadState);
13099 }
13100 } else {
13101 // Link click can be triggered inside an onload handler, and we don't want
13102 // to add history entry in this case.
13103 bool inOnLoadHandler = false;
13104 GetIsExecutingOnLoadHandler(&inOnLoadHandler);
13105 if (inOnLoadHandler) {
13106 loadType = LOAD_NORMAL_REPLACE;
13107 }
13108 }
13109
13110 nsCOMPtr<nsIReferrerInfo> referrerInfo =
13111 elementCanHaveNoopener ? new ReferrerInfo(*aContent->AsElement())
13112 : new ReferrerInfo(*referrerDoc);
13113 RefPtr<WindowContext> context = mBrowsingContext->GetCurrentWindowContext();
13114
13115 aLoadState->SetTriggeringSandboxFlags(triggeringSandboxFlags);
13116 aLoadState->SetTriggeringWindowId(triggeringWindowId);
13117 aLoadState->SetTriggeringStorageAccess(triggeringStorageAccess);
13118 aLoadState->SetReferrerInfo(referrerInfo);
13119 aLoadState->SetInternalLoadFlags(flags);
13120 aLoadState->SetTypeHint(NS_ConvertUTF16toUTF8(typeHint));
13121 aLoadState->SetLoadType(loadType);
13122 aLoadState->SetSourceBrowsingContext(mBrowsingContext);
13123 aLoadState->SetHasValidUserGestureActivation(
13124 context && context->HasValidTransientUserGestureActivation());
13125
13126 nsresult rv = InternalLoad(aLoadState);
13127
13128 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
13129 nsPingListener::DispatchPings(this, aContent, aLoadState->URI(),
13130 referrerInfo);
13131 }
13132
13133 return rv;
13134}
13135
13136nsresult nsDocShell::OnOverLink(nsIContent* aContent, nsIURI* aURI,
13137 const nsAString& aTargetSpec) {
13138 if (aContent->IsEditable()) {
13139 return NS_OK;
13140 }
13141
13142 nsresult rv = NS_ERROR_FAILURE;
13143
13144 nsCOMPtr<nsIWebBrowserChrome> browserChrome = do_GetInterface(mTreeOwner);
13145 if (!browserChrome) {
13146 return rv;
13147 }
13148
13149 nsCOMPtr<nsIURI> exposableURI = nsIOService::CreateExposableURI(aURI);
13150 nsAutoCString spec;
13151 rv = exposableURI->GetDisplaySpec(spec);
13152 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"
, 13152); return rv; } } while (false)
;
13153
13154 NS_ConvertUTF8toUTF16 uStr(spec);
13155
13156 PredictorPredict(aURI, mCurrentURI, nsINetworkPredictor::PREDICT_LINK,
13157 aContent->NodePrincipal()->OriginAttributesRef(), nullptr);
13158
13159 rv = browserChrome->SetLinkStatus(uStr);
13160 return rv;
13161}
13162
13163nsresult nsDocShell::OnLeaveLink() {
13164 nsCOMPtr<nsIWebBrowserChrome> browserChrome(do_GetInterface(mTreeOwner));
13165 nsresult rv = NS_ERROR_FAILURE;
13166
13167 if (browserChrome) {
13168 rv = browserChrome->SetLinkStatus(u""_ns);
13169 }
13170 return rv;
13171}
13172
13173bool nsDocShell::ShouldBlockLoadingForBackButton() {
13174 if (!(mLoadType & LOAD_CMD_HISTORY) ||
13175 UserActivation::IsHandlingUserInput() ||
13176 !Preferences::GetBool("accessibility.blockjsredirection")) {
13177 return false;
13178 }
13179
13180 bool canGoForward = false;
13181 GetCanGoForward(&canGoForward);
13182 return canGoForward;
13183}
13184
13185bool nsDocShell::PluginsAllowedInCurrentDoc() {
13186 if (!mDocumentViewer) {
13187 return false;
13188 }
13189
13190 Document* doc = mDocumentViewer->GetDocument();
13191 if (!doc) {
13192 return false;
13193 }
13194
13195 return doc->GetAllowPlugins();
13196}
13197
13198//----------------------------------------------------------------------
13199// Web Shell Services API
13200
13201// This functions is only called when a new charset is detected in loading a
13202// document.
13203nsresult nsDocShell::CharsetChangeReloadDocument(
13204 mozilla::NotNull<const mozilla::Encoding*> aEncoding, int32_t aSource) {
13205 // XXX hack. keep the aCharset and aSource wait to pick it up
13206 nsCOMPtr<nsIDocumentViewer> viewer;
13207 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"
, 13207); return NS_ERROR_FAILURE; } } while (false)
;
13208 if (viewer) {
13209 int32_t source;
13210 Unused << viewer->GetReloadEncodingAndSource(&source);
13211 if (aSource > source) {
13212 viewer->SetReloadEncodingAndSource(aEncoding, aSource);
13213 if (eCharsetReloadRequested != mCharsetReloadState) {
13214 mCharsetReloadState = eCharsetReloadRequested;
13215 switch (mLoadType) {
13216 case LOAD_RELOAD_BYPASS_PROXY_AND_CACHE:
13217 return Reload(LOAD_FLAGS_CHARSET_CHANGE | LOAD_FLAGS_BYPASS_CACHE |
13218 LOAD_FLAGS_BYPASS_PROXY);
13219 case LOAD_RELOAD_BYPASS_CACHE:
13220 return Reload(LOAD_FLAGS_CHARSET_CHANGE | LOAD_FLAGS_BYPASS_CACHE);
13221 default:
13222 return Reload(LOAD_FLAGS_CHARSET_CHANGE);
13223 }
13224 }
13225 }
13226 }
13227 // return failure if this request is not accepted due to mCharsetReloadState
13228 return NS_ERROR_DOCSHELL_REQUEST_REJECTED;
13229}
13230
13231nsresult nsDocShell::CharsetChangeStopDocumentLoad() {
13232 if (eCharsetReloadRequested != mCharsetReloadState) {
13233 Stop(nsIWebNavigation::STOP_ALL);
13234 return NS_OK;
13235 }
13236 // return failer if this request is not accepted due to mCharsetReloadState
13237 return NS_ERROR_DOCSHELL_REQUEST_REJECTED;
13238}
13239
13240NS_IMETHODIMPnsresult nsDocShell::ExitPrintPreview() {
13241#if NS_PRINT_PREVIEW1
13242 nsCOMPtr<nsIWebBrowserPrint> viewer = do_QueryInterface(mDocumentViewer);
13243 return viewer->ExitPrintPreview();
13244#else
13245 return NS_OK;
13246#endif
13247}
13248
13249/* [infallible] */
13250NS_IMETHODIMPnsresult nsDocShell::GetIsTopLevelContentDocShell(
13251 bool* aIsTopLevelContentDocShell) {
13252 *aIsTopLevelContentDocShell = false;
13253
13254 if (mItemType == typeContent) {
13255 *aIsTopLevelContentDocShell = mBrowsingContext->IsTopContent();
13256 }
13257
13258 return NS_OK;
13259}
13260
13261// Implements nsILoadContext.originAttributes
13262NS_IMETHODIMPnsresult
13263nsDocShell::GetScriptableOriginAttributes(JSContext* aCx,
13264 JS::MutableHandle<JS::Value> aVal) {
13265 return mBrowsingContext->GetScriptableOriginAttributes(aCx, aVal);
13266}
13267
13268// Implements nsIDocShell.GetOriginAttributes()
13269NS_IMETHODIMPnsresult
13270nsDocShell::GetOriginAttributes(JSContext* aCx,
13271 JS::MutableHandle<JS::Value> aVal) {
13272 return mBrowsingContext->GetScriptableOriginAttributes(aCx, aVal);
13273}
13274
13275bool nsDocShell::ServiceWorkerAllowedToControlWindow(nsIPrincipal* aPrincipal,
13276 nsIURI* aURI) {
13277 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"
, 13277); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPrincipal"
")"); do { *((volatile int*)__null) = 13277; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
13278 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"
, 13278); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aURI" ")")
; do { *((volatile int*)__null) = 13278; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
13279
13280 if (UsePrivateBrowsing() || mBrowsingContext->GetSandboxFlags()) {
13281 return false;
13282 }
13283
13284 nsCOMPtr<nsIDocShellTreeItem> parent;
13285 GetInProcessSameTypeParent(getter_AddRefs(parent));
13286 nsPIDOMWindowOuter* parentOuter = parent ? parent->GetWindow() : nullptr;
13287 nsPIDOMWindowInner* parentInner =
13288 parentOuter ? parentOuter->GetCurrentInnerWindow() : nullptr;
13289
13290 StorageAccess storage =
13291 StorageAllowedForNewWindow(aPrincipal, aURI, parentInner);
13292
13293 // If the partitioned service worker is enabled, service worker is allowed to
13294 // control the window if partition is enabled.
13295 if (StaticPrefs::privacy_partition_serviceWorkers() && parentInner) {
13296 RefPtr<Document> doc = parentInner->GetExtantDoc();
13297
13298 if (doc && StoragePartitioningEnabled(storage, doc->CookieJarSettings())) {
13299 return true;
13300 }
13301 }
13302
13303 return storage == StorageAccess::eAllow;
13304}
13305
13306nsresult nsDocShell::SetOriginAttributes(const OriginAttributes& aAttrs) {
13307 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"
, 13307); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mIsBeingDestroyed"
")"); do { *((volatile int*)__null) = 13307; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
13308 return mBrowsingContext->SetOriginAttributes(aAttrs);
13309}
13310
13311NS_IMETHODIMPnsresult
13312nsDocShell::ResumeRedirectedLoad(uint64_t aIdentifier, int32_t aHistoryIndex) {
13313 RefPtr<nsDocShell> self = this;
13314 RefPtr<ChildProcessChannelListener> cpcl =
13315 ChildProcessChannelListener::GetSingleton();
13316
13317 // Call into InternalLoad with the pending channel when it is received.
13318 cpcl->RegisterCallback(
13319 aIdentifier, [self, aHistoryIndex](
13320 nsDocShellLoadState* aLoadState,
13321 nsTArray<Endpoint<extensions::PStreamFilterParent>>&&
13322 aStreamFilterEndpoints,
13323 nsDOMNavigationTiming* aTiming) {
13324 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"
, 13324); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->GetPendingRedirectedChannel()"
")"); do { *((volatile int*)__null) = 13324; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
13325 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"
, 13325)
) {
13326 aLoadState->GetPendingRedirectedChannel()->CancelWithReason(
13327 NS_BINDING_ABORTED, "nsDocShell::mIsBeingDestroyed"_ns);
13328 return NS_BINDING_ABORTED;
13329 }
13330
13331 self->mLoadType = aLoadState->LoadType();
13332 nsCOMPtr<nsIURI> previousURI;
13333 uint32_t previousFlags = 0;
13334 ExtractLastVisit(aLoadState->GetPendingRedirectedChannel(),
13335 getter_AddRefs(previousURI), &previousFlags);
13336 self->SaveLastVisit(aLoadState->GetPendingRedirectedChannel(),
13337 previousURI, previousFlags);
13338
13339 if (aTiming) {
13340 self->mTiming = new nsDOMNavigationTiming(self, aTiming);
13341 self->mBlankTiming = false;
13342 }
13343
13344 // If we're performing a history load, locate the correct history entry,
13345 // and set the relevant bits on our loadState.
13346 if (aHistoryIndex >= 0 && self->GetSessionHistory() &&
13347 !mozilla::SessionHistoryInParent()) {
13348 nsCOMPtr<nsISHistory> legacySHistory =
13349 self->GetSessionHistory()->LegacySHistory();
13350
13351 nsCOMPtr<nsISHEntry> entry;
13352 nsresult rv = legacySHistory->GetEntryAtIndex(aHistoryIndex,
13353 getter_AddRefs(entry));
13354 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
13355 legacySHistory->InternalSetRequestedIndex(aHistoryIndex);
13356 aLoadState->SetLoadType(LOAD_HISTORY);
13357 aLoadState->SetSHEntry(entry);
13358 }
13359 }
13360
13361 self->InternalLoad(aLoadState);
13362
13363 if (aLoadState->GetOriginalURIString().isSome()) {
13364 // Save URI string in case it's needed later when
13365 // sending to search engine service in EndPageLoad()
13366 self->mOriginalUriString = *aLoadState->GetOriginalURIString();
13367 }
13368
13369 for (auto& endpoint : aStreamFilterEndpoints) {
13370 extensions::StreamFilterParent::Attach(
13371 aLoadState->GetPendingRedirectedChannel(), std::move(endpoint));
13372 }
13373
13374 // If the channel isn't pending, then it means that InternalLoad
13375 // never connected it, and we shouldn't try to continue. This
13376 // can happen even if InternalLoad returned NS_OK.
13377 bool pending = false;
13378 aLoadState->GetPendingRedirectedChannel()->IsPending(&pending);
13379 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"
, 13379); MOZ_PretendNoReturn(); } } while (0)
;
13380 if (!pending) {
13381 return NS_BINDING_ABORTED;
13382 }
13383 return NS_OK;
13384 });
13385 return NS_OK;
13386}
13387
13388NS_IMETHODIMPnsresult
13389nsDocShell::SetOriginAttributes(JS::Handle<JS::Value> aOriginAttributes,
13390 JSContext* aCx) {
13391 OriginAttributes attrs;
13392 if (!aOriginAttributes.isObject() || !attrs.Init(aCx, aOriginAttributes)) {
13393 return NS_ERROR_INVALID_ARG;
13394 }
13395
13396 return SetOriginAttributes(attrs);
13397}
13398
13399NS_IMETHODIMPnsresult
13400nsDocShell::GetAsyncPanZoomEnabled(bool* aOut) {
13401 if (PresShell* presShell = GetPresShell()) {
13402 *aOut = presShell->AsyncPanZoomEnabled();
13403 return NS_OK;
13404 }
13405
13406 // If we don't have a presShell, fall back to the default platform value of
13407 // whether or not APZ is enabled.
13408 *aOut = gfxPlatform::AsyncPanZoomEnabled();
13409 return NS_OK;
13410}
13411
13412bool nsDocShell::HasUnloadedParent() {
13413 for (WindowContext* wc = GetBrowsingContext()->GetParentWindowContext(); wc;
13414 wc = wc->GetParentWindowContext()) {
13415 if (!wc->IsCurrent() || wc->IsDiscarded() ||
13416 wc->GetBrowsingContext()->IsDiscarded()) {
13417 // If a parent is OOP and the parent WindowContext is no
13418 // longer current, we can assume the parent was unloaded.
13419 return true;
13420 }
13421
13422 if (wc->GetBrowsingContext()->IsInProcess() &&
13423 (!wc->GetBrowsingContext()->GetDocShell() ||
13424 wc->GetBrowsingContext()->GetDocShell()->GetIsInUnload())) {
13425 return true;
13426 }
13427 }
13428 return false;
13429}
13430
13431/* static */
13432bool nsDocShell::ShouldUpdateGlobalHistory(uint32_t aLoadType) {
13433 return !(aLoadType == LOAD_BYPASS_HISTORY || aLoadType == LOAD_ERROR_PAGE ||
13434 aLoadType & LOAD_CMD_HISTORY);
13435}
13436
13437void nsDocShell::UpdateGlobalHistoryTitle(nsIURI* aURI) {
13438 if (!mBrowsingContext->GetUseGlobalHistory() || UsePrivateBrowsing()) {
13439 return;
13440 }
13441
13442 // Global history is interested into sub-frame visits only for link-coloring
13443 // purposes, thus title updates are skipped for those.
13444 //
13445 // Moreover, some iframe documents (such as the ones created via
13446 // document.open()) inherit the document uri of the caller, which would cause
13447 // us to override a previously set page title with one from the subframe.
13448 if (IsSubframe()) {
13449 return;
13450 }
13451
13452 if (nsCOMPtr<IHistory> history = components::History::Service()) {
13453 history->SetURITitle(aURI, mTitle);
13454 }
13455}
13456
13457bool nsDocShell::IsInvisible() { return mInvisible; }
13458
13459void nsDocShell::SetInvisible(bool aInvisible) { mInvisible = aInvisible; }
13460
13461/* static */
13462void nsDocShell::MaybeNotifyKeywordSearchLoading(const nsString& aProvider,
13463 const nsString& aKeyword) {
13464 if (aProvider.IsEmpty()) {
13465 return;
13466 }
13467 nsresult rv;
13468 nsCOMPtr<nsISupportsString> isupportsString =
13469 do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID"@mozilla.org/supports-string;1", &rv);
13470 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"
, 13470); return; } } while (false)
;
13471
13472 rv = isupportsString->SetData(aProvider);
13473 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"
, 13473); return; } } while (false)
;
13474
13475 nsCOMPtr<nsIObserverService> obsSvc = services::GetObserverService();
13476 if (obsSvc) {
13477 // Note that "keyword-search" refers to a search via the url
13478 // bar, not a bookmarks keyword search.
13479 obsSvc->NotifyObservers(isupportsString, "keyword-search", aKeyword.get());
13480 }
13481}
13482
13483NS_IMETHODIMPnsresult
13484nsDocShell::ShouldPrepareForIntercept(nsIURI* aURI, nsIChannel* aChannel,
13485 bool* aShouldIntercept) {
13486 return mInterceptController->ShouldPrepareForIntercept(aURI, aChannel,
13487 aShouldIntercept);
13488}
13489
13490NS_IMETHODIMPnsresult
13491nsDocShell::ChannelIntercepted(nsIInterceptedChannel* aChannel) {
13492 return mInterceptController->ChannelIntercepted(aChannel);
13493}
13494
13495bool nsDocShell::InFrameSwap() {
13496 RefPtr<nsDocShell> shell = this;
13497 do {
13498 if (shell->mInFrameSwap) {
13499 return true;
13500 }
13501 shell = shell->GetInProcessParentDocshell();
13502 } while (shell);
13503 return false;
13504}
13505
13506UniquePtr<ClientSource> nsDocShell::TakeInitialClientSource() {
13507 return std::move(mInitialClientSource);
13508}
13509
13510NS_IMETHODIMPnsresult
13511nsDocShell::GetEditingSession(nsIEditingSession** aEditSession) {
13512 if (!NS_SUCCEEDED(EnsureEditorData())((bool)(__builtin_expect(!!(!NS_FAILED_impl(EnsureEditorData(
))), 1)))
) {
13513 return NS_ERROR_FAILURE;
13514 }
13515
13516 *aEditSession = do_AddRef(mEditorData->GetEditingSession()).take();
13517 return *aEditSession ? NS_OK : NS_ERROR_FAILURE;
13518}
13519
13520NS_IMETHODIMPnsresult
13521nsDocShell::GetScriptableBrowserChild(nsIBrowserChild** aBrowserChild) {
13522 *aBrowserChild = GetBrowserChild().take();
13523 return *aBrowserChild ? NS_OK : NS_ERROR_FAILURE;
13524}
13525
13526already_AddRefed<nsIBrowserChild> nsDocShell::GetBrowserChild() {
13527 nsCOMPtr<nsIBrowserChild> tc = do_QueryReferent(mBrowserChild);
13528 return tc.forget();
13529}
13530
13531nsCommandManager* nsDocShell::GetCommandManager() {
13532 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"
, 13532); return nullptr; } } while (false)
;
13533 return mCommandManager;
13534}
13535
13536NS_IMETHODIMP_(void)void
13537nsDocShell::GetOriginAttributes(mozilla::OriginAttributes& aAttrs) {
13538 mBrowsingContext->GetOriginAttributes(aAttrs);
13539}
13540
13541HTMLEditor* nsIDocShell::GetHTMLEditor() {
13542 nsDocShell* docShell = static_cast<nsDocShell*>(this);
13543 return docShell->GetHTMLEditorInternal();
13544}
13545
13546nsresult nsIDocShell::SetHTMLEditor(HTMLEditor* aHTMLEditor) {
13547 nsDocShell* docShell = static_cast<nsDocShell*>(this);
13548 return docShell->SetHTMLEditorInternal(aHTMLEditor);
13549}
13550
13551#define MATRIX_LENGTH 20
13552
13553NS_IMETHODIMPnsresult
13554nsDocShell::SetColorMatrix(const nsTArray<float>& aMatrix) {
13555 if (aMatrix.Length() == MATRIX_LENGTH) {
13556 mColorMatrix.reset(new gfx::Matrix5x4());
13557 static_assert(
13558 MATRIX_LENGTH * sizeof(float) == sizeof(mColorMatrix->components),
13559 "Size mismatch for our memcpy");
13560 memcpy(mColorMatrix->components, aMatrix.Elements(),
13561 sizeof(mColorMatrix->components));
13562 } else if (aMatrix.Length() == 0) {
13563 mColorMatrix.reset();
13564 } else {
13565 return NS_ERROR_INVALID_ARG;
13566 }
13567
13568 PresShell* presShell = GetPresShell();
13569 if (!presShell) {
13570 return NS_ERROR_FAILURE;
13571 }
13572
13573 nsIFrame* frame = presShell->GetRootFrame();
13574 if (!frame) {
13575 return NS_ERROR_FAILURE;
13576 }
13577
13578 frame->SchedulePaint();
13579
13580 return NS_OK;
13581}
13582
13583NS_IMETHODIMPnsresult
13584nsDocShell::GetColorMatrix(nsTArray<float>& aMatrix) {
13585 if (mColorMatrix) {
13586 aMatrix.SetLength(MATRIX_LENGTH);
13587 static_assert(
13588 MATRIX_LENGTH * sizeof(float) == sizeof(mColorMatrix->components),
13589 "Size mismatch for our memcpy");
13590 memcpy(aMatrix.Elements(), mColorMatrix->components,
13591 MATRIX_LENGTH * sizeof(float));
13592 }
13593
13594 return NS_OK;
13595}
13596
13597#undef MATRIX_LENGTH
13598
13599NS_IMETHODIMPnsresult
13600nsDocShell::GetIsForceReloading(bool* aForceReload) {
13601 *aForceReload = IsForceReloading();
13602 return NS_OK;
13603}
13604
13605bool nsDocShell::IsForceReloading() { return IsForceReloadType(mLoadType); }
13606
13607NS_IMETHODIMPnsresult
13608nsDocShell::GetBrowsingContextXPCOM(BrowsingContext** aBrowsingContext) {
13609 *aBrowsingContext = do_AddRef(mBrowsingContext).take();
13610 return NS_OK;
13611}
13612
13613BrowsingContext* nsDocShell::GetBrowsingContext() { return mBrowsingContext; }
13614
13615bool nsDocShell::GetIsAttemptingToNavigate() {
13616 // XXXbz the document.open spec says to abort even if there's just a
13617 // queued navigation task, sort of. It's not clear whether browsers
13618 // actually do that, and we didn't use to do it, so for now let's
13619 // not do that.
13620 // https://github.com/whatwg/html/issues/3447 tracks the spec side of this.
13621 if (mDocumentRequest) {
13622 // There's definitely a navigation in progress.
13623 return true;
13624 }
13625
13626 // javascript: channels have slightly weird behavior: they're LOAD_BACKGROUND
13627 // until the script runs, which means they're not sending loadgroup
13628 // notifications and hence not getting set as mDocumentRequest. Look through
13629 // our loadgroup for document-level javascript: loads.
13630 if (!mLoadGroup) {
13631 return false;
13632 }
13633
13634 nsCOMPtr<nsISimpleEnumerator> requests;
13635 mLoadGroup->GetRequests(getter_AddRefs(requests));
13636 bool hasMore = false;
13637 while (NS_SUCCEEDED(requests->HasMoreElements(&hasMore))((bool)(__builtin_expect(!!(!NS_FAILED_impl(requests->HasMoreElements
(&hasMore))), 1)))
&& hasMore) {
13638 nsCOMPtr<nsISupports> elem;
13639 requests->GetNext(getter_AddRefs(elem));
13640 nsCOMPtr<nsIScriptChannel> scriptChannel(do_QueryInterface(elem));
13641 if (!scriptChannel) {
13642 continue;
13643 }
13644
13645 if (scriptChannel->GetIsDocumentLoad()) {
13646 // This is a javascript: load that might lead to a new document,
13647 // hence a navigation.
13648 return true;
13649 }
13650 }
13651
13652 return mCheckingSessionHistory;
13653}
13654
13655void nsDocShell::SetLoadingSessionHistoryInfo(
13656 const mozilla::dom::LoadingSessionHistoryInfo& aLoadingInfo,
13657 bool aNeedToReportActiveAfterLoadingBecomesActive) {
13658 // FIXME Would like to assert this, but can't yet.
13659 // MOZ_ASSERT(!mLoadingEntry);
13660 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)
13661 ("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)
13662 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)
;
13663 mLoadingEntry = MakeUnique<LoadingSessionHistoryInfo>(aLoadingInfo);
13664 mNeedToReportActiveAfterLoadingBecomesActive =
13665 aNeedToReportActiveAfterLoadingBecomesActive;
13666}
13667
13668void nsDocShell::MoveLoadingToActiveEntry(bool aPersist, bool aExpired,
13669 uint32_t aCacheKey,
13670 nsIURI* aPreviousURI) {
13671 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"
, 13671); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mozilla::SessionHistoryInParent()"
")"); do { *((volatile int*)__null) = 13671; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
13672
13673 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)
13674 ("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)
;
13675
13676 UniquePtr<SessionHistoryInfo> previousActiveEntry(mActiveEntry.release());
13677 mozilla::UniquePtr<mozilla::dom::LoadingSessionHistoryInfo> loadingEntry;
13678 mActiveEntryIsLoadingFromSessionHistory =
13679 mLoadingEntry && mLoadingEntry->mLoadIsFromSessionHistory;
13680 if (mLoadingEntry) {
13681 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)
13682 ("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)
13683 "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)
13684 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)
;
13685 mActiveEntry = MakeUnique<SessionHistoryInfo>(mLoadingEntry->mInfo);
13686 mLoadingEntry.swap(loadingEntry);
13687 if (!mActiveEntryIsLoadingFromSessionHistory) {
13688 if (mNeedToReportActiveAfterLoadingBecomesActive) {
13689 // Needed to pass various history length WPTs.
13690 mBrowsingContext->SetActiveSessionHistoryEntry(
13691 mozilla::Nothing(), mActiveEntry.get(), mLoadType,
13692 /* aUpdatedCacheKey = */ 0, false);
13693 }
13694 mBrowsingContext->IncrementHistoryEntryCountForBrowsingContext();
13695 }
13696 }
13697 mNeedToReportActiveAfterLoadingBecomesActive = false;
13698
13699 if (mActiveEntry) {
13700 if (aCacheKey != 0) {
13701 mActiveEntry->SetCacheKey(aCacheKey);
13702 }
13703 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"
, 13703); AnnotateMozCrashReason("MOZ_ASSERT" "(" "loadingEntry"
")"); do { *((volatile int*)__null) = 13703; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
13704 uint32_t loadType =
13705 mLoadType == LOAD_ERROR_PAGE ? mFailedLoadType : mLoadType;
13706
13707 if (loadingEntry->mLoadId != UINT64_MAX(18446744073709551615UL)) {
13708 // We're passing in mCurrentURI, which could be null. SessionHistoryCommit
13709 // does require a non-null uri if this is for a refresh load of the same
13710 // URI, but in that case mCurrentURI won't be null here.
13711 mBrowsingContext->SessionHistoryCommit(
13712 *loadingEntry, loadType, aPreviousURI, previousActiveEntry.get(),
13713 aPersist, false, aExpired, aCacheKey);
13714 }
13715 }
13716}
13717
13718static bool IsFaviconLoad(nsIRequest* aRequest) {
13719 nsCOMPtr<nsIChannel> channel = do_QueryInterface(aRequest);
13720 if (!channel) {
13721 return false;
13722 }
13723
13724 nsCOMPtr<nsILoadInfo> li = channel->LoadInfo();
13725 return li && li->InternalContentPolicyType() ==
13726 nsIContentPolicy::TYPE_INTERNAL_IMAGE_FAVICON;
13727}
13728
13729void nsDocShell::RecordSingleChannelId(bool aStartRequest,
13730 nsIRequest* aRequest) {
13731 // Ignore favicon loads, they don't need to block caching.
13732 if (IsFaviconLoad(aRequest)) {
13733 return;
13734 }
13735
13736 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"
, 13736); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mRequestForBlockingFromBFCacheCount > 0"
")"); do { *((volatile int*)__null) = 13736; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false); } } while
(false)
;
13737
13738 mRequestForBlockingFromBFCacheCount += aStartRequest ? 1 : -1;
13739
13740 if (mBrowsingContext->GetCurrentWindowContext()) {
13741 // We have three states: no request, one request with an id and
13742 // eiher one request without an id or multiple requests. Nothing() is no
13743 // request, Some(non-zero) is one request with an id and Some(0) is one
13744 // request without an id or multiple requests.
13745 Maybe<uint64_t> singleChannelId;
13746 if (mRequestForBlockingFromBFCacheCount > 1) {
13747 singleChannelId = Some(0);
13748 } else if (mRequestForBlockingFromBFCacheCount == 1) {
13749 nsCOMPtr<nsIIdentChannel> identChannel;
13750 if (aStartRequest) {
13751 identChannel = do_QueryInterface(aRequest);
13752 } else {
13753 // aChannel is the channel that's being removed, but we need to check if
13754 // the remaining channel in the loadgroup has an id.
13755 nsCOMPtr<nsISimpleEnumerator> requests;
13756 mLoadGroup->GetRequests(getter_AddRefs(requests));
13757 for (const auto& request : SimpleEnumerator<nsIRequest>(requests)) {
13758 if (!IsFaviconLoad(request) &&
13759 !!(identChannel = do_QueryInterface(request))) {
13760 break;
13761 }
13762 }
13763 }
13764
13765 if (identChannel) {
13766 singleChannelId = Some(identChannel->ChannelId());
13767 } else {
13768 singleChannelId = Some(0);
13769 }
13770 } else {
13771 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"
, 13771); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mRequestForBlockingFromBFCacheCount == 0"
")"); do { *((volatile int*)__null) = 13771; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
13772 singleChannelId = Nothing();
13773 }
13774
13775 if (MOZ_UNLIKELY(MOZ_LOG_TEST(gSHIPBFCacheLog, LogLevel::Verbose))(__builtin_expect(!!((__builtin_expect(!!(mozilla::detail::log_test
(gSHIPBFCacheLog, LogLevel::Verbose)), 0))), 0))
) {
13776 nsAutoCString uri("[no uri]");
13777 if (mCurrentURI) {
13778 uri = mCurrentURI->GetSpecOrDefault();
13779 }
13780 if (singleChannelId.isNothing()) {
13781 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)
13782 ("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)
13783 "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)
13784 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)
;
13785 } else if (singleChannelId.value() == 0) {
13786 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)
13787 ("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)
13788 "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)
13789 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)
;
13790 } else {
13791 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)
13792 ("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)
13793 " 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)
13794 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)
;
13795 }
13796 }
13797
13798 if (mSingleChannelId != singleChannelId) {
13799 mSingleChannelId = singleChannelId;
13800 WindowGlobalChild* wgc =
13801 mBrowsingContext->GetCurrentWindowContext()->GetWindowGlobalChild();
13802 if (wgc) {
13803 wgc->SendSetSingleChannelId(singleChannelId);
13804 }
13805 }
13806 }
13807}
13808
13809NS_IMETHODIMPnsresult
13810nsDocShell::OnStartRequest(nsIRequest* aRequest) {
13811 if (MOZ_UNLIKELY(MOZ_LOG_TEST(gSHIPBFCacheLog, LogLevel::Verbose))(__builtin_expect(!!((__builtin_expect(!!(mozilla::detail::log_test
(gSHIPBFCacheLog, LogLevel::Verbose)), 0))), 0))
) {
13812 nsAutoCString uri("[no uri]");
13813 if (mCurrentURI) {
13814 uri = mCurrentURI->GetSpecOrDefault();
13815 }
13816 nsAutoCString name;
13817 aRequest->GetName(name);
13818 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)
13819 ("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)
;
13820 }
13821 RecordSingleChannelId(true, aRequest);
13822 return nsDocLoader::OnStartRequest(aRequest);
13823}
13824
13825NS_IMETHODIMPnsresult
13826nsDocShell::OnStopRequest(nsIRequest* aRequest, nsresult aStatusCode) {
13827 if (MOZ_UNLIKELY(MOZ_LOG_TEST(gSHIPBFCacheLog, LogLevel::Verbose))(__builtin_expect(!!((__builtin_expect(!!(mozilla::detail::log_test
(gSHIPBFCacheLog, LogLevel::Verbose)), 0))), 0))
) {
13828 nsAutoCString uri("[no uri]");
13829 if (mCurrentURI) {
13830 uri = mCurrentURI->GetSpecOrDefault();
13831 }
13832 nsAutoCString name;
13833 aRequest->GetName(name);
13834 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)
13835 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)
13836 ("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)
;
13837 }
13838 RecordSingleChannelId(false, aRequest);
13839 return nsDocLoader::OnStopRequest(aRequest, aStatusCode);
13840}
13841
13842void nsDocShell::MaybeDisconnectChildListenersOnPageHide() {
13843 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"
, 13843); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "XRE_IsContentProcess()"
")"); do { *((volatile int*)__null) = 13843; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
13844
13845 if (mChannelToDisconnectOnPageHide != 0 && mLoadGroup) {
13846 nsCOMPtr<nsISimpleEnumerator> requests;
13847 mLoadGroup->GetRequests(getter_AddRefs(requests));
13848 for (const auto& request : SimpleEnumerator<nsIRequest>(requests)) {
13849 RefPtr<DocumentChannel> channel = do_QueryObject(request);
13850 if (channel && channel->ChannelId() == mChannelToDisconnectOnPageHide) {
13851 static_cast<DocumentChannelChild*>(channel.get())
13852 ->DisconnectChildListeners(NS_BINDING_ABORTED, NS_BINDING_ABORTED);
13853 }
13854 }
13855 mChannelToDisconnectOnPageHide = 0;
13856 }
13857}