Bug Summary

File:root/firefox-clang/docshell/base/nsDocShell.cpp
Warning:line 3442, 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=/root/firefox-clang/obj-x86_64-pc-linux-gnu/docshell/base -fcoverage-compilation-dir=/root/firefox-clang/obj-x86_64-pc-linux-gnu/docshell/base -resource-dir /usr/lib/llvm-21/lib/clang/21 -include /root/firefox-clang/config/gcc_hidden.h -include /root/firefox-clang/obj-x86_64-pc-linux-gnu/mozilla-config.h -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/stl_wrappers -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/system_wrappers -U _FORTIFY_SOURCE -D _FORTIFY_SOURCE=2 -D _GLIBCXX_ASSERTIONS -D DEBUG=1 -D MOZ_HAS_MOZGLUE -D MOZILLA_INTERNAL_API -D IMPL_LIBXUL -D MOZ_SUPPORT_LEAKCHECKING -D STATIC_EXPORTABLE_JS_API -I /root/firefox-clang/docshell/base -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/docshell/base -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/ipc/ipdl/_ipdlheaders -I /root/firefox-clang/ipc/chromium/src -I /root/firefox-clang/docshell/shistory -I /root/firefox-clang/dom/base -I /root/firefox-clang/dom/bindings -I /root/firefox-clang/js/xpconnect/src -I /root/firefox-clang/layout/base -I /root/firefox-clang/layout/generic -I /root/firefox-clang/layout/style -I /root/firefox-clang/layout/xul -I /root/firefox-clang/netwerk/base -I /root/firefox-clang/netwerk/protocol/viewsource -I /root/firefox-clang/toolkit/components/browser -I /root/firefox-clang/toolkit/components/find -I /root/firefox-clang/tools/profiler -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/nspr -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/nss -D MOZILLA_CLIENT -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../include/x86_64-linux-gnu/c++/14 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/backward -internal-isystem /usr/lib/llvm-21/lib/clang/21/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-error=pessimizing-move -Wno-error=large-by-value-copy=128 -Wno-error=implicit-int-float-conversion -Wno-error=thread-safety-analysis -Wno-error=tautological-type-limit-compare -Wno-invalid-offsetof -Wno-range-loop-analysis -Wno-deprecated-anon-enum-enum-conversion -Wno-deprecated-enum-enum-conversion -Wno-deprecated-this-capture -Wno-inline-new-delete -Wno-error=deprecated-declarations -Wno-error=array-bounds -Wno-error=free-nonheap-object -Wno-error=atomic-alignment -Wno-error=deprecated-builtins -Wno-psabi -Wno-error=builtin-macro-redefined -Wno-vla-cxx-extension -Wno-unknown-warning-option -fdeprecated-macro -ferror-limit 19 -fstrict-flex-arrays=1 -stack-protector 2 -fstack-clash-protection -ftrivial-auto-var-init=pattern -fno-rtti -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -fno-sized-deallocation -fno-aligned-allocation -vectorize-loops -vectorize-slp -analyzer-checker optin.performance.Padding -analyzer-output=html -analyzer-config stable-report-filename=true -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/scan-build-2025-06-27-100320-3286336-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#include "mozilla/dom/HTMLFormElement.h"
11
12#ifdef XP_WIN
13# include <process.h>
14# define getpid _getpid
15#else
16# include <unistd.h> // for getpid()
17#endif
18
19#include "mozilla/ArrayUtils.h"
20#include "mozilla/Attributes.h"
21#include "mozilla/AutoRestore.h"
22#include "mozilla/BasePrincipal.h"
23#include "mozilla/Casting.h"
24#include "mozilla/CheckedInt.h"
25#include "mozilla/Components.h"
26#include "mozilla/DebugOnly.h"
27#include "mozilla/Encoding.h"
28#include "mozilla/EventStateManager.h"
29#include "mozilla/HTMLEditor.h"
30#include "mozilla/InputTaskManager.h"
31#include "mozilla/LoadInfo.h"
32#include "mozilla/Logging.h"
33#include "mozilla/MediaFeatureChange.h"
34#include "mozilla/Preferences.h"
35#include "mozilla/PresShell.h"
36#include "mozilla/ResultExtensions.h"
37#include "mozilla/SchedulerGroup.h"
38#include "mozilla/ScopeExit.h"
39#include "mozilla/ScrollContainerFrame.h"
40#include "mozilla/ScrollTypes.h"
41#include "mozilla/SimpleEnumerator.h"
42#include "mozilla/StaticPrefs_browser.h"
43#include "mozilla/StaticPrefs_docshell.h"
44#include "mozilla/StaticPrefs_dom.h"
45#include "mozilla/StaticPrefs_extensions.h"
46#include "mozilla/StaticPrefs_privacy.h"
47#include "mozilla/StaticPrefs_security.h"
48#include "mozilla/StaticPrefs_ui.h"
49#include "mozilla/StaticPrefs_fission.h"
50#include "mozilla/StartupTimeline.h"
51#include "mozilla/StorageAccess.h"
52#include "mozilla/StoragePrincipalHelper.h"
53#include "mozilla/Telemetry.h"
54
55#include "mozilla/Unused.h"
56#include "mozilla/WidgetUtils.h"
57
58#include "mozilla/dom/AutoEntryScript.h"
59#include "mozilla/dom/ChildProcessChannelListener.h"
60#include "mozilla/dom/ClientChannelHelper.h"
61#include "mozilla/dom/ClientHandle.h"
62#include "mozilla/dom/ClientInfo.h"
63#include "mozilla/dom/ClientManager.h"
64#include "mozilla/dom/ClientSource.h"
65#include "mozilla/dom/ContentChild.h"
66#include "mozilla/dom/ContentFrameMessageManager.h"
67#include "mozilla/dom/DocGroup.h"
68#include "mozilla/dom/Element.h"
69#include "mozilla/dom/FragmentDirective.h"
70#include "mozilla/dom/HTMLAnchorElement.h"
71#include "mozilla/dom/HTMLIFrameElement.h"
72#include "mozilla/dom/Navigation.h"
73#include "mozilla/dom/NavigationBinding.h"
74#include "mozilla/dom/NavigationHistoryEntry.h"
75#include "mozilla/dom/PerformanceNavigation.h"
76#include "mozilla/dom/PermissionMessageUtils.h"
77#include "mozilla/dom/PopupBlocker.h"
78#include "mozilla/dom/ScreenOrientation.h"
79#include "mozilla/dom/ScriptSettings.h"
80#include "mozilla/dom/ServiceWorkerInterceptController.h"
81#include "mozilla/dom/ServiceWorkerUtils.h"
82#include "mozilla/dom/SessionHistoryEntry.h"
83#include "mozilla/dom/SessionStorageManager.h"
84#include "mozilla/dom/SessionStoreChangeListener.h"
85#include "mozilla/dom/SessionStoreChild.h"
86#include "mozilla/dom/SessionStoreUtils.h"
87#include "mozilla/dom/BrowserChild.h"
88#include "mozilla/dom/ToJSValue.h"
89#include "mozilla/dom/UserActivation.h"
90#include "mozilla/dom/ChildSHistory.h"
91#include "mozilla/dom/nsCSPContext.h"
92#include "mozilla/dom/nsHTTPSOnlyUtils.h"
93#include "mozilla/dom/LoadURIOptionsBinding.h"
94#include "mozilla/dom/JSWindowActorChild.h"
95#include "mozilla/dom/DocumentBinding.h"
96#include "mozilla/glean/DocshellMetrics.h"
97#include "mozilla/ipc/ProtocolUtils.h"
98#include "mozilla/net/DocumentChannel.h"
99#include "mozilla/net/DocumentChannelChild.h"
100#include "mozilla/net/ParentChannelWrapper.h"
101#include "mozilla/net/UrlClassifierFeatureFactory.h"
102#include "ReferrerInfo.h"
103
104#include "nsIAuthPrompt.h"
105#include "nsIAuthPrompt2.h"
106#include "nsICachingChannel.h"
107#include "nsICaptivePortalService.h"
108#include "nsIChannel.h"
109#include "nsIChannelEventSink.h"
110#include "nsIClassifiedChannel.h"
111#include "nsIClassOfService.h"
112#include "nsIConsoleReportCollector.h"
113#include "nsIContent.h"
114#include "nsIContentInlines.h"
115#include "nsIContentSecurityPolicy.h"
116#include "nsIController.h"
117#include "nsIDocShellTreeItem.h"
118#include "nsIDocShellTreeOwner.h"
119#include "nsIDocumentViewer.h"
120#include "mozilla/dom/Document.h"
121#include "nsHTMLDocument.h"
122#include "nsIDocumentLoaderFactory.h"
123#include "nsIDOMWindow.h"
124#include "nsIEditingSession.h"
125#include "nsIEffectiveTLDService.h"
126#include "nsIExternalProtocolService.h"
127#include "nsIFormPOSTActionChannel.h"
128#include "nsIFrame.h"
129#include "nsIGlobalObject.h"
130#include "nsIHttpChannel.h"
131#include "nsIHttpChannelInternal.h"
132#include "nsIIDNService.h"
133#include "nsIInputStreamChannel.h"
134#include "nsIInterfaceRequestorUtils.h"
135#include "nsILayoutHistoryState.h"
136#include "nsILoadInfo.h"
137#include "nsILoadURIDelegate.h"
138#include "nsIMultiPartChannel.h"
139#include "nsINestedURI.h"
140#include "nsINetworkPredictor.h"
141#include "nsINode.h"
142#include "nsINSSErrorsService.h"
143#include "nsIObserverService.h"
144#include "nsIOService.h"
145#include "nsIPrincipal.h"
146#include "nsIPrivacyTransitionObserver.h"
147#include "nsIPrompt.h"
148#include "nsIPromptCollection.h"
149#include "nsIPromptFactory.h"
150#include "nsIPublicKeyPinningService.h"
151#include "nsIReflowObserver.h"
152#include "nsIScriptChannel.h"
153#include "nsIScriptObjectPrincipal.h"
154#include "nsIScriptSecurityManager.h"
155#include "nsScriptSecurityManager.h"
156#include "nsIScrollObserver.h"
157#include "nsISupportsPrimitives.h"
158#include "nsISecureBrowserUI.h"
159#include "nsISeekableStream.h"
160#include "nsISelectionDisplay.h"
161#include "nsISHEntry.h"
162#include "nsISiteSecurityService.h"
163#include "nsISocketProvider.h"
164#include "nsIStringBundle.h"
165#include "nsIStructuredCloneContainer.h"
166#include "nsIBrowserChild.h"
167#include "nsITextToSubURI.h"
168#include "nsITimedChannel.h"
169#include "nsITimer.h"
170#include "nsITransportSecurityInfo.h"
171#include "nsIUploadChannel.h"
172#include "nsIURIFixup.h"
173#include "nsIURIMutator.h"
174#include "nsIURILoader.h"
175#include "nsIViewSourceChannel.h"
176#include "nsIWebBrowserChrome.h"
177#include "nsIWebBrowserFind.h"
178#include "nsIWebProgress.h"
179#include "nsIWidget.h"
180#include "nsIWindowWatcher.h"
181#include "nsIWritablePropertyBag2.h"
182#include "nsIX509Cert.h"
183#include "nsIXULRuntime.h"
184
185#include "nsCommandManager.h"
186#include "nsPIDOMWindow.h"
187#include "nsPIWindowRoot.h"
188
189#include "IHistory.h"
190#include "IUrlClassifierUITelemetry.h"
191
192#include "nsArray.h"
193#include "nsArrayUtils.h"
194#include "nsBrowserStatusFilter.h"
195#include "nsCExternalHandlerService.h"
196#include "nsContentDLF.h"
197#include "nsContentPolicyUtils.h" // NS_CheckContentLoadPolicy(...)
198#include "nsContentSecurityManager.h"
199#include "nsContentSecurityUtils.h"
200#include "nsContentUtils.h"
201#include "nsCURILoader.h"
202#include "nsDocShellCID.h"
203#include "nsDocShellEditorData.h"
204#include "nsDocShellEnumerator.h"
205#include "nsDocShellLoadState.h"
206#include "nsDocShellLoadTypes.h"
207#include "nsDOMCID.h"
208#include "nsDOMNavigationTiming.h"
209#include "nsDSURIContentListener.h"
210#include "nsEditingSession.h"
211#include "nsError.h"
212#include "nsEscape.h"
213#include "nsFocusManager.h"
214#include "nsGlobalWindowInner.h"
215#include "nsGlobalWindowOuter.h"
216#include "nsJSEnvironment.h"
217#include "nsNetCID.h"
218#include "nsNetUtil.h"
219#include "nsObjectLoadingContent.h"
220#include "nsPingListener.h"
221#include "nsPoint.h"
222#include "nsQueryObject.h"
223#include "nsQueryActor.h"
224#include "nsRect.h"
225#include "nsRefreshTimer.h"
226#include "nsSandboxFlags.h"
227#include "nsSHEntry.h"
228#include "nsSHistory.h"
229#include "nsSHEntry.h"
230#include "nsStructuredCloneContainer.h"
231#include "nsSubDocumentFrame.h"
232#include "nsURILoader.h"
233#include "nsURLHelper.h"
234#include "nsView.h"
235#include "nsViewManager.h"
236#include "nsViewSourceHandler.h"
237#include "nsWebBrowserFind.h"
238#include "nsWhitespaceTokenizer.h"
239#include "nsWidgetsCID.h"
240#include "nsXULAppAPI.h"
241
242#include "CertVerifier.h"
243#include "ThirdPartyUtil.h"
244#include "GeckoProfiler.h"
245#include "mozilla/NullPrincipal.h"
246#include "Navigator.h"
247#include "prenv.h"
248#include "mozilla/ipc/URIUtils.h"
249#include "sslerr.h"
250#include "mozpkix/pkix.h"
251#include "NSSErrorsService.h"
252
253#include "nsDocShellTelemetryUtils.h"
254
255#ifdef MOZ_PLACES1
256# include "mozilla/places/nsFaviconService.h"
257# include "mozIPlacesPendingOperation.h"
258#endif
259
260#if NS_PRINT_PREVIEW1
261# include "nsIDocumentViewerPrint.h"
262# include "nsIWebBrowserPrint.h"
263#endif
264
265using namespace mozilla;
266using namespace mozilla::dom;
267using namespace mozilla::net;
268
269using mozilla::ipc::Endpoint;
270
271// Threshold value in ms for META refresh based redirects
272#define REFRESH_REDIRECT_TIMER15000 15000
273
274static mozilla::LazyLogModule gCharsetMenuLog("CharsetMenu");
275
276#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)
\
277 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)
278
279#ifdef DEBUG1
280unsigned long nsDocShell::gNumberOfDocShells = 0;
281static uint64_t gDocshellIDCounter = 0;
282
283static mozilla::LazyLogModule gDocShellLog("nsDocShell");
284static mozilla::LazyLogModule gDocShellAndDOMWindowLeakLogging(
285 "DocShellAndDOMWindowLeak");
286#endif
287static mozilla::LazyLogModule gDocShellLeakLog("nsDocShellLeak");
288extern mozilla::LazyLogModule gPageCacheLog;
289extern mozilla::LazyLogModule gNavigationLog;
290mozilla::LazyLogModule gSHLog("SessionHistory");
291extern mozilla::LazyLogModule gSHIPBFCacheLog;
292
293const char kAppstringsBundleURL[] =
294 "chrome://global/locale/appstrings.properties";
295
296static bool IsTopLevelDoc(BrowsingContext* aBrowsingContext,
297 nsILoadInfo* aLoadInfo) {
298 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"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 298); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aBrowsingContext" ")"); do { MOZ_CrashSequence
(__null, 298); __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
299 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", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 299); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadInfo" ")"
); do { MOZ_CrashSequence(__null, 299); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
300
301 if (aLoadInfo->GetExternalContentPolicyType() !=
302 ExtContentPolicy::TYPE_DOCUMENT) {
303 return false;
304 }
305
306 return aBrowsingContext->IsTopContent();
307}
308
309// True if loading for top level document loading in active tab.
310static bool IsUrgentStart(BrowsingContext* aBrowsingContext,
311 nsILoadInfo* aLoadInfo, uint32_t aLoadType) {
312 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"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 312); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aBrowsingContext" ")"); do { MOZ_CrashSequence
(__null, 312); __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
313 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", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 313); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadInfo" ")"
); do { MOZ_CrashSequence(__null, 313); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
314
315 if (!IsTopLevelDoc(aBrowsingContext, aLoadInfo)) {
316 return false;
317 }
318
319 if (aLoadType &
320 (nsIDocShell::LOAD_CMD_NORMAL | nsIDocShell::LOAD_CMD_HISTORY)) {
321 return true;
322 }
323
324 return aBrowsingContext->IsActive();
325}
326
327nsDocShell::nsDocShell(BrowsingContext* aBrowsingContext,
328 uint64_t aContentWindowID)
329 : nsDocLoader(true),
330 mContentWindowID(aContentWindowID),
331 mBrowsingContext(aBrowsingContext),
332 mParentCharset(nullptr),
333 mTreeOwner(nullptr),
334 mScrollbarPref(ScrollbarPreference::Auto),
335 mCharsetReloadState(eCharsetReloadInit),
336 mParentCharsetSource(0),
337 mFrameMargins(-1, -1),
338 mItemType(aBrowsingContext->IsContent() ? typeContent : typeChrome),
339 mPreviousEntryIndex(-1),
340 mLoadedEntryIndex(-1),
341 mBusyFlags(BUSY_FLAGS_NONE),
342 mAppType(nsIDocShell::APP_TYPE_UNKNOWN),
343 mLoadType(0),
344 mFailedLoadType(0),
345 mChannelToDisconnectOnPageHide(0),
346 mCreatingDocument(false),
347#ifdef DEBUG1
348 mInEnsureScriptEnv(false),
349#endif
350 mInitialized(false),
351 mAllowSubframes(true),
352 mAllowMetaRedirects(true),
353 mAllowImages(true),
354 mAllowMedia(true),
355 mAllowDNSPrefetch(true),
356 mAllowWindowControl(true),
357 mCSSErrorReportingEnabled(false),
358 mAllowAuth(mItemType == typeContent),
359 mAllowKeywordFixup(false),
360 mDisableMetaRefreshWhenInactive(false),
361 mWindowDraggingAllowed(false),
362 mInFrameSwap(false),
363 mFiredUnloadEvent(false),
364 mEODForCurrentDocument(false),
365 mURIResultedInDocument(false),
366 mIsBeingDestroyed(false),
367 mIsExecutingOnLoadHandler(false),
368 mSavingOldViewer(false),
369 mInvisible(false),
370 mHasLoadedNonBlankURI(false),
371 mBlankTiming(false),
372 mTitleValidForCurrentURI(false),
373 mWillChangeProcess(false),
374 mIsNavigating(false),
375 mForcedAutodetection(false),
376 mCheckingSessionHistory(false),
377 mNeedToReportActiveAfterLoadingBecomesActive(false) {
378 // If no outer window ID was provided, generate a new one.
379 if (aContentWindowID == 0) {
380 mContentWindowID = nsContentUtils::GenerateWindowId();
381 }
382
383 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)
;
384
385#ifdef DEBUG1
386 mDocShellID = gDocshellIDCounter++;
387 // We're counting the number of |nsDocShells| to help find leaks
388 ++gNumberOfDocShells;
389 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)
390 ("++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)
391 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)
;
392#endif
393}
394
395nsDocShell::~nsDocShell() {
396 // Avoid notifying observers while we're in the dtor.
397 mIsBeingDestroyed = true;
398
399 Destroy();
400
401 if (mDocumentViewer) {
402 mDocumentViewer->Close(nullptr);
403 mDocumentViewer->Destroy();
404 mDocumentViewer = nullptr;
405 }
406
407 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)
;
408
409#ifdef DEBUG1
410 if (MOZ_LOG_TEST(gDocShellAndDOMWindowLeakLogging, LogLevel::Info)(__builtin_expect(!!(mozilla::detail::log_test(gDocShellAndDOMWindowLeakLogging
, LogLevel::Info)), 0))
) {
411 nsAutoCString url;
412 if (mLastOpenedURI) {
413 url = mLastOpenedURI->GetSpecOrDefault();
414
415 // Data URLs can be very long, so truncate to avoid flooding the log.
416 const uint32_t maxURLLength = 1000;
417 if (url.Length() > maxURLLength) {
418 url.Truncate(maxURLLength);
419 }
420 }
421
422 // We're counting the number of |nsDocShells| to help find leaks
423 --gNumberOfDocShells;
424 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)
425 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)
426 ("--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)
427 (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)
;
428 }
429#endif
430}
431
432bool nsDocShell::Initialize() {
433 if (mInitialized) {
434 // We've already been initialized.
435 return true;
436 }
437
438 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", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 439); MOZ_PretendNoReturn(); } } while (0)
439 "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", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 439); MOZ_PretendNoReturn(); } } while (0)
;
440
441 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, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 441); return false; } } while (false)
;
442 mInitialized = true;
443
444 mDisableMetaRefreshWhenInactive =
445 Preferences::GetBool("browser.meta_refresh_when_inactive.disabled",
446 mDisableMetaRefreshWhenInactive);
447
448 if (nsCOMPtr<nsIObserverService> serv = services::GetObserverService()) {
449 const char* msg = mItemType == typeContent ? NS_WEBNAVIGATION_CREATE"webnavigation-create"
450 : NS_CHROME_WEBNAVIGATION_CREATE"chrome-webnavigation-create";
451 serv->NotifyWhenScriptSafe(GetAsSupports(this), msg, nullptr);
452 }
453
454 return true;
455}
456
457/* static */
458already_AddRefed<nsDocShell> nsDocShell::Create(
459 BrowsingContext* aBrowsingContext, uint64_t aContentWindowID) {
460 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!" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 460); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aBrowsingContext"
") (" "DocShell without a BrowsingContext!" ")"); do { MOZ_CrashSequence
(__null, 460); __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
461
462 nsresult rv;
463 RefPtr<nsDocShell> ds = new nsDocShell(aBrowsingContext, aContentWindowID);
464
465 // Initialize the underlying nsDocLoader.
466 rv = ds->nsDocLoader::InitWithBrowsingContext(aBrowsingContext);
467 if (NS_WARN_IF(NS_FAILED(rv))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(rv
)), 0))), "NS_FAILED(rv)", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 467)
) {
468 return nullptr;
469 }
470
471 // Create our ContentListener
472 ds->mContentListener = new nsDSURIContentListener(ds);
473
474 // We enable if we're in the parent process in order to support non-e10s
475 // configurations.
476 // Note: This check is duplicated in SharedWorkerInterfaceRequestor's
477 // constructor.
478 if (XRE_IsParentProcess()) {
479 ds->mInterceptController = new ServiceWorkerInterceptController();
480 }
481
482 // We want to hold a strong ref to the loadgroup, so it better hold a weak
483 // ref to us... use an InterfaceRequestorProxy to do this.
484 nsCOMPtr<nsIInterfaceRequestor> proxy = new InterfaceRequestorProxy(ds);
485 ds->mLoadGroup->SetNotificationCallbacks(proxy);
486
487 // XXX(nika): We have our BrowsingContext, so we might be able to skip this.
488 // It could be nice to directly set up our DocLoader tree?
489 rv = nsDocLoader::AddDocLoaderAsChildOfRoot(ds);
490 if (NS_WARN_IF(NS_FAILED(rv))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(rv
)), 0))), "NS_FAILED(rv)", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 490)
) {
491 return nullptr;
492 }
493
494 uint32_t notifyMask =
495 nsIWebProgress::NOTIFY_STATE_ALL | nsIWebProgress::NOTIFY_LOCATION |
496 nsIWebProgress::NOTIFY_SECURITY | nsIWebProgress::NOTIFY_STATUS;
497
498 // NOTE: Only listen for NOTIFY_PROGRESS on toplevel BrowsingContexts, as
499 // listeners in the browser UI only cares about total progress on the toplevel
500 // context. Aggregation of the total progress is currently handled within
501 // `nsDocLoader`, and does not take out-of-process iframes into account.
502 if (aBrowsingContext->IsTop()) {
503 notifyMask |= nsIWebProgress::NOTIFY_PROGRESS;
504 }
505
506 // Add |ds| as a progress listener to itself. A little weird, but simpler
507 // than reproducing all the listener-notification logic in overrides of the
508 // various methods via which nsDocLoader can be notified. Note that this
509 // holds an nsWeakPtr to |ds|, so it's ok.
510 rv = ds->AddProgressListener(ds, notifyMask);
511 if (NS_WARN_IF(NS_FAILED(rv))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(rv
)), 0))), "NS_FAILED(rv)", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 511)
) {
512 return nullptr;
513 }
514
515 // If our BrowsingContext has private browsing enabled, update the number of
516 // private browsing docshells.
517 if (aBrowsingContext->UsePrivateBrowsing()) {
518 ds->NotifyPrivateBrowsingChanged();
519 }
520
521 // If our parent window is present in this process, set up our parent now.
522 RefPtr<WindowContext> parentWC = aBrowsingContext->GetParentWindowContext();
523 if (parentWC && parentWC->IsInProcess()) {
524 // If we don't have a parent element anymore, we can't finish this load!
525 // How'd we get here?
526 RefPtr<Element> parentElement = aBrowsingContext->GetEmbedderElement();
527 if (!parentElement) {
528 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" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 528); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "nsDocShell::Create() - !parentElement"
")"); do { MOZ_CrashSequence(__null, 528); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
529 return nullptr;
530 }
531
532 // We have an in-process parent window, but don't have a parent nsDocShell?
533 // How'd we get here!
534 nsCOMPtr<nsIDocShell> parentShell =
535 parentElement->OwnerDoc()->GetDocShell();
536 if (!parentShell) {
537 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" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 537); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "nsDocShell::Create() - !parentShell"
")"); do { MOZ_CrashSequence(__null, 537); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
538 return nullptr;
539 }
540 parentShell->AddChild(ds);
541 }
542
543 // Make |ds| the primary DocShell for the given context.
544 aBrowsingContext->SetDocShell(ds);
545
546 // Set |ds| default load flags on load group.
547 ds->SetLoadGroupDefaultLoadFlags(aBrowsingContext->GetDefaultLoadFlags());
548
549 return ds.forget();
550}
551
552void nsDocShell::DestroyChildren() {
553 for (auto* child : mChildList.ForwardRange()) {
554 nsCOMPtr<nsIDocShellTreeItem> shell = do_QueryObject(child);
555 NS_ASSERTION(shell, "docshell has null child")do { if (!(shell)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "docshell has null child"
, "shell", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 555); MOZ_PretendNoReturn(); } } while (0)
;
556
557 if (shell) {
558 shell->SetTreeOwner(nullptr);
559 }
560 }
561
562 nsDocLoader::DestroyChildren();
563}
564
565NS_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); ImplCycleCollectionUnlink(tmp->mBCWebProgressStatusFilter
); 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); ImplCycleCollectionTraverse(cb, tmp
->mBCWebProgressStatusFilter, "mBCWebProgressStatusFilter"
, 0); (void)tmp; return NS_OK; }
566 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); ImplCycleCollectionUnlink(tmp->mBCWebProgressStatusFilter
); 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); ImplCycleCollectionTraverse(cb, tmp
->mBCWebProgressStatusFilter, "mBCWebProgressStatusFilter"
, 0); (void)tmp; return NS_OK; }
567 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); ImplCycleCollectionUnlink(tmp->mBCWebProgressStatusFilter
); 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); ImplCycleCollectionTraverse(cb, tmp
->mBCWebProgressStatusFilter, "mBCWebProgressStatusFilter"
, 0); (void)tmp; return NS_OK; }
568 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); ImplCycleCollectionUnlink(tmp->mBCWebProgressStatusFilter
); 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); ImplCycleCollectionTraverse(cb, tmp
->mBCWebProgressStatusFilter, "mBCWebProgressStatusFilter"
, 0); (void)tmp; return NS_OK; }
569 mBCWebProgressStatusFilter)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); ImplCycleCollectionUnlink(tmp->mBCWebProgressStatusFilter
); 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); ImplCycleCollectionTraverse(cb, tmp
->mBCWebProgressStatusFilter, "mBCWebProgressStatusFilter"
, 0); (void)tmp; return NS_OK; }
570
571NS_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; }
572NS_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; }
573
574NS_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", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 574); MOZ_PretendNoReturn(); } } while (0); nsISupports* foundInterface
; if (TopThreeWordsEquals( aIID, (nsXPCOMCycleCollectionParticipant
::kIID), (nsCycleCollectionISupports::kIID)) && (LowWordEquals
(aIID, (nsXPCOMCycleCollectionParticipant::kIID)) || LowWordEquals
(aIID, (nsCycleCollectionISupports::kIID)))) { if (LowWordEquals
(aIID, (nsXPCOMCycleCollectionParticipant::kIID))) { *aInstancePtr
= nsDocShell::cycleCollection::GetParticipant(); return NS_OK
; } if (LowWordEquals(aIID, (nsCycleCollectionISupports::kIID
))) { *aInstancePtr = nsDocShell::cycleCollection::Upcast(this
); return NS_OK; } foundInterface = nullptr; } else
575 NS_INTERFACE_MAP_ENTRY(nsIDocShell)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIDocShell>)) foundInterface = static_cast
<nsIDocShell*>(this); else
576 NS_INTERFACE_MAP_ENTRY(nsIDocShellTreeItem)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIDocShellTreeItem>)) foundInterface
= static_cast<nsIDocShellTreeItem*>(this); else
577 NS_INTERFACE_MAP_ENTRY(nsIWebNavigation)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIWebNavigation>)) foundInterface
= static_cast<nsIWebNavigation*>(this); else
578 NS_INTERFACE_MAP_ENTRY(nsIBaseWindow)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIBaseWindow>)) foundInterface =
static_cast<nsIBaseWindow*>(this); else
579 NS_INTERFACE_MAP_ENTRY(nsIRefreshURI)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIRefreshURI>)) foundInterface =
static_cast<nsIRefreshURI*>(this); else
580 NS_INTERFACE_MAP_ENTRY(nsIWebProgressListener)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIWebProgressListener>)) foundInterface
= static_cast<nsIWebProgressListener*>(this); else
581 NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsISupportsWeakReference>)) foundInterface
= static_cast<nsISupportsWeakReference*>(this); else
582 NS_INTERFACE_MAP_ENTRY(nsIWebPageDescriptor)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIWebPageDescriptor>)) foundInterface
= static_cast<nsIWebPageDescriptor*>(this); else
583 NS_INTERFACE_MAP_ENTRY(nsIAuthPromptProvider)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIAuthPromptProvider>)) foundInterface
= static_cast<nsIAuthPromptProvider*>(this); else
584 NS_INTERFACE_MAP_ENTRY(nsILoadContext)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsILoadContext>)) foundInterface =
static_cast<nsILoadContext*>(this); else
585 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
586 mInterceptController)if ((mInterceptController) && aIID.Equals(mozilla::detail
::kImplementedIID<std::remove_reference_t<decltype(*this
)>, nsINetworkInterceptController>)) foundInterface = static_cast
<nsINetworkInterceptController*>(this); else
587NS_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; }
588
589NS_IMETHODIMPnsresult
590nsDocShell::GetInterface(const nsIID& aIID, void** aSink) {
591 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"
")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 591
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aSink" ") (" "null out param"
")"); do { MOZ_CrashSequence(__null, 591); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
592
593 *aSink = nullptr;
594
595 if (aIID.Equals(NS_GET_IID(nsICommandManager)(nsICommandManager::kIID))) {
596 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
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 596); return
NS_ERROR_FAILURE; } } while (false)
;
597 *aSink = static_cast<nsICommandManager*>(mCommandManager.get());
598 } else if (aIID.Equals(NS_GET_IID(nsIURIContentListener)(nsIURIContentListener::kIID))) {
599 *aSink = mContentListener;
600 } else if ((aIID.Equals(NS_GET_IID(nsIScriptGlobalObject)(nsIScriptGlobalObject::kIID)) ||
601 aIID.Equals(NS_GET_IID(nsIGlobalObject)(nsIGlobalObject::kIID)) ||
602 aIID.Equals(NS_GET_IID(nsPIDOMWindowOuter)(nsPIDOMWindowOuter::kIID)) ||
603 aIID.Equals(NS_GET_IID(mozIDOMWindowProxy)(mozIDOMWindowProxy::kIID)) ||
604 aIID.Equals(NS_GET_IID(nsIDOMWindow)(nsIDOMWindow::kIID))) &&
605 NS_SUCCEEDED(EnsureScriptEnvironment())((bool)(__builtin_expect(!!(!NS_FAILED_impl(EnsureScriptEnvironment
())), 1)))
) {
606 return mScriptGlobal->QueryInterface(aIID, aSink);
607 } else if (aIID.Equals(NS_GET_IID(Document)(Document::kIID)) &&
608 NS_SUCCEEDED(EnsureDocumentViewer())((bool)(__builtin_expect(!!(!NS_FAILED_impl(EnsureDocumentViewer
())), 1)))
) {
609 RefPtr<Document> doc = mDocumentViewer->GetDocument();
610 doc.forget(aSink);
611 return *aSink ? NS_OK : NS_NOINTERFACE;
612 } else if (aIID.Equals(NS_GET_IID(nsIPrompt)(nsIPrompt::kIID)) &&
613 NS_SUCCEEDED(EnsureScriptEnvironment())((bool)(__builtin_expect(!!(!NS_FAILED_impl(EnsureScriptEnvironment
())), 1)))
) {
614 nsresult rv;
615 nsCOMPtr<nsIWindowWatcher> wwatch =
616 do_GetService(NS_WINDOWWATCHER_CONTRACTID"@mozilla.org/embedcomp/window-watcher;1", &rv);
617 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, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 617); return rv; } } while (false)
;
618
619 // Get the an auth prompter for our window so that the parenting
620 // of the dialogs works as it should when using tabs.
621 nsIPrompt* prompt;
622 rv = wwatch->GetNewPrompter(mScriptGlobal, &prompt);
623 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, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 623); return rv; } } while (false)
;
624
625 *aSink = prompt;
626 return NS_OK;
627 } else if (aIID.Equals(NS_GET_IID(nsIAuthPrompt)(nsIAuthPrompt::kIID)) ||
628 aIID.Equals(NS_GET_IID(nsIAuthPrompt2)(nsIAuthPrompt2::kIID))) {
629 return NS_SUCCEEDED(GetAuthPrompt(PROMPT_NORMAL, aIID, aSink))((bool)(__builtin_expect(!!(!NS_FAILED_impl(GetAuthPrompt(PROMPT_NORMAL
, aIID, aSink))), 1)))
630 ? NS_OK
631 : NS_NOINTERFACE;
632 } else if (aIID.Equals(NS_GET_IID(nsISHistory)(nsISHistory::kIID))) {
633 // This is deprecated, you should instead directly get
634 // ChildSHistory from the browsing context.
635 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"
")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 636
); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "false"
") (" "Do not try to get a nsISHistory interface from nsIDocShell"
")"); do { MOZ_CrashSequence(__null, 636); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
636 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"
")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 636
); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "false"
") (" "Do not try to get a nsISHistory interface from nsIDocShell"
")"); do { MOZ_CrashSequence(__null, 636); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
637 return NS_NOINTERFACE;
638 } else if (aIID.Equals(NS_GET_IID(nsIWebBrowserFind)(nsIWebBrowserFind::kIID))) {
639 nsresult rv = EnsureFind();
640 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
641 return rv;
642 }
643
644 *aSink = mFind;
645 NS_ADDREF((nsISupports*)*aSink)((nsISupports*)*aSink)->AddRef();
646 return NS_OK;
647 } else if (aIID.Equals(NS_GET_IID(nsISelectionDisplay)(nsISelectionDisplay::kIID))) {
648 if (PresShell* presShell = GetPresShell()) {
649 return presShell->QueryInterface(aIID, aSink);
650 }
651 } else if (aIID.Equals(NS_GET_IID(nsIDocShellTreeOwner)(nsIDocShellTreeOwner::kIID))) {
652 nsCOMPtr<nsIDocShellTreeOwner> treeOwner;
653 nsresult rv = GetTreeOwner(getter_AddRefs(treeOwner));
654 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && treeOwner) {
655 return treeOwner->QueryInterface(aIID, aSink);
656 }
657 } else if (aIID.Equals(NS_GET_IID(nsIBrowserChild)(nsIBrowserChild::kIID))) {
658 *aSink = GetBrowserChild().take();
659 return *aSink ? NS_OK : NS_ERROR_FAILURE;
660 } else {
661 return nsDocLoader::GetInterface(aIID, aSink);
662 }
663
664 NS_IF_ADDREF(((nsISupports*)*aSink))ns_if_addref(((nsISupports*)*aSink));
665 return *aSink ? NS_OK : NS_NOINTERFACE;
666}
667
668NS_IMETHODIMPnsresult
669nsDocShell::SetCancelContentJSEpoch(int32_t aEpoch) {
670 // Note: this gets called fairly early (before a pageload actually starts).
671 // We could probably defer this even longer.
672 nsCOMPtr<nsIBrowserChild> browserChild = GetBrowserChild();
673 static_cast<BrowserChild*>(browserChild.get())
674 ->SetCancelContentJSEpoch(aEpoch);
675 return NS_OK;
676}
677
678nsresult nsDocShell::CheckDisallowedJavascriptLoad(
679 nsDocShellLoadState* aLoadState) {
680 if (!aLoadState->URI()->SchemeIs("javascript")) {
681 return NS_OK;
682 }
683
684 if (nsCOMPtr<nsIPrincipal> targetPrincipal =
685 GetInheritedPrincipal(/* aConsiderCurrentDocument */ true)) {
686 if (!aLoadState->TriggeringPrincipal()->Subsumes(targetPrincipal)) {
687 return NS_ERROR_DOM_BAD_CROSS_ORIGIN_URI;
688 }
689 return NS_OK;
690 }
691 return NS_ERROR_DOM_BAD_CROSS_ORIGIN_URI;
692}
693
694NS_IMETHODIMPnsresult
695nsDocShell::LoadURI(nsDocShellLoadState* aLoadState, bool aSetNavigating) {
696 return LoadURI(aLoadState, aSetNavigating, false);
697}
698
699nsresult nsDocShell::LoadURI(nsDocShellLoadState* aLoadState,
700 bool aSetNavigating,
701 bool aContinueHandlingSubframeHistory) {
702 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!"
")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 702
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState" ") ("
"Must have a valid load state!" ")"); do { MOZ_CrashSequence
(__null, 702); __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
703 // NOTE: This comparison between what appears to be internal/external load
704 // flags is intentional, as it's ensuring that the caller isn't using any of
705 // the flags reserved for implementations by the `nsIWebNavigation` interface.
706 // In the future, this check may be dropped.
707 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" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 709); AnnotateMozCrashReason("MOZ_ASSERT" "(" "(aLoadState->LoadFlags() & INTERNAL_LOAD_FLAGS_LOADURI_SETUP_FLAGS) == 0"
") (" "Should not have these flags set" ")"); do { MOZ_CrashSequence
(__null, 709); __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
708 (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" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 709); AnnotateMozCrashReason("MOZ_ASSERT" "(" "(aLoadState->LoadFlags() & INTERNAL_LOAD_FLAGS_LOADURI_SETUP_FLAGS) == 0"
") (" "Should not have these flags set" ")"); do { MOZ_CrashSequence
(__null, 709); __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
709 "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" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 709); AnnotateMozCrashReason("MOZ_ASSERT" "(" "(aLoadState->LoadFlags() & INTERNAL_LOAD_FLAGS_LOADURI_SETUP_FLAGS) == 0"
") (" "Should not have these flags set" ")"); do { MOZ_CrashSequence
(__null, 709); __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
710 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" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 711); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->TargetBrowsingContext().IsNull()"
") (" "Targeting doesn't occur until InternalLoad" ")"); do {
MOZ_CrashSequence(__null, 711); __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
711 "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" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 711); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->TargetBrowsingContext().IsNull()"
") (" "Targeting doesn't occur until InternalLoad" ")"); do {
MOZ_CrashSequence(__null, 711); __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
;
712
713 if (!aLoadState->TriggeringPrincipal()) {
714 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"
")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 714
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") (" "LoadURI must have a triggering principal"
")"); do { MOZ_CrashSequence(__null, 714); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
715 return NS_ERROR_FAILURE;
716 }
717
718 MOZ_TRY(CheckDisallowedJavascriptLoad(aLoadState))__extension__({ auto mozTryVarTempResult = ::mozilla::ToResult
(CheckDisallowedJavascriptLoad(aLoadState)); if ((__builtin_expect
(!!(mozTryVarTempResult.isErr()), 0))) { return mozTryVarTempResult
.propagateErr(); } mozTryVarTempResult.unwrap(); })
;
719
720 bool oldIsNavigating = mIsNavigating;
721 auto cleanupIsNavigating =
722 MakeScopeExit([&]() { mIsNavigating = oldIsNavigating; });
723 if (aSetNavigating) {
724 mIsNavigating = true;
725 }
726
727 PopupBlocker::PopupControlState popupState = PopupBlocker::openOverridden;
728 if (aLoadState->HasLoadFlags(LOAD_FLAGS_ALLOW_POPUPS)) {
729 popupState = PopupBlocker::openAllowed;
730 // If we allow popups as part of the navigation, ensure we fake a user
731 // interaction, so that popups can, in fact, be allowed to open.
732 if (WindowContext* wc = mBrowsingContext->GetCurrentWindowContext()) {
733 wc->NotifyUserGestureActivation();
734 }
735 }
736
737 AutoPopupStatePusherAutoPopupStatePusherInternal statePusher(popupState);
738
739 if (aLoadState->GetCancelContentJSEpoch().isSome()) {
740 SetCancelContentJSEpoch(*aLoadState->GetCancelContentJSEpoch());
741 }
742
743 // Note: we allow loads to get through here even if mFiredUnloadEvent is
744 // true; that case will get handled in LoadInternal or LoadHistoryEntry,
745 // so we pass false as the second parameter to IsNavigationAllowed.
746 // However, we don't allow the page to change location *in the middle of*
747 // firing beforeunload, so we do need to check if *beforeunload* is currently
748 // firing, so we call IsNavigationAllowed rather than just IsPrintingOrPP.
749 if (!IsNavigationAllowed(true, false)) {
750 return NS_OK; // JS may not handle returning of an error code
751 }
752
753 nsLoadFlags defaultLoadFlags = mBrowsingContext->GetDefaultLoadFlags();
754 if (aLoadState->HasLoadFlags(LOAD_FLAGS_FORCE_TRR)) {
755 defaultLoadFlags |= nsIRequest::LOAD_TRR_ONLY_MODE;
756 } else if (aLoadState->HasLoadFlags(LOAD_FLAGS_DISABLE_TRR)) {
757 defaultLoadFlags |= nsIRequest::LOAD_TRR_DISABLED_MODE;
758 }
759
760 MOZ_ALWAYS_SUCCEEDS(mBrowsingContext->SetDefaultLoadFlags(defaultLoadFlags))do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(mBrowsingContext->SetDefaultLoadFlags(defaultLoadFlags)))
, 1)))), 1))) { } else { do { do { } while (false); MOZ_ReportCrash
("" "NS_SUCCEEDED(mBrowsingContext->SetDefaultLoadFlags(defaultLoadFlags))"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 760); AnnotateMozCrashReason
("MOZ_CRASH(" "NS_SUCCEEDED(mBrowsingContext->SetDefaultLoadFlags(defaultLoadFlags))"
")"); do { MOZ_CrashSequence(__null, 760); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
;
761
762 if (!StartupTimeline::HasRecord(StartupTimeline::FIRST_LOAD_URI) &&
763 mItemType == typeContent && !NS_IsAboutBlank(aLoadState->URI())) {
764 StartupTimeline::RecordOnce(StartupTimeline::FIRST_LOAD_URI);
765 }
766
767 // LoadType used to be set to a default value here, if no LoadInfo/LoadState
768 // object was passed in. That functionality has been removed as of bug
769 // 1492648. LoadType should now be set up by the caller at the time they
770 // create their nsDocShellLoadState object to pass into LoadURI.
771
772 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)
773 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)
774 ("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)
775 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)
;
776
777 if ((!aLoadState->LoadIsFromSessionHistory() &&
778 !LOAD_TYPE_HAS_FLAGS(aLoadState->LoadType(),((aLoadState->LoadType()) & ((LOAD_FLAGS_REPLACE_HISTORY
) << 16))
779 LOAD_FLAGS_REPLACE_HISTORY)((aLoadState->LoadType()) & ((LOAD_FLAGS_REPLACE_HISTORY
) << 16))
) ||
780 aContinueHandlingSubframeHistory) {
781 // This is possibly a subframe, so handle it accordingly.
782 //
783 // If history exists, it will be loaded into the aLoadState object, and the
784 // LoadType will be changed.
785 if (MaybeHandleSubframeHistory(aLoadState,
786 aContinueHandlingSubframeHistory)) {
787 // MaybeHandleSubframeHistory returns true if we need to continue loading
788 // asynchronously.
789 return NS_OK;
790 }
791 }
792
793 if (aLoadState->LoadIsFromSessionHistory()) {
794 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)
795 ("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)
;
796
797 if (!mozilla::SessionHistoryInParent()) {
798 nsCOMPtr<nsISHEntry> entry = aLoadState->SHEntry();
799 return LoadHistoryEntry(entry, aLoadState->LoadType(),
800 aLoadState->HasValidUserGestureActivation());
801 }
802
803 // FIXME Null check aLoadState->GetLoadingSessionHistoryInfo()?
804 return LoadHistoryEntry(*aLoadState->GetLoadingSessionHistoryInfo(),
805 aLoadState->LoadType(),
806 aLoadState->HasValidUserGestureActivation());
807 }
808
809 // On history navigation via Back/Forward buttons, don't execute
810 // automatic JavaScript redirection such as |location.href = ...| or
811 // |window.open()|
812 //
813 // LOAD_NORMAL: window.open(...) etc.
814 // LOAD_STOP_CONTENT: location.href = ..., location.assign(...)
815 if ((aLoadState->LoadType() == LOAD_NORMAL ||
816 aLoadState->LoadType() == LOAD_STOP_CONTENT) &&
817 ShouldBlockLoadingForBackButton()) {
818 return NS_OK;
819 }
820
821 BrowsingContext::Type bcType = mBrowsingContext->GetType();
822
823 // Set up the inheriting principal in LoadState.
824 nsresult rv = aLoadState->SetupInheritingPrincipal(
825 bcType, mBrowsingContext->OriginAttributesRef());
826 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, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 826); return rv; } } while (false)
;
827
828 rv = aLoadState->SetupTriggeringPrincipal(
829 mBrowsingContext->OriginAttributesRef());
830 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, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 830); return rv; } } while (false)
;
831
832 aLoadState->CalculateLoadURIFlags();
833
834 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"
")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 835
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->TypeHint().IsVoid()"
") (" "Typehint should be null when calling InternalLoad from LoadURI"
")"); do { MOZ_CrashSequence(__null, 835); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
835 "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"
")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 835
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->TypeHint().IsVoid()"
") (" "Typehint should be null when calling InternalLoad from LoadURI"
")"); do { MOZ_CrashSequence(__null, 835); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
836 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"
")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 837
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->FileName().IsVoid()"
") (" "FileName should be null when calling InternalLoad from LoadURI"
")"); do { MOZ_CrashSequence(__null, 837); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
837 "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"
")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 837
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->FileName().IsVoid()"
") (" "FileName should be null when calling InternalLoad from LoadURI"
")"); do { MOZ_CrashSequence(__null, 837); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
838 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" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 840); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aLoadState->LoadIsFromSessionHistory()"
") (" "Shouldn't be loading from an entry when calling InternalLoad "
"from LoadURI" ")"); do { MOZ_CrashSequence(__null, 840); __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
839 "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" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 840); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aLoadState->LoadIsFromSessionHistory()"
") (" "Shouldn't be loading from an entry when calling InternalLoad "
"from LoadURI" ")"); do { MOZ_CrashSequence(__null, 840); __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
840 "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" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 840); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aLoadState->LoadIsFromSessionHistory()"
") (" "Shouldn't be loading from an entry when calling InternalLoad "
"from LoadURI" ")"); do { MOZ_CrashSequence(__null, 840); __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
;
841
842 // If we have a system triggering principal, we can assume that this load was
843 // triggered by some UI in the browser chrome, such as the URL bar or
844 // bookmark bar. This should count as a user interaction for the current sh
845 // entry, so that the user may navigate back to the current entry, from the
846 // entry that is going to be added as part of this load.
847 nsCOMPtr<nsIPrincipal> triggeringPrincipal =
848 aLoadState->TriggeringPrincipal();
849 if (triggeringPrincipal && triggeringPrincipal->IsSystemPrincipal()) {
850 if (mozilla::SessionHistoryInParent()) {
851 WindowContext* topWc = mBrowsingContext->GetTopWindowContext();
852 if (topWc && !topWc->IsDiscarded()) {
853 MOZ_ALWAYS_SUCCEEDS(topWc->SetSHEntryHasUserInteraction(true))do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(topWc->SetSHEntryHasUserInteraction(true))), 1)))), 1))) {
} else { do { do { } while (false); MOZ_ReportCrash("" "NS_SUCCEEDED(topWc->SetSHEntryHasUserInteraction(true))"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 853); AnnotateMozCrashReason
("MOZ_CRASH(" "NS_SUCCEEDED(topWc->SetSHEntryHasUserInteraction(true))"
")"); do { MOZ_CrashSequence(__null, 853); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
;
854 }
855 } else {
856 bool oshe = false;
857 nsCOMPtr<nsISHEntry> currentSHEntry;
858 GetCurrentSHEntry(getter_AddRefs(currentSHEntry), &oshe);
859 if (currentSHEntry) {
860 currentSHEntry->SetHasUserInteraction(true);
861 }
862 }
863 }
864
865 rv = InternalLoad(aLoadState);
866 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, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 866); return rv; } } while (false)
;
867
868 if (aLoadState->GetOriginalURIString().isSome()) {
869 // Save URI string in case it's needed later when
870 // sending to search engine service in EndPageLoad()
871 mOriginalUriString = *aLoadState->GetOriginalURIString();
872 }
873
874 return NS_OK;
875}
876
877bool nsDocShell::IsLoadingFromSessionHistory() {
878 return mActiveEntryIsLoadingFromSessionHistory;
879}
880
881// StopDetector is modeled similarly to OnloadBlocker; it is a rather
882// dummy nsIRequest implementation which can be added to an nsILoadGroup to
883// detect Cancel calls.
884class StopDetector final : public nsIRequest {
885 public:
886 StopDetector() = default;
887
888 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:
889 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;
890
891 bool Canceled() { return mCanceled; }
892
893 private:
894 ~StopDetector() = default;
895
896 bool mCanceled = false;
897};
898
899NS_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" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 899); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { MOZ_CrashSequence(__null, 899
); __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" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 899); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"StopDetector\" != nullptr"
") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__null
, 899); __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" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 899); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { MOZ_CrashSequence(__null, 899
); __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" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 899); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"StopDetector\" != nullptr"
") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__null
, 899); __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", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 899); MOZ_PretendNoReturn(); } } while (0); nsresult rv = NS_ERROR_FAILURE
; static_assert(1 > 0, "Need more arguments to NS_INTERFACE_TABLE"
); static const QITableEntry table[] = { {&mozilla::detail
::kImplementedIID<StopDetector, nsIRequest>, int32_t( reinterpret_cast
<char*>(static_cast<nsIRequest*>((StopDetector*)0x1000
)) - reinterpret_cast<char*>((StopDetector*)0x1000))}, {
&mozilla::detail::kImplementedIID<StopDetector, nsISupports
>, int32_t(reinterpret_cast<char*>(static_cast<nsISupports
*>( static_cast<nsIRequest*>((StopDetector*)0x1000))
) - reinterpret_cast<char*>((StopDetector*)0x1000))}, {
nullptr, 0 } } ; static_assert(std::size(table) > 1, "need at least 1 interface"
); rv = NS_TableDrivenQI(static_cast<void*>(this), aIID
, aInstancePtr, table); return rv; }
900
901NS_IMETHODIMPnsresult
902StopDetector::GetName(nsACString& aResult) {
903 aResult.AssignLiteral("about:stop-detector");
904 return NS_OK;
905}
906
907NS_IMETHODIMPnsresult
908StopDetector::IsPending(bool* aRetVal) {
909 *aRetVal = true;
910 return NS_OK;
911}
912
913NS_IMETHODIMPnsresult
914StopDetector::GetStatus(nsresult* aStatus) {
915 *aStatus = NS_OK;
916 return NS_OK;
917}
918
919NS_IMETHODIMPnsresult StopDetector::SetCanceledReason(const nsACString& aReason) {
920 return SetCanceledReasonImpl(aReason);
921}
922
923NS_IMETHODIMPnsresult StopDetector::GetCanceledReason(nsACString& aReason) {
924 return GetCanceledReasonImpl(aReason);
925}
926
927NS_IMETHODIMPnsresult StopDetector::CancelWithReason(nsresult aStatus,
928 const nsACString& aReason) {
929 return CancelWithReasonImpl(aStatus, aReason);
930}
931
932NS_IMETHODIMPnsresult
933StopDetector::Cancel(nsresult aStatus) {
934 mCanceled = true;
935 return NS_OK;
936}
937
938NS_IMETHODIMPnsresult
939StopDetector::Suspend(void) { return NS_OK; }
940NS_IMETHODIMPnsresult
941StopDetector::Resume(void) { return NS_OK; }
942
943NS_IMETHODIMPnsresult
944StopDetector::GetLoadGroup(nsILoadGroup** aLoadGroup) {
945 *aLoadGroup = nullptr;
946 return NS_OK;
947}
948
949NS_IMETHODIMPnsresult
950StopDetector::SetLoadGroup(nsILoadGroup* aLoadGroup) { return NS_OK; }
951
952NS_IMETHODIMPnsresult
953StopDetector::GetLoadFlags(nsLoadFlags* aLoadFlags) {
954 *aLoadFlags = nsIRequest::LOAD_NORMAL;
955 return NS_OK;
956}
957
958NS_IMETHODIMPnsresult
959StopDetector::GetTRRMode(nsIRequest::TRRMode* aTRRMode) {
960 return GetTRRModeImpl(aTRRMode);
961}
962
963NS_IMETHODIMPnsresult
964StopDetector::SetTRRMode(nsIRequest::TRRMode aTRRMode) {
965 return SetTRRModeImpl(aTRRMode);
966}
967
968NS_IMETHODIMPnsresult
969StopDetector::SetLoadFlags(nsLoadFlags aLoadFlags) { return NS_OK; }
970
971bool nsDocShell::MaybeHandleSubframeHistory(
972 nsDocShellLoadState* aLoadState, bool aContinueHandlingSubframeHistory) {
973 // First, verify if this is a subframe.
974 // Note, it is ok to rely on docshell here and not browsing context since when
975 // an iframe is created, it has first in-process docshell.
976 nsCOMPtr<nsIDocShellTreeItem> parentAsItem;
977 GetInProcessSameTypeParent(getter_AddRefs(parentAsItem));
978 nsCOMPtr<nsIDocShell> parentDS(do_QueryInterface(parentAsItem));
979
980 if (!parentDS || parentDS == static_cast<nsIDocShell*>(this)) {
981 if (mBrowsingContext && mBrowsingContext->IsTop()) {
982 // This is the root docshell. If we got here while
983 // executing an onLoad Handler,this load will not go
984 // into session history.
985 // XXX Why is this code in a method which deals with iframes!
986 if (aLoadState->IsFormSubmission()) {
987#ifdef DEBUG1
988 if (!mEODForCurrentDocument) {
989 const MaybeDiscarded<BrowsingContext>& targetBC =
990 aLoadState->TargetBrowsingContext();
991 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", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 992); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->LoadType() == LOAD_NORMAL_REPLACE"
")"); do { MOZ_CrashSequence(__null, 992); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
992 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", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 992); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->LoadType() == LOAD_NORMAL_REPLACE"
")"); do { MOZ_CrashSequence(__null, 992); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
993 }
994#endif
995 } else {
996 bool inOnLoadHandler = false;
997 GetIsExecutingOnLoadHandler(&inOnLoadHandler);
998 if (inOnLoadHandler) {
999 aLoadState->SetLoadType(LOAD_NORMAL_REPLACE);
1000 }
1001 }
1002 }
1003 return false;
1004 }
1005
1006 /* OK. It is a subframe. Checkout the parent's loadtype. If the parent was
1007 * loaded through a history mechanism, then get the SH entry for the child
1008 * from the parent. This is done to restore frameset navigation while going
1009 * back/forward. If the parent was loaded through any other loadType, set the
1010 * child's loadType too accordingly, so that session history does not get
1011 * confused.
1012 */
1013
1014 // Get the parent's load type
1015 uint32_t parentLoadType;
1016 parentDS->GetLoadType(&parentLoadType);
1017
1018 if (!aContinueHandlingSubframeHistory) {
1019 if (mozilla::SessionHistoryInParent()) {
1020 if (nsDocShell::Cast(parentDS.get())->IsLoadingFromSessionHistory() &&
1021 !GetCreatedDynamically()) {
1022 if (XRE_IsContentProcess()) {
1023 dom::ContentChild* contentChild = dom::ContentChild::GetSingleton();
1024 nsCOMPtr<nsILoadGroup> loadGroup;
1025 GetLoadGroup(getter_AddRefs(loadGroup));
1026 if (contentChild && loadGroup && !mCheckingSessionHistory) {
1027 RefPtr<Document> parentDoc = parentDS->GetDocument();
1028 parentDoc->BlockOnload();
1029 RefPtr<BrowsingContext> browsingContext = mBrowsingContext;
1030 Maybe<uint64_t> currentLoadIdentifier =
1031 mBrowsingContext->GetCurrentLoadIdentifier();
1032 RefPtr<nsDocShellLoadState> loadState = aLoadState;
1033 bool isNavigating = mIsNavigating;
1034 RefPtr<StopDetector> stopDetector = new StopDetector();
1035 loadGroup->AddRequest(stopDetector, nullptr);
1036 // Need to set mCheckingSessionHistory so that
1037 // GetIsAttemptingToNavigate() returns true.
1038 mCheckingSessionHistory = true;
1039
1040 auto resolve =
1041 [currentLoadIdentifier, browsingContext, parentDoc, loadState,
1042 isNavigating, loadGroup, stopDetector](
1043 mozilla::Maybe<LoadingSessionHistoryInfo>&& aResult) {
1044 RefPtr<nsDocShell> docShell =
1045 static_cast<nsDocShell*>(browsingContext->GetDocShell());
1046 auto unblockParent = MakeScopeExit(
1047 [loadGroup, stopDetector, parentDoc, docShell]() {
1048 if (docShell) {
1049 docShell->mCheckingSessionHistory = false;
1050 }
1051 loadGroup->RemoveRequest(stopDetector, nullptr, NS_OK);
1052 parentDoc->UnblockOnload(false);
1053 });
1054
1055 if (!docShell || !docShell->mCheckingSessionHistory) {
1056 return;
1057 }
1058
1059 if (stopDetector->Canceled()) {
1060 return;
1061 }
1062 if (currentLoadIdentifier ==
1063 browsingContext->GetCurrentLoadIdentifier() &&
1064 aResult.isSome()) {
1065 loadState->SetLoadingSessionHistoryInfo(aResult.value());
1066 // This is an initial subframe load from the session
1067 // history, index doesn't need to be updated.
1068 loadState->SetLoadIsFromSessionHistory(0, false);
1069 }
1070
1071 // We got the results back from the parent process, call
1072 // LoadURI again with the possibly updated data.
1073 docShell->LoadURI(loadState, isNavigating, true);
1074 };
1075 auto reject = [loadGroup, stopDetector, browsingContext,
1076 parentDoc](mozilla::ipc::ResponseRejectReason) {
1077 RefPtr<nsDocShell> docShell =
1078 static_cast<nsDocShell*>(browsingContext->GetDocShell());
1079 if (docShell) {
1080 docShell->mCheckingSessionHistory = false;
1081 }
1082 // In practise reject shouldn't be called ever.
1083 loadGroup->RemoveRequest(stopDetector, nullptr, NS_OK);
1084 parentDoc->UnblockOnload(false);
1085 };
1086 contentChild->SendGetLoadingSessionHistoryInfoFromParent(
1087 mBrowsingContext, std::move(resolve), std::move(reject));
1088 return true;
1089 }
1090 } else {
1091 Maybe<LoadingSessionHistoryInfo> info;
1092 mBrowsingContext->Canonical()->GetLoadingSessionHistoryInfoFromParent(
1093 info);
1094 if (info.isSome()) {
1095 aLoadState->SetLoadingSessionHistoryInfo(info.value());
1096 // This is an initial subframe load from the session
1097 // history, index doesn't need to be updated.
1098 aLoadState->SetLoadIsFromSessionHistory(0, false);
1099 }
1100 }
1101 }
1102 } else {
1103 // Get the ShEntry for the child from the parent
1104 nsCOMPtr<nsISHEntry> currentSH;
1105 bool oshe = false;
1106 parentDS->GetCurrentSHEntry(getter_AddRefs(currentSH), &oshe);
1107 bool dynamicallyAddedChild = GetCreatedDynamically();
1108
1109 if (!dynamicallyAddedChild && !oshe && currentSH) {
1110 // Only use the old SHEntry, if we're sure enough that
1111 // it wasn't originally for some other frame.
1112 nsCOMPtr<nsISHEntry> shEntry;
1113 currentSH->GetChildSHEntryIfHasNoDynamicallyAddedChild(
1114 mBrowsingContext->ChildOffset(), getter_AddRefs(shEntry));
1115 if (shEntry) {
1116 aLoadState->SetSHEntry(shEntry);
1117 }
1118 }
1119 }
1120 }
1121
1122 // Make some decisions on the child frame's loadType based on the
1123 // parent's loadType, if the subframe hasn't loaded anything into it.
1124 //
1125 // In some cases privileged scripts may try to get the DOMWindow
1126 // reference of this docshell before the loading starts, causing the
1127 // initial about:blank content viewer being created and mCurrentURI being
1128 // set. To handle this case we check if mCurrentURI is about:blank and
1129 // currentSHEntry is null.
1130 bool oshe = false;
1131 nsCOMPtr<nsISHEntry> currentChildEntry;
1132 GetCurrentSHEntry(getter_AddRefs(currentChildEntry), &oshe);
1133
1134 if (mCurrentURI && (!NS_IsAboutBlank(mCurrentURI) || currentChildEntry ||
1135 mLoadingEntry || mActiveEntry)) {
1136 // This is a pre-existing subframe. If
1137 // 1. The load of this frame was not originally initiated by session
1138 // history directly (i.e. (!shEntry) condition succeeded, but it can
1139 // still be a history load on parent which causes this frame being
1140 // loaded), which we checked with the above assert, and
1141 // 2. mCurrentURI is not null, nor the initial about:blank,
1142 // it is possible that a parent's onLoadHandler or even self's
1143 // onLoadHandler is loading a new page in this child. Check parent's and
1144 // self's busy flag and if it is set, we don't want this onLoadHandler
1145 // load to get in to session history.
1146 BusyFlags parentBusy = parentDS->GetBusyFlags();
1147 BusyFlags selfBusy = GetBusyFlags();
1148
1149 if (parentBusy & BUSY_FLAGS_BUSY || selfBusy & BUSY_FLAGS_BUSY) {
1150 aLoadState->SetLoadType(LOAD_NORMAL_REPLACE);
1151 aLoadState->ClearLoadIsFromSessionHistory();
1152 }
1153 return false;
1154 }
1155
1156 // This is a newly created frame. Check for exception cases first.
1157 // By default the subframe will inherit the parent's loadType.
1158 if (aLoadState->LoadIsFromSessionHistory() &&
1159 (parentLoadType == LOAD_NORMAL || parentLoadType == LOAD_LINK)) {
1160 // The parent was loaded normally. In this case, this *brand new*
1161 // child really shouldn't have a SHEntry. If it does, it could be
1162 // because the parent is replacing an existing frame with a new frame,
1163 // in the onLoadHandler. We don't want this url to get into session
1164 // history. Clear off shEntry, and set load type to
1165 // LOAD_BYPASS_HISTORY.
1166 bool inOnLoadHandler = false;
1167 parentDS->GetIsExecutingOnLoadHandler(&inOnLoadHandler);
1168 if (inOnLoadHandler) {
1169 aLoadState->SetLoadType(LOAD_NORMAL_REPLACE);
1170 aLoadState->ClearLoadIsFromSessionHistory();
1171 }
1172 } else if (parentLoadType == LOAD_REFRESH) {
1173 // Clear shEntry. For refresh loads, we have to load
1174 // what comes through the pipe, not what's in history.
1175 aLoadState->ClearLoadIsFromSessionHistory();
1176 } else if ((parentLoadType == LOAD_BYPASS_HISTORY) ||
1177 (aLoadState->LoadIsFromSessionHistory() &&
1178 ((parentLoadType & LOAD_CMD_HISTORY) ||
1179 (parentLoadType == LOAD_RELOAD_NORMAL) ||
1180 (parentLoadType == LOAD_RELOAD_CHARSET_CHANGE) ||
1181 (parentLoadType == LOAD_RELOAD_CHARSET_CHANGE_BYPASS_CACHE) ||
1182 (parentLoadType ==
1183 LOAD_RELOAD_CHARSET_CHANGE_BYPASS_PROXY_AND_CACHE)))) {
1184 // If the parent url, bypassed history or was loaded from
1185 // history, pass on the parent's loadType to the new child
1186 // frame too, so that the child frame will also
1187 // avoid getting into history.
1188 aLoadState->SetLoadType(parentLoadType);
1189 } else if (parentLoadType == LOAD_ERROR_PAGE) {
1190 // If the parent document is an error page, we don't
1191 // want to update global/session history. However,
1192 // this child frame is not an error page.
1193 aLoadState->SetLoadType(LOAD_BYPASS_HISTORY);
1194 } else if ((parentLoadType == LOAD_RELOAD_BYPASS_CACHE) ||
1195 (parentLoadType == LOAD_RELOAD_BYPASS_PROXY) ||
1196 (parentLoadType == LOAD_RELOAD_BYPASS_PROXY_AND_CACHE)) {
1197 // the new frame should inherit the parent's load type so that it also
1198 // bypasses the cache and/or proxy
1199 aLoadState->SetLoadType(parentLoadType);
1200 }
1201
1202 return false;
1203}
1204
1205/*
1206 * Reset state to a new content model within the current document and the
1207 * document viewer. Called by the document before initiating an out of band
1208 * document.write().
1209 */
1210NS_IMETHODIMPnsresult
1211nsDocShell::PrepareForNewContentModel() {
1212 // Clear out our form control state, because the state of controls
1213 // in the pre-open() document should not affect the state of
1214 // controls that are now going to be written.
1215 SetLayoutHistoryState(nullptr);
1216 mEODForCurrentDocument = false;
1217 return NS_OK;
1218}
1219
1220NS_IMETHODIMPnsresult
1221nsDocShell::FirePageHideNotification(bool aIsUnload) {
1222 FirePageHideNotificationInternal(aIsUnload, false);
1223 return NS_OK;
1224}
1225
1226void nsDocShell::FirePageHideNotificationInternal(
1227 bool aIsUnload, bool aSkipCheckingDynEntries) {
1228 if (mDocumentViewer && !mFiredUnloadEvent) {
1229 // Keep an explicit reference since calling PageHide could release
1230 // mDocumentViewer
1231 nsCOMPtr<nsIDocumentViewer> viewer(mDocumentViewer);
1232 mFiredUnloadEvent = true;
1233
1234 if (mTiming) {
1235 mTiming->NotifyUnloadEventStart();
1236 }
1237
1238 viewer->PageHide(aIsUnload);
1239
1240 if (mTiming) {
1241 mTiming->NotifyUnloadEventEnd();
1242 }
1243
1244 AutoTArray<nsCOMPtr<nsIDocShell>, 8> kids;
1245 uint32_t n = mChildList.Length();
1246 kids.SetCapacity(n);
1247 for (uint32_t i = 0; i < n; i++) {
1248 kids.AppendElement(do_QueryInterface(ChildAt(i)));
1249 }
1250
1251 n = kids.Length();
1252 for (uint32_t i = 0; i < n; ++i) {
1253 RefPtr<nsDocShell> child = static_cast<nsDocShell*>(kids[i].get());
1254 if (child) {
1255 // Skip checking dynamic subframe entries in our children.
1256 child->FirePageHideNotificationInternal(aIsUnload, true);
1257 }
1258 }
1259
1260 // If the document is unloading, remove all dynamic subframe entries.
1261 if (aIsUnload && !aSkipCheckingDynEntries) {
1262 RefPtr<ChildSHistory> rootSH = GetRootSessionHistory();
1263 if (rootSH) {
1264 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)
1265 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)
1266 ("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)
;
1267 if (mozilla::SessionHistoryInParent()) {
1268 if (mActiveEntry) {
1269 mBrowsingContext->RemoveDynEntriesFromActiveSessionHistoryEntry();
1270 }
1271 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)
1272 ("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)
;
1273 } else if (mOSHE) {
1274 int32_t index = rootSH->Index();
1275 rootSH->LegacySHistory()->RemoveDynEntries(index, mOSHE);
1276 }
1277 }
1278 }
1279
1280 // Now make sure our editor, if any, is detached before we go
1281 // any farther.
1282 DetachEditorFromWindow();
1283 }
1284}
1285
1286void nsDocShell::ThawFreezeNonRecursive(bool aThaw) {
1287 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()"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 1287); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "mozilla::BFCacheInParent()" ")"); do { MOZ_CrashSequence
(__null, 1287); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
1288
1289 if (!mScriptGlobal) {
1290 return;
1291 }
1292
1293 if (RefPtr<nsGlobalWindowInner> inner =
1294 nsGlobalWindowInner::Cast(mScriptGlobal->GetCurrentInnerWindow())) {
1295 if (aThaw) {
1296 inner->Thaw(false);
1297 } else {
1298 inner->Freeze(false);
1299 }
1300 }
1301}
1302
1303void nsDocShell::FirePageHideShowNonRecursive(bool aShow) {
1304 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()"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 1304); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "mozilla::BFCacheInParent()" ")"); do { MOZ_CrashSequence
(__null, 1304); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
1305
1306 if (!mDocumentViewer) {
1307 return;
1308 }
1309
1310 // Emulate what non-SHIP BFCache does too. In pageshow case
1311 // add and remove a request and before that call SetCurrentURI to get
1312 // the location change notification.
1313 // For pagehide, set mFiredUnloadEvent to true, so that unload doesn't fire.
1314 nsCOMPtr<nsIDocumentViewer> viewer(mDocumentViewer);
1315 if (aShow) {
1316 viewer->SetIsHidden(false);
1317 mRefreshURIList = std::move(mBFCachedRefreshURIList);
1318 RefreshURIFromQueue();
1319 mFiredUnloadEvent = false;
1320 RefPtr<Document> doc = viewer->GetDocument();
1321 if (doc) {
1322 doc->NotifyActivityChanged();
1323 nsCOMPtr<nsPIDOMWindowInner> inner =
1324 mScriptGlobal ? mScriptGlobal->GetCurrentInnerWindow() : nullptr;
1325 if (mBrowsingContext->IsTop()) {
1326 doc->NotifyPossibleTitleChange(false);
1327 doc->SetLoadingOrRestoredFromBFCacheTimeStampToNow();
1328 if (inner) {
1329 // Now that we have found the inner window of the page restored
1330 // from the history, we have to make sure that
1331 // performance.navigation.type is 2.
1332 // Traditionally this type change has been done to the top level page
1333 // only.
1334 Performance* performance = inner->GetPerformance();
1335 if (performance) {
1336 performance->GetDOMTiming()->NotifyRestoreStart();
1337 }
1338 }
1339 }
1340
1341 nsCOMPtr<nsIChannel> channel = doc->GetChannel();
1342 if (channel) {
1343 SetLoadType(LOAD_HISTORY);
1344 mEODForCurrentDocument = false;
1345 mIsRestoringDocument = true;
1346 mLoadGroup->AddRequest(channel, nullptr);
1347 nsCOMPtr<nsIURI> uri;
1348 if (doc->FragmentDirective()) {
1349 // If we have fragment directives, then we've mutated the document
1350 // uri. Set the current URI from session history instead.
1351 if (mozilla::SessionHistoryInParent()) {
1352 uri = mActiveEntry ? mActiveEntry->GetURI() : nullptr;
1353 } else if (mOSHE) {
1354 uri = mOSHE->GetURI();
1355 }
1356 }
1357 if (!uri) {
1358 uri = doc->GetDocumentURI();
1359 }
1360 SetCurrentURI(uri, channel,
1361 /* aFireOnLocationChange */ true,
1362 /* aIsInitialAboutBlank */ false,
1363 /* aLocationFlags */ 0);
1364 mLoadGroup->RemoveRequest(channel, nullptr, NS_OK);
1365 mIsRestoringDocument = false;
1366 }
1367 RefPtr<PresShell> presShell = GetPresShell();
1368 if (presShell) {
1369 presShell->Thaw(false);
1370 }
1371
1372 if (inner) {
1373 inner->FireDelayedDOMEvents(false);
1374 }
1375 }
1376 } else if (!mFiredUnloadEvent) {
1377 // XXXBFCache check again that the page can enter bfcache.
1378 // XXXBFCache should mTiming->NotifyUnloadEventStart()/End() be called here?
1379
1380 if (mRefreshURIList) {
1381 RefreshURIToQueue();
1382 mBFCachedRefreshURIList = std::move(mRefreshURIList);
1383 } else {
1384 // If Stop was called, the list was moved to mSavedRefreshURIList after
1385 // calling SuspendRefreshURIs, which calls RefreshURIToQueue.
1386 mBFCachedRefreshURIList = std::move(mSavedRefreshURIList);
1387 }
1388
1389 mFiredUnloadEvent = true;
1390 viewer->PageHide(false);
1391
1392 RefPtr<PresShell> presShell = GetPresShell();
1393 if (presShell) {
1394 presShell->Freeze(false);
1395 }
1396 }
1397}
1398
1399nsresult nsDocShell::Dispatch(already_AddRefed<nsIRunnable>&& aRunnable) {
1400 nsCOMPtr<nsIRunnable> runnable(aRunnable);
1401 if (NS_WARN_IF(!GetWindow())NS_warn_if_impl(!GetWindow(), "!GetWindow()", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 1401)
) {
1402 // Window should only be unavailable after destroyed.
1403 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"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 1403); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "mIsBeingDestroyed" ")"); do { MOZ_CrashSequence
(__null, 1403); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
1404 return NS_ERROR_FAILURE;
1405 }
1406 return SchedulerGroup::Dispatch(runnable.forget());
1407}
1408
1409NS_IMETHODIMPnsresult
1410nsDocShell::DispatchLocationChangeEvent() {
1411 return Dispatch(NewRunnableMethod("nsDocShell::FireDummyOnLocationChange",
1412 this,
1413 &nsDocShell::FireDummyOnLocationChange));
1414}
1415
1416NS_IMETHODIMPnsresult
1417nsDocShell::StartDelayedAutoplayMediaComponents() {
1418 RefPtr<nsPIDOMWindowOuter> outerWindow = GetWindow();
1419 if (outerWindow) {
1420 outerWindow->ActivateMediaComponents();
1421 }
1422 return NS_OK;
1423}
1424
1425bool nsDocShell::MaybeInitTiming() {
1426 if (mTiming && !mBlankTiming) {
1427 return false;
1428 }
1429
1430 bool canBeReset = false;
1431
1432 if (mScriptGlobal && mBlankTiming) {
1433 nsPIDOMWindowInner* innerWin = mScriptGlobal->GetCurrentInnerWindow();
1434 if (innerWin && innerWin->GetPerformance()) {
1435 mTiming = innerWin->GetPerformance()->GetDOMTiming();
1436 mBlankTiming = false;
1437 }
1438 }
1439
1440 if (!mTiming) {
1441 mTiming = new nsDOMNavigationTiming(this);
1442 canBeReset = true;
1443 }
1444
1445 mTiming->NotifyNavigationStart(
1446 mBrowsingContext->IsActive()
1447 ? nsDOMNavigationTiming::DocShellState::eActive
1448 : nsDOMNavigationTiming::DocShellState::eInactive);
1449
1450 return canBeReset;
1451}
1452
1453void nsDocShell::MaybeResetInitTiming(bool aReset) {
1454 if (aReset) {
1455 mTiming = nullptr;
1456 }
1457}
1458
1459nsDOMNavigationTiming* nsDocShell::GetNavigationTiming() const {
1460 return mTiming;
1461}
1462
1463nsPresContext* nsDocShell::GetEldestPresContext() {
1464 nsIDocumentViewer* viewer = mDocumentViewer;
1465 while (viewer) {
1466 nsIDocumentViewer* prevViewer = viewer->GetPreviousViewer();
1467 if (!prevViewer) {
1468 return viewer->GetPresContext();
1469 }
1470 viewer = prevViewer;
1471 }
1472
1473 return nullptr;
1474}
1475
1476nsPresContext* nsDocShell::GetPresContext() {
1477 if (!mDocumentViewer) {
1478 return nullptr;
1479 }
1480
1481 return mDocumentViewer->GetPresContext();
1482}
1483
1484PresShell* nsDocShell::GetPresShell() {
1485 nsPresContext* presContext = GetPresContext();
1486 return presContext ? presContext->GetPresShell() : nullptr;
1487}
1488
1489PresShell* nsDocShell::GetEldestPresShell() {
1490 nsPresContext* presContext = GetEldestPresContext();
1491
1492 if (presContext) {
1493 return presContext->GetPresShell();
1494 }
1495
1496 return nullptr;
1497}
1498
1499NS_IMETHODIMPnsresult
1500nsDocShell::GetDocViewer(nsIDocumentViewer** aDocumentViewer) {
1501 NS_ENSURE_ARG_POINTER(aDocumentViewer)do { if ((__builtin_expect(!!(!(aDocumentViewer)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aDocumentViewer" ") failed"
, nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 1501); return NS_ERROR_INVALID_POINTER; } } while (false)
;
1502
1503 *aDocumentViewer = mDocumentViewer;
1504 NS_IF_ADDREF(*aDocumentViewer)ns_if_addref(*aDocumentViewer);
1505 return NS_OK;
1506}
1507
1508NS_IMETHODIMPnsresult
1509nsDocShell::GetOuterWindowID(uint64_t* aWindowID) {
1510 *aWindowID = mContentWindowID;
1511 return NS_OK;
1512}
1513
1514NS_IMETHODIMPnsresult
1515nsDocShell::SetChromeEventHandler(EventTarget* aChromeEventHandler) {
1516 mChromeEventHandler = aChromeEventHandler;
1517
1518 if (mScriptGlobal) {
1519 mScriptGlobal->SetChromeEventHandler(mChromeEventHandler);
1520 }
1521
1522 return NS_OK;
1523}
1524
1525NS_IMETHODIMPnsresult
1526nsDocShell::GetChromeEventHandler(EventTarget** aChromeEventHandler) {
1527 NS_ENSURE_ARG_POINTER(aChromeEventHandler)do { if ((__builtin_expect(!!(!(aChromeEventHandler)), 0))) {
NS_DebugBreak(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aChromeEventHandler"
") failed", nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 1527); return NS_ERROR_INVALID_POINTER; } } while (false)
;
1528 RefPtr<EventTarget> handler = mChromeEventHandler;
1529 handler.forget(aChromeEventHandler);
1530 return NS_OK;
1531}
1532
1533NS_IMETHODIMPnsresult
1534nsDocShell::SetCurrentURIForSessionStore(nsIURI* aURI) {
1535 // Note that securityUI will set STATE_IS_INSECURE, even if
1536 // the scheme of |aURI| is "https".
1537 SetCurrentURI(aURI, nullptr,
1538 /* aFireOnLocationChange */
1539 true,
1540 /* aIsInitialAboutBlank */
1541 false,
1542 /* aLocationFlags */
1543 nsIWebProgressListener::LOCATION_CHANGE_SESSION_STORE);
1544 return NS_OK;
1545}
1546
1547bool nsDocShell::SetCurrentURI(nsIURI* aURI, nsIRequest* aRequest,
1548 bool aFireOnLocationChange,
1549 bool aIsInitialAboutBlank,
1550 uint32_t aLocationFlags) {
1551 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"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 1551); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!mIsBeingDestroyed" ")"); do { MOZ_CrashSequence
(__null, 1551); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
1552
1553 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)
1554 ("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)
1555 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)
;
1556
1557 // We don't want to send a location change when we're displaying an error
1558 // page, and we don't want to change our idea of "current URI" either
1559 if (mLoadType == LOAD_ERROR_PAGE) {
1560 return false;
1561 }
1562
1563 bool uriIsEqual = false;
1564 if (!mCurrentURI || !aURI ||
1565 NS_FAILED(mCurrentURI->Equals(aURI, &uriIsEqual))((bool)(__builtin_expect(!!(NS_FAILED_impl(mCurrentURI->Equals
(aURI, &uriIsEqual))), 0)))
|| !uriIsEqual) {
1566 mTitleValidForCurrentURI = false;
1567 }
1568
1569 SetCurrentURIInternal(aURI);
1570
1571#ifdef DEBUG1
1572 mLastOpenedURI = aURI;
1573#endif
1574
1575 if (!NS_IsAboutBlank(mCurrentURI)) {
1576 mHasLoadedNonBlankURI = true;
1577 }
1578
1579 // Don't fire onLocationChange when creating a subframe's initial about:blank
1580 // document, as this can happen when it's not safe for us to run script.
1581 if (aIsInitialAboutBlank && !mHasLoadedNonBlankURI &&
1582 !mBrowsingContext->IsTop()) {
1583 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"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 1583); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!aRequest && aLocationFlags == 0" ")"
); do { MOZ_CrashSequence(__null, 1583); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1584 return false;
1585 }
1586
1587 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()", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 1587); AnnotateMozCrashReason("MOZ_ASSERT" "(" "nsContentUtils::IsSafeToRunScript()"
")"); do { MOZ_CrashSequence(__null, 1587); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1588
1589 if (aFireOnLocationChange) {
1590 FireOnLocationChange(this, aRequest, aURI, aLocationFlags);
1591 }
1592 return !aFireOnLocationChange;
1593}
1594
1595void nsDocShell::SetCurrentURIInternal(nsIURI* aURI) {
1596 mCurrentURI = aURI;
1597 if (mBrowsingContext) {
1598 mBrowsingContext->ClearCachedValuesOfLocations();
1599 }
1600}
1601
1602NS_IMETHODIMPnsresult
1603nsDocShell::GetCharset(nsACString& aCharset) {
1604 aCharset.Truncate();
1605
1606 PresShell* presShell = GetPresShell();
1607 NS_ENSURE_TRUE(presShell, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(presShell)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "presShell" ") failed", nullptr
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 1607); return
NS_ERROR_FAILURE; } } while (false)
;
1608 Document* doc = presShell->GetDocument();
1609 NS_ENSURE_TRUE(doc, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(doc)), 0))) { NS_DebugBreak(NS_DEBUG_WARNING
, "NS_ENSURE_TRUE(" "doc" ") failed", nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 1609); return NS_ERROR_FAILURE; } } while (false)
;
1610 doc->GetDocumentCharacterSet()->Name(aCharset);
1611 return NS_OK;
1612}
1613
1614NS_IMETHODIMPnsresult
1615nsDocShell::ForceEncodingDetection() {
1616 nsCOMPtr<nsIDocumentViewer> viewer;
1617 GetDocViewer(getter_AddRefs(viewer));
1618 if (!viewer) {
1619 return NS_OK;
1620 }
1621
1622 Document* doc = viewer->GetDocument();
1623 if (!doc || doc->WillIgnoreCharsetOverride()) {
1624 return NS_OK;
1625 }
1626
1627 mForcedAutodetection = true;
1628
1629 nsIURI* uri = doc->GetOriginalURI();
1630 bool isFileURL = uri && uri->SchemeIs("file");
1631
1632 int32_t charsetSource = doc->GetDocumentCharacterSetSource();
1633 auto encoding = doc->GetDocumentCharacterSet();
1634 // AsHTMLDocument is valid, because we called
1635 // WillIgnoreCharsetOverride() above.
1636 if (doc->AsHTMLDocument()->IsPlainText()) {
1637 switch (charsetSource) {
1638 case kCharsetFromInitialAutoDetectionASCII:
1639 // Deliberately no final version
1640 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)
;
1641 break;
1642 case kCharsetFromInitialAutoDetectionWouldNotHaveBeenUTF8Generic:
1643 case kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8Generic:
1644 case kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8GenericInitialWasASCII:
1645 case kCharsetFromInitialAutoDetectionWouldNotHaveBeenUTF8Content:
1646 case kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8Content:
1647 case kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8ContentInitialWasASCII:
1648 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)
;
1649 break;
1650 case kCharsetFromInitialAutoDetectionWouldNotHaveBeenUTF8DependedOnTLD:
1651 case kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8DependedOnTLD:
1652 case kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8DependedOnTLDInitialWasASCII:
1653 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)
;
1654 break;
1655 case kCharsetFromInitialAutoDetectionWouldHaveBeenUTF8:
1656 case kCharsetFromFinalAutoDetectionWouldHaveBeenUTF8InitialWasASCII:
1657 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)
;
1658 break;
1659 case kCharsetFromChannel:
1660 if (encoding == UTF_8_ENCODING) {
1661 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)
;
1662 } else {
1663 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)
;
1664 }
1665 break;
1666 default:
1667 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)
;
1668 break;
1669 }
1670 } else {
1671 switch (charsetSource) {
1672 case kCharsetFromInitialAutoDetectionASCII:
1673 // Deliberately no final version
1674 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)
;
1675 break;
1676 case kCharsetFromInitialAutoDetectionWouldNotHaveBeenUTF8Generic:
1677 case kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8Generic:
1678 case kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8GenericInitialWasASCII:
1679 case kCharsetFromInitialAutoDetectionWouldNotHaveBeenUTF8Content:
1680 case kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8Content:
1681 case kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8ContentInitialWasASCII:
1682 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)
;
1683 break;
1684 case kCharsetFromInitialAutoDetectionWouldNotHaveBeenUTF8DependedOnTLD:
1685 case kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8DependedOnTLD:
1686 case kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8DependedOnTLDInitialWasASCII:
1687 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)
;
1688 break;
1689 case kCharsetFromInitialAutoDetectionWouldHaveBeenUTF8:
1690 case kCharsetFromFinalAutoDetectionWouldHaveBeenUTF8InitialWasASCII:
1691 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)
;
1692 break;
1693 case kCharsetFromChannel:
1694 if (encoding == UTF_8_ENCODING) {
1695 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)
;
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 }
1699 break;
1700 case kCharsetFromXmlDeclaration:
1701 case kCharsetFromMetaTag:
1702 if (isFileURL) {
1703 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)
;
1704 } else if (encoding == UTF_8_ENCODING) {
1705 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)
;
1706 } else {
1707 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)
;
1708 }
1709 break;
1710 default:
1711 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)
;
1712 break;
1713 }
1714 }
1715 return NS_OK;
1716}
1717
1718void nsDocShell::SetParentCharset(const Encoding*& aCharset,
1719 int32_t aCharsetSource,
1720 nsIPrincipal* aPrincipal) {
1721 mParentCharset = aCharset;
1722 mParentCharsetSource = aCharsetSource;
1723 mParentCharsetPrincipal = aPrincipal;
1724}
1725
1726void nsDocShell::GetParentCharset(const Encoding*& aCharset,
1727 int32_t* aCharsetSource,
1728 nsIPrincipal** aPrincipal) {
1729 aCharset = mParentCharset;
1730 *aCharsetSource = mParentCharsetSource;
1731 NS_IF_ADDREF(*aPrincipal = mParentCharsetPrincipal)ns_if_addref(*aPrincipal = mParentCharsetPrincipal);
1732}
1733
1734NS_IMETHODIMPnsresult
1735nsDocShell::GetHasTrackingContentBlocked(Promise** aPromise) {
1736 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", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 1736); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPromise" ")"
); do { MOZ_CrashSequence(__null, 1736); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1737
1738 ErrorResult rv;
1739 RefPtr<Document> doc(GetDocument());
1740 RefPtr<Promise> retPromise = Promise::Create(doc->GetOwnerGlobal(), rv);
1741 if (NS_WARN_IF(rv.Failed())NS_warn_if_impl(rv.Failed(), "rv.Failed()", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 1741)
) {
1742 return rv.StealNSResult();
1743 }
1744
1745 // Retrieve the document's content blocking events from the parent process.
1746 RefPtr<Document::GetContentBlockingEventsPromise> promise =
1747 doc->GetContentBlockingEvents();
1748 if (promise) {
1749 promise->Then(
1750 GetCurrentSerialEventTarget(), __func__,
1751 [retPromise](const Document::GetContentBlockingEventsPromise::
1752 ResolveOrRejectValue& aValue) {
1753 if (aValue.IsResolve()) {
1754 bool has = aValue.ResolveValue() &
1755 nsIWebProgressListener::STATE_BLOCKED_TRACKING_CONTENT;
1756 retPromise->MaybeResolve(has);
1757 } else {
1758 retPromise->MaybeResolve(false);
1759 }
1760 });
1761 } else {
1762 retPromise->MaybeResolve(false);
1763 }
1764
1765 retPromise.forget(aPromise);
1766 return NS_OK;
1767}
1768
1769NS_IMETHODIMPnsresult
1770nsDocShell::GetCssErrorReportingEnabled(bool* aEnabled) {
1771 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", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 1771); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aEnabled" ")"
); do { MOZ_CrashSequence(__null, 1771); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1772 *aEnabled = mCSSErrorReportingEnabled;
1773 return NS_OK;
1774}
1775
1776NS_IMETHODIMPnsresult
1777nsDocShell::SetCssErrorReportingEnabled(bool aEnabled) {
1778 mCSSErrorReportingEnabled = aEnabled;
1779 return NS_OK;
1780}
1781
1782NS_IMETHODIMPnsresult
1783nsDocShell::GetUsePrivateBrowsing(bool* aUsePrivateBrowsing) {
1784 NS_ENSURE_ARG_POINTER(aUsePrivateBrowsing)do { if ((__builtin_expect(!!(!(aUsePrivateBrowsing)), 0))) {
NS_DebugBreak(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aUsePrivateBrowsing"
") failed", nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 1784); return NS_ERROR_INVALID_POINTER; } } while (false)
;
1785 return mBrowsingContext->GetUsePrivateBrowsing(aUsePrivateBrowsing);
1786}
1787
1788void nsDocShell::NotifyPrivateBrowsingChanged() {
1789 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"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 1789); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!mIsBeingDestroyed" ")"); do { MOZ_CrashSequence
(__null, 1789); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
1790
1791 nsTObserverArray<nsWeakPtr>::ForwardIterator iter(mPrivacyObservers);
1792 while (iter.HasMore()) {
1793 nsWeakPtr ref = iter.GetNext();
1794 nsCOMPtr<nsIPrivacyTransitionObserver> obs = do_QueryReferent(ref);
1795 if (!obs) {
1796 iter.Remove();
1797 } else {
1798 obs->PrivateModeChanged(UsePrivateBrowsing());
1799 }
1800 }
1801}
1802
1803NS_IMETHODIMPnsresult
1804nsDocShell::SetUsePrivateBrowsing(bool aUsePrivateBrowsing) {
1805 return mBrowsingContext->SetUsePrivateBrowsing(aUsePrivateBrowsing);
1806}
1807
1808NS_IMETHODIMPnsresult
1809nsDocShell::SetPrivateBrowsing(bool aUsePrivateBrowsing) {
1810 return mBrowsingContext->SetPrivateBrowsing(aUsePrivateBrowsing);
1811}
1812
1813NS_IMETHODIMPnsresult
1814nsDocShell::GetHasLoadedNonBlankURI(bool* aResult) {
1815 NS_ENSURE_ARG_POINTER(aResult)do { if ((__builtin_expect(!!(!(aResult)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aResult" ") failed", nullptr
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 1815); return
NS_ERROR_INVALID_POINTER; } } while (false)
;
1816
1817 *aResult = mHasLoadedNonBlankURI;
1818 return NS_OK;
1819}
1820
1821NS_IMETHODIMPnsresult
1822nsDocShell::GetUseRemoteTabs(bool* aUseRemoteTabs) {
1823 NS_ENSURE_ARG_POINTER(aUseRemoteTabs)do { if ((__builtin_expect(!!(!(aUseRemoteTabs)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aUseRemoteTabs" ") failed"
, nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 1823); return NS_ERROR_INVALID_POINTER; } } while (false)
;
1824 return mBrowsingContext->GetUseRemoteTabs(aUseRemoteTabs);
1825}
1826
1827NS_IMETHODIMPnsresult
1828nsDocShell::SetRemoteTabs(bool aUseRemoteTabs) {
1829 return mBrowsingContext->SetRemoteTabs(aUseRemoteTabs);
1830}
1831
1832NS_IMETHODIMPnsresult
1833nsDocShell::GetUseRemoteSubframes(bool* aUseRemoteSubframes) {
1834 NS_ENSURE_ARG_POINTER(aUseRemoteSubframes)do { if ((__builtin_expect(!!(!(aUseRemoteSubframes)), 0))) {
NS_DebugBreak(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aUseRemoteSubframes"
") failed", nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 1834); return NS_ERROR_INVALID_POINTER; } } while (false)
;
1835 return mBrowsingContext->GetUseRemoteSubframes(aUseRemoteSubframes);
1836}
1837
1838NS_IMETHODIMPnsresult
1839nsDocShell::SetRemoteSubframes(bool aUseRemoteSubframes) {
1840 return mBrowsingContext->SetRemoteSubframes(aUseRemoteSubframes);
1841}
1842
1843NS_IMETHODIMPnsresult
1844nsDocShell::AddWeakPrivacyTransitionObserver(
1845 nsIPrivacyTransitionObserver* aObserver) {
1846 nsWeakPtr weakObs = do_GetWeakReference(aObserver);
1847 if (!weakObs) {
1848 return NS_ERROR_NOT_AVAILABLE;
1849 }
1850 mPrivacyObservers.AppendElement(weakObs);
1851 return NS_OK;
1852}
1853
1854NS_IMETHODIMPnsresult
1855nsDocShell::AddWeakReflowObserver(nsIReflowObserver* aObserver) {
1856 nsWeakPtr weakObs = do_GetWeakReference(aObserver);
1857 if (!weakObs) {
1858 return NS_ERROR_FAILURE;
1859 }
1860 mReflowObservers.AppendElement(weakObs);
1861 return NS_OK;
1862}
1863
1864NS_IMETHODIMPnsresult
1865nsDocShell::RemoveWeakReflowObserver(nsIReflowObserver* aObserver) {
1866 nsWeakPtr obs = do_GetWeakReference(aObserver);
1867 return mReflowObservers.RemoveElement(obs) ? NS_OK : NS_ERROR_FAILURE;
1868}
1869
1870NS_IMETHODIMPnsresult
1871nsDocShell::NotifyReflowObservers(bool aInterruptible,
1872 DOMHighResTimeStamp aStart,
1873 DOMHighResTimeStamp aEnd) {
1874 nsTObserverArray<nsWeakPtr>::ForwardIterator iter(mReflowObservers);
1875 while (iter.HasMore()) {
1876 nsWeakPtr ref = iter.GetNext();
1877 nsCOMPtr<nsIReflowObserver> obs = do_QueryReferent(ref);
1878 if (!obs) {
1879 iter.Remove();
1880 } else if (aInterruptible) {
1881 obs->ReflowInterruptible(aStart, aEnd);
1882 } else {
1883 obs->Reflow(aStart, aEnd);
1884 }
1885 }
1886 return NS_OK;
1887}
1888
1889NS_IMETHODIMPnsresult
1890nsDocShell::GetAllowMetaRedirects(bool* aReturn) {
1891 NS_ENSURE_ARG_POINTER(aReturn)do { if ((__builtin_expect(!!(!(aReturn)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aReturn" ") failed", nullptr
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 1891); return
NS_ERROR_INVALID_POINTER; } } while (false)
;
1892
1893 *aReturn = mAllowMetaRedirects;
1894 return NS_OK;
1895}
1896
1897NS_IMETHODIMPnsresult
1898nsDocShell::SetAllowMetaRedirects(bool aValue) {
1899 mAllowMetaRedirects = aValue;
1900 return NS_OK;
1901}
1902
1903NS_IMETHODIMPnsresult
1904nsDocShell::GetAllowSubframes(bool* aAllowSubframes) {
1905 NS_ENSURE_ARG_POINTER(aAllowSubframes)do { if ((__builtin_expect(!!(!(aAllowSubframes)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aAllowSubframes" ") failed"
, nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 1905); return NS_ERROR_INVALID_POINTER; } } while (false)
;
1906
1907 *aAllowSubframes = mAllowSubframes;
1908 return NS_OK;
1909}
1910
1911NS_IMETHODIMPnsresult
1912nsDocShell::SetAllowSubframes(bool aAllowSubframes) {
1913 mAllowSubframes = aAllowSubframes;
1914 return NS_OK;
1915}
1916
1917NS_IMETHODIMPnsresult
1918nsDocShell::GetAllowImages(bool* aAllowImages) {
1919 NS_ENSURE_ARG_POINTER(aAllowImages)do { if ((__builtin_expect(!!(!(aAllowImages)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aAllowImages" ") failed"
, nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 1919); return NS_ERROR_INVALID_POINTER; } } while (false)
;
1920
1921 *aAllowImages = mAllowImages;
1922 return NS_OK;
1923}
1924
1925NS_IMETHODIMPnsresult
1926nsDocShell::SetAllowImages(bool aAllowImages) {
1927 mAllowImages = aAllowImages;
1928 return NS_OK;
1929}
1930
1931NS_IMETHODIMPnsresult
1932nsDocShell::GetAllowMedia(bool* aAllowMedia) {
1933 *aAllowMedia = mAllowMedia;
1934 return NS_OK;
1935}
1936
1937NS_IMETHODIMPnsresult
1938nsDocShell::SetAllowMedia(bool aAllowMedia) {
1939 mAllowMedia = aAllowMedia;
1940
1941 // Mute or unmute audio contexts attached to the inner window.
1942 if (mScriptGlobal) {
1943 if (nsPIDOMWindowInner* innerWin = mScriptGlobal->GetCurrentInnerWindow()) {
1944 if (aAllowMedia) {
1945 innerWin->UnmuteAudioContexts();
1946 } else {
1947 innerWin->MuteAudioContexts();
1948 }
1949 }
1950 }
1951
1952 return NS_OK;
1953}
1954
1955NS_IMETHODIMPnsresult
1956nsDocShell::GetAllowDNSPrefetch(bool* aAllowDNSPrefetch) {
1957 *aAllowDNSPrefetch = mAllowDNSPrefetch;
1958 return NS_OK;
1959}
1960
1961NS_IMETHODIMPnsresult
1962nsDocShell::SetAllowDNSPrefetch(bool aAllowDNSPrefetch) {
1963 mAllowDNSPrefetch = aAllowDNSPrefetch;
1964 return NS_OK;
1965}
1966
1967NS_IMETHODIMPnsresult
1968nsDocShell::GetAllowWindowControl(bool* aAllowWindowControl) {
1969 *aAllowWindowControl = mAllowWindowControl;
1970 return NS_OK;
1971}
1972
1973NS_IMETHODIMPnsresult
1974nsDocShell::SetAllowWindowControl(bool aAllowWindowControl) {
1975 mAllowWindowControl = aAllowWindowControl;
1976 return NS_OK;
1977}
1978
1979NS_IMETHODIMPnsresult
1980nsDocShell::GetAllowContentRetargeting(bool* aAllowContentRetargeting) {
1981 *aAllowContentRetargeting = mBrowsingContext->GetAllowContentRetargeting();
1982 return NS_OK;
1983}
1984
1985NS_IMETHODIMPnsresult
1986nsDocShell::SetAllowContentRetargeting(bool aAllowContentRetargeting) {
1987 BrowsingContext::Transaction txn;
1988 txn.SetAllowContentRetargeting(aAllowContentRetargeting);
1989 txn.SetAllowContentRetargetingOnChildren(aAllowContentRetargeting);
1990 return txn.Commit(mBrowsingContext);
1991}
1992
1993NS_IMETHODIMPnsresult
1994nsDocShell::GetAllowContentRetargetingOnChildren(
1995 bool* aAllowContentRetargetingOnChildren) {
1996 *aAllowContentRetargetingOnChildren =
1997 mBrowsingContext->GetAllowContentRetargetingOnChildren();
1998 return NS_OK;
1999}
2000
2001NS_IMETHODIMPnsresult
2002nsDocShell::SetAllowContentRetargetingOnChildren(
2003 bool aAllowContentRetargetingOnChildren) {
2004 return mBrowsingContext->SetAllowContentRetargetingOnChildren(
2005 aAllowContentRetargetingOnChildren);
2006}
2007
2008NS_IMETHODIMPnsresult
2009nsDocShell::GetMayEnableCharacterEncodingMenu(
2010 bool* aMayEnableCharacterEncodingMenu) {
2011 *aMayEnableCharacterEncodingMenu = false;
2012 if (!mDocumentViewer) {
2013 return NS_OK;
2014 }
2015 Document* doc = mDocumentViewer->GetDocument();
2016 if (!doc) {
2017 return NS_OK;
2018 }
2019 if (doc->WillIgnoreCharsetOverride()) {
2020 return NS_OK;
2021 }
2022
2023 *aMayEnableCharacterEncodingMenu = true;
2024 return NS_OK;
2025}
2026
2027NS_IMETHODIMPnsresult
2028nsDocShell::GetAllDocShellsInSubtree(int32_t aItemType,
2029 DocShellEnumeratorDirection aDirection,
2030 nsTArray<RefPtr<nsIDocShell>>& aResult) {
2031 aResult.Clear();
2032
2033 nsDocShellEnumerator docShellEnum(
2034 (aDirection == ENUMERATE_FORWARDS)
2035 ? nsDocShellEnumerator::EnumerationDirection::Forwards
2036 : nsDocShellEnumerator::EnumerationDirection::Backwards,
2037 aItemType, *this);
2038
2039 nsresult rv = docShellEnum.BuildDocShellArray(aResult);
2040 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2041 return rv;
2042 }
2043
2044 return NS_OK;
2045}
2046
2047NS_IMETHODIMPnsresult
2048nsDocShell::GetAppType(AppType* aAppType) {
2049 *aAppType = mAppType;
2050 return NS_OK;
2051}
2052
2053NS_IMETHODIMPnsresult
2054nsDocShell::SetAppType(AppType aAppType) {
2055 mAppType = aAppType;
2056 return NS_OK;
2057}
2058
2059NS_IMETHODIMPnsresult
2060nsDocShell::GetAllowAuth(bool* aAllowAuth) {
2061 *aAllowAuth = mAllowAuth;
2062 return NS_OK;
2063}
2064
2065NS_IMETHODIMPnsresult
2066nsDocShell::SetAllowAuth(bool aAllowAuth) {
2067 mAllowAuth = aAllowAuth;
2068 return NS_OK;
2069}
2070
2071NS_IMETHODIMPnsresult
2072nsDocShell::GetZoom(float* aZoom) {
2073 NS_ENSURE_ARG_POINTER(aZoom)do { if ((__builtin_expect(!!(!(aZoom)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aZoom" ") failed", nullptr
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 2073); return
NS_ERROR_INVALID_POINTER; } } while (false)
;
2074 *aZoom = 1.0f;
2075 return NS_OK;
2076}
2077
2078NS_IMETHODIMPnsresult
2079nsDocShell::SetZoom(float aZoom) { return NS_ERROR_NOT_IMPLEMENTED; }
2080
2081NS_IMETHODIMPnsresult
2082nsDocShell::GetBusyFlags(BusyFlags* aBusyFlags) {
2083 NS_ENSURE_ARG_POINTER(aBusyFlags)do { if ((__builtin_expect(!!(!(aBusyFlags)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aBusyFlags" ") failed",
nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp",
2083); return NS_ERROR_INVALID_POINTER; } } while (false)
;
2084
2085 *aBusyFlags = mBusyFlags;
2086 return NS_OK;
2087}
2088
2089NS_IMETHODIMPnsresult
2090nsDocShell::GetLoadURIDelegate(nsILoadURIDelegate** aLoadURIDelegate) {
2091 nsCOMPtr<nsILoadURIDelegate> delegate = GetLoadURIDelegate();
2092 delegate.forget(aLoadURIDelegate);
2093 return NS_OK;
2094}
2095
2096already_AddRefed<nsILoadURIDelegate> nsDocShell::GetLoadURIDelegate() {
2097 if (nsCOMPtr<nsILoadURIDelegate> result =
2098 do_QueryActor("LoadURIDelegate", GetDocument())) {
2099 return result.forget();
2100 }
2101
2102 return nullptr;
2103}
2104
2105NS_IMETHODIMPnsresult
2106nsDocShell::GetUseErrorPages(bool* aUseErrorPages) {
2107 *aUseErrorPages = mBrowsingContext->GetUseErrorPages();
2108 return NS_OK;
2109}
2110
2111NS_IMETHODIMPnsresult
2112nsDocShell::SetUseErrorPages(bool aUseErrorPages) {
2113 return mBrowsingContext->SetUseErrorPages(aUseErrorPages);
2114}
2115
2116NS_IMETHODIMPnsresult
2117nsDocShell::GetPreviousEntryIndex(int32_t* aPreviousEntryIndex) {
2118 *aPreviousEntryIndex = mPreviousEntryIndex;
2119 return NS_OK;
2120}
2121
2122NS_IMETHODIMPnsresult
2123nsDocShell::GetLoadedEntryIndex(int32_t* aLoadedEntryIndex) {
2124 *aLoadedEntryIndex = mLoadedEntryIndex;
2125 return NS_OK;
2126}
2127
2128NS_IMETHODIMPnsresult
2129nsDocShell::HistoryPurged(int32_t aNumEntries) {
2130 // These indices are used for fastback cache eviction, to determine
2131 // which session history entries are candidates for content viewer
2132 // eviction. We need to adjust by the number of entries that we
2133 // just purged from history, so that we look at the right session history
2134 // entries during eviction.
2135 mPreviousEntryIndex = std::max(-1, mPreviousEntryIndex - aNumEntries);
2136 mLoadedEntryIndex = std::max(0, mLoadedEntryIndex - aNumEntries);
2137
2138 for (auto* child : mChildList.ForwardRange()) {
2139 nsCOMPtr<nsIDocShell> shell = do_QueryObject(child);
2140 if (shell) {
2141 shell->HistoryPurged(aNumEntries);
2142 }
2143 }
2144
2145 return NS_OK;
2146}
2147
2148nsresult nsDocShell::HistoryEntryRemoved(int32_t aIndex) {
2149 // These indices are used for fastback cache eviction, to determine
2150 // which session history entries are candidates for content viewer
2151 // eviction. We need to adjust by the number of entries that we
2152 // just purged from history, so that we look at the right session history
2153 // entries during eviction.
2154 if (aIndex == mPreviousEntryIndex) {
2155 mPreviousEntryIndex = -1;
2156 } else if (aIndex < mPreviousEntryIndex) {
2157 --mPreviousEntryIndex;
2158 }
2159 if (mLoadedEntryIndex == aIndex) {
2160 mLoadedEntryIndex = 0;
2161 } else if (aIndex < mLoadedEntryIndex) {
2162 --mLoadedEntryIndex;
2163 }
2164
2165 for (auto* child : mChildList.ForwardRange()) {
2166 nsCOMPtr<nsIDocShell> shell = do_QueryObject(child);
2167 if (shell) {
2168 static_cast<nsDocShell*>(shell.get())->HistoryEntryRemoved(aIndex);
2169 }
2170 }
2171
2172 return NS_OK;
2173}
2174
2175nsresult nsDocShell::Now(DOMHighResTimeStamp* aWhen) {
2176 *aWhen = (TimeStamp::Now() - TimeStamp::ProcessCreation()).ToMilliseconds();
2177 return NS_OK;
2178}
2179
2180NS_IMETHODIMPnsresult
2181nsDocShell::SetWindowDraggingAllowed(bool aValue) {
2182 RefPtr<nsDocShell> parent;
2183 if (!aValue && mItemType == typeChrome &&
2184 !(parent = GetInProcessParentDocshell())) {
2185 // Window dragging is always allowed for top level
2186 // chrome docshells.
2187 return NS_ERROR_FAILURE;
2188 }
2189 mWindowDraggingAllowed = aValue;
2190 return NS_OK;
2191}
2192
2193NS_IMETHODIMPnsresult
2194nsDocShell::GetWindowDraggingAllowed(bool* aValue) {
2195 // window dragging regions in CSS (-moz-window-drag:drag)
2196 // can be slow. Default behavior is to only allow it for
2197 // chrome top level windows.
2198 RefPtr<nsDocShell> parent;
2199 if (mItemType == typeChrome && !(parent = GetInProcessParentDocshell())) {
2200 // Top level chrome window
2201 *aValue = true;
2202 } else {
2203 *aValue = mWindowDraggingAllowed;
2204 }
2205 return NS_OK;
2206}
2207
2208NS_IMETHODIMPnsresult
2209nsDocShell::GetCurrentDocumentChannel(nsIChannel** aResult) {
2210 NS_IF_ADDREF(*aResult = GetCurrentDocChannel())ns_if_addref(*aResult = GetCurrentDocChannel());
2211 return NS_OK;
2212}
2213
2214nsIChannel* nsDocShell::GetCurrentDocChannel() {
2215 if (mDocumentViewer) {
2216 Document* doc = mDocumentViewer->GetDocument();
2217 if (doc) {
2218 return doc->GetChannel();
2219 }
2220 }
2221 return nullptr;
2222}
2223
2224NS_IMETHODIMPnsresult
2225nsDocShell::AddWeakScrollObserver(nsIScrollObserver* aObserver) {
2226 nsWeakPtr weakObs = do_GetWeakReference(aObserver);
2227 if (!weakObs) {
2228 return NS_ERROR_FAILURE;
2229 }
2230 mScrollObservers.AppendElement(weakObs);
2231 return NS_OK;
2232}
2233
2234NS_IMETHODIMPnsresult
2235nsDocShell::RemoveWeakScrollObserver(nsIScrollObserver* aObserver) {
2236 nsWeakPtr obs = do_GetWeakReference(aObserver);
2237 return mScrollObservers.RemoveElement(obs) ? NS_OK : NS_ERROR_FAILURE;
2238}
2239
2240void nsDocShell::NotifyAsyncPanZoomStarted() {
2241 nsTObserverArray<nsWeakPtr>::ForwardIterator iter(mScrollObservers);
2242 while (iter.HasMore()) {
2243 nsWeakPtr ref = iter.GetNext();
2244 nsCOMPtr<nsIScrollObserver> obs = do_QueryReferent(ref);
2245 if (obs) {
2246 obs->AsyncPanZoomStarted();
2247 } else {
2248 iter.Remove();
2249 }
2250 }
2251}
2252
2253void nsDocShell::NotifyAsyncPanZoomStopped() {
2254 nsTObserverArray<nsWeakPtr>::ForwardIterator iter(mScrollObservers);
2255 while (iter.HasMore()) {
2256 nsWeakPtr ref = iter.GetNext();
2257 nsCOMPtr<nsIScrollObserver> obs = do_QueryReferent(ref);
2258 if (obs) {
2259 obs->AsyncPanZoomStopped();
2260 } else {
2261 iter.Remove();
2262 }
2263 }
2264}
2265
2266NS_IMETHODIMPnsresult
2267nsDocShell::NotifyScrollObservers() {
2268 nsTObserverArray<nsWeakPtr>::ForwardIterator iter(mScrollObservers);
2269 while (iter.HasMore()) {
2270 nsWeakPtr ref = iter.GetNext();
2271 nsCOMPtr<nsIScrollObserver> obs = do_QueryReferent(ref);
2272 if (obs) {
2273 obs->ScrollPositionChanged();
2274 } else {
2275 iter.Remove();
2276 }
2277 }
2278 return NS_OK;
2279}
2280
2281//*****************************************************************************
2282// nsDocShell::nsIDocShellTreeItem
2283//*****************************************************************************
2284
2285NS_IMETHODIMPnsresult
2286nsDocShell::GetName(nsAString& aName) {
2287 aName = mBrowsingContext->Name();
2288 return NS_OK;
2289}
2290
2291NS_IMETHODIMPnsresult
2292nsDocShell::SetName(const nsAString& aName) {
2293 return mBrowsingContext->SetName(aName);
2294}
2295
2296NS_IMETHODIMPnsresult
2297nsDocShell::NameEquals(const nsAString& aName, bool* aResult) {
2298 NS_ENSURE_ARG_POINTER(aResult)do { if ((__builtin_expect(!!(!(aResult)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aResult" ") failed", nullptr
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 2298); return
NS_ERROR_INVALID_POINTER; } } while (false)
;
2299 *aResult = mBrowsingContext->NameEquals(aName);
2300 return NS_OK;
2301}
2302
2303NS_IMETHODIMPnsresult
2304nsDocShell::GetCustomUserAgent(nsAString& aCustomUserAgent) {
2305 mBrowsingContext->GetCustomUserAgent(aCustomUserAgent);
2306 return NS_OK;
2307}
2308
2309NS_IMETHODIMPnsresult
2310nsDocShell::SetCustomUserAgent(const nsAString& aCustomUserAgent) {
2311 if (mWillChangeProcess) {
2312 NS_WARNING("SetCustomUserAgent: Process is changing. Ignoring set")NS_DebugBreak(NS_DEBUG_WARNING, "SetCustomUserAgent: Process is changing. Ignoring set"
, nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 2312)
;
2313 return NS_ERROR_FAILURE;
2314 }
2315
2316 return mBrowsingContext->SetCustomUserAgent(aCustomUserAgent);
2317}
2318
2319NS_IMETHODIMPnsresult
2320nsDocShell::ClearCachedPlatform() {
2321 nsCOMPtr<nsPIDOMWindowInner> win =
2322 mScriptGlobal ? mScriptGlobal->GetCurrentInnerWindow() : nullptr;
2323 if (win) {
2324 Navigator* navigator = win->Navigator();
2325 if (navigator) {
2326 navigator->ClearPlatformCache();
2327 }
2328 }
2329
2330 return NS_OK;
2331}
2332
2333NS_IMETHODIMPnsresult
2334nsDocShell::ClearCachedUserAgent() {
2335 nsCOMPtr<nsPIDOMWindowInner> win =
2336 mScriptGlobal ? mScriptGlobal->GetCurrentInnerWindow() : nullptr;
2337 if (win) {
2338 Navigator* navigator = win->Navigator();
2339 if (navigator) {
2340 navigator->ClearUserAgentCache();
2341 }
2342 }
2343
2344 return NS_OK;
2345}
2346
2347/* virtual */
2348int32_t nsDocShell::ItemType() { return mItemType; }
2349
2350NS_IMETHODIMPnsresult
2351nsDocShell::GetItemType(int32_t* aItemType) {
2352 NS_ENSURE_ARG_POINTER(aItemType)do { if ((__builtin_expect(!!(!(aItemType)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aItemType" ") failed", nullptr
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 2352); return
NS_ERROR_INVALID_POINTER; } } while (false)
;
2353
2354 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"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 2355); AnnotateMozCrashReason
("MOZ_DIAGNOSTIC_ASSERT" "(" "(mBrowsingContext->IsContent() ? typeContent : typeChrome) == mItemType"
")"); do { MOZ_CrashSequence(__null, 2355); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2355 (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"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 2355); AnnotateMozCrashReason
("MOZ_DIAGNOSTIC_ASSERT" "(" "(mBrowsingContext->IsContent() ? typeContent : typeChrome) == mItemType"
")"); do { MOZ_CrashSequence(__null, 2355); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2356 *aItemType = mItemType;
2357 return NS_OK;
2358}
2359
2360NS_IMETHODIMPnsresult
2361nsDocShell::GetInProcessParent(nsIDocShellTreeItem** aParent) {
2362 if (!mParent) {
2363 *aParent = nullptr;
2364 } else {
2365 CallQueryInterface(mParent, aParent);
2366 }
2367 // Note that in the case when the parent is not an nsIDocShellTreeItem we
2368 // don't want to throw; we just want to return null.
2369 return NS_OK;
2370}
2371
2372// With Fission, related nsDocShell objects may exist in a different process. In
2373// that case, this method will return `nullptr`, despite a parent nsDocShell
2374// object existing.
2375//
2376// Prefer using `BrowsingContext::Parent()`, which will succeed even if the
2377// parent entry is not in the current process, and handle the case where the
2378// parent nsDocShell is inaccessible.
2379already_AddRefed<nsDocShell> nsDocShell::GetInProcessParentDocshell() {
2380 nsCOMPtr<nsIDocShell> docshell = do_QueryInterface(GetAsSupports(mParent));
2381 return docshell.forget().downcast<nsDocShell>();
2382}
2383
2384void nsDocShell::MaybeCreateInitialClientSource(nsIPrincipal* aPrincipal) {
2385 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"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 2385); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!mIsBeingDestroyed" ")"); do { MOZ_CrashSequence
(__null, 2385); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
2386
2387 // If there is an existing document then there is no need to create
2388 // a client for a future initial about:blank document.
2389 if (mScriptGlobal && mScriptGlobal->GetCurrentInnerWindow() &&
2390 mScriptGlobal->GetCurrentInnerWindow()->GetExtantDoc()) {
2391 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()"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 2392); AnnotateMozCrashReason
("MOZ_DIAGNOSTIC_ASSERT" "(" "mScriptGlobal->GetCurrentInnerWindow()->GetClientInfo().isSome()"
")"); do { MOZ_CrashSequence(__null, 2392); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2392 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()"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 2392); AnnotateMozCrashReason
("MOZ_DIAGNOSTIC_ASSERT" "(" "mScriptGlobal->GetCurrentInnerWindow()->GetClientInfo().isSome()"
")"); do { MOZ_CrashSequence(__null, 2392); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2393 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"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 2393); AnnotateMozCrashReason
("MOZ_DIAGNOSTIC_ASSERT" "(" "!mInitialClientSource" ")"); do
{ MOZ_CrashSequence(__null, 2393); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
2394 return;
2395 }
2396
2397 // Don't recreate the initial client source. We call this multiple times
2398 // when DoChannelLoad() is called before CreateAboutBlankDocumentViewer.
2399 if (mInitialClientSource) {
2400 return;
2401 }
2402
2403 // Don't pre-allocate the client when we are sandboxed. The inherited
2404 // principal does not take sandboxing into account.
2405 // TODO: Refactor sandboxing principal code out so we can use it here.
2406 if (!aPrincipal && mBrowsingContext->GetSandboxFlags()) {
2407 return;
2408 }
2409
2410 // We cannot get inherited foreign partitioned principal here. Instead, we
2411 // directly check which principal we want to inherit for the service worker.
2412 nsIPrincipal* principal =
2413 aPrincipal
2414 ? aPrincipal
2415 : GetInheritedPrincipal(
2416 false, StoragePrincipalHelper::
2417 ShouldUsePartitionPrincipalForServiceWorker(this));
2418
2419 // Sometimes there is no principal available when we are called from
2420 // CreateAboutBlankDocumentViewer. For example, sometimes the principal
2421 // is only extracted from the load context after the document is created
2422 // in Document::ResetToURI(). Ideally we would do something similar
2423 // here, but for now lets just avoid the issue by not preallocating the
2424 // client.
2425 if (!principal) {
2426 return;
2427 }
2428
2429 nsCOMPtr<nsPIDOMWindowOuter> win = GetWindow();
2430 if (!win) {
2431 return;
2432 }
2433
2434 mInitialClientSource = ClientManager::CreateSource(
2435 ClientType::Window, GetMainThreadSerialEventTarget(), principal);
2436 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"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 2436); AnnotateMozCrashReason
("MOZ_DIAGNOSTIC_ASSERT" "(" "mInitialClientSource" ")"); do {
MOZ_CrashSequence(__null, 2436); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
2437
2438 // Mark the initial client as execution ready, but owned by the docshell.
2439 // If the client is actually used this will cause ClientSource to force
2440 // the creation of the initial about:blank by calling
2441 // nsDocShell::GetDocument().
2442 mInitialClientSource->DocShellExecutionReady(this);
2443
2444 // Next, check to see if the parent is controlled.
2445 nsCOMPtr<nsIDocShell> parent = GetInProcessParentDocshell();
2446 nsPIDOMWindowOuter* parentOuter = parent ? parent->GetWindow() : nullptr;
2447 nsPIDOMWindowInner* parentInner =
2448 parentOuter ? parentOuter->GetCurrentInnerWindow() : nullptr;
2449 if (!parentInner) {
2450 return;
2451 }
2452
2453 nsCOMPtr<nsIURI> uri;
2454 MOZ_ALWAYS_SUCCEEDS(NS_NewURI(getter_AddRefs(uri), "about:blank"_ns))do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(NS_NewURI(getter_AddRefs(uri), "about:blank"_ns))), 1)))), 1
))) { } else { do { do { } while (false); MOZ_ReportCrash("" "NS_SUCCEEDED(NS_NewURI(getter_AddRefs(uri), \"about:blank\"_ns))"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 2454); AnnotateMozCrashReason
("MOZ_CRASH(" "NS_SUCCEEDED(NS_NewURI(getter_AddRefs(uri), \"about:blank\"_ns))"
")"); do { MOZ_CrashSequence(__null, 2454); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
;
2455
2456 // We're done if there is no parent controller or if this docshell
2457 // is not permitted to control for some reason.
2458 Maybe<ServiceWorkerDescriptor> controller(parentInner->GetController());
2459 if (controller.isNothing() ||
2460 !ServiceWorkerAllowedToControlWindow(principal, uri)) {
2461 return;
2462 }
2463
2464 mInitialClientSource->InheritController(controller.ref());
2465}
2466
2467Maybe<ClientInfo> nsDocShell::GetInitialClientInfo() const {
2468 if (mInitialClientSource) {
2469 Maybe<ClientInfo> result;
2470 result.emplace(mInitialClientSource->Info());
2471 return result;
2472 }
2473
2474 nsPIDOMWindowInner* innerWindow =
2475 mScriptGlobal ? mScriptGlobal->GetCurrentInnerWindow() : nullptr;
2476 Document* doc = innerWindow ? innerWindow->GetExtantDoc() : nullptr;
2477
2478 if (!doc || !doc->IsInitialDocument()) {
2479 return Maybe<ClientInfo>();
2480 }
2481
2482 return innerWindow->GetClientInfo();
2483}
2484
2485nsresult nsDocShell::SetDocLoaderParent(nsDocLoader* aParent) {
2486 bool wasFrame = IsSubframe();
2487
2488 nsresult rv = nsDocLoader::SetDocLoaderParent(aParent);
2489 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, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 2489); return rv; } } while (false)
;
2490
2491 nsCOMPtr<nsISupportsPriority> priorityGroup = do_QueryInterface(mLoadGroup);
2492 if (wasFrame != IsSubframe() && priorityGroup) {
2493 priorityGroup->AdjustPriority(wasFrame ? -1 : 1);
2494 }
2495
2496 // Curse ambiguous nsISupports inheritance!
2497 nsISupports* parent = GetAsSupports(aParent);
2498
2499 // If parent is another docshell, we inherit all their flags for
2500 // allowing plugins, scripting etc.
2501 bool value;
2502 nsCOMPtr<nsIDocShell> parentAsDocShell(do_QueryInterface(parent));
2503
2504 if (parentAsDocShell) {
2505 if (mAllowMetaRedirects &&
2506 NS_SUCCEEDED(parentAsDocShell->GetAllowMetaRedirects(&value))((bool)(__builtin_expect(!!(!NS_FAILED_impl(parentAsDocShell->
GetAllowMetaRedirects(&value))), 1)))
) {
2507 SetAllowMetaRedirects(value);
2508 }
2509 if (mAllowSubframes &&
2510 NS_SUCCEEDED(parentAsDocShell->GetAllowSubframes(&value))((bool)(__builtin_expect(!!(!NS_FAILED_impl(parentAsDocShell->
GetAllowSubframes(&value))), 1)))
) {
2511 SetAllowSubframes(value);
2512 }
2513 if (mAllowImages &&
2514 NS_SUCCEEDED(parentAsDocShell->GetAllowImages(&value))((bool)(__builtin_expect(!!(!NS_FAILED_impl(parentAsDocShell->
GetAllowImages(&value))), 1)))
) {
2515 SetAllowImages(value);
2516 }
2517 SetAllowMedia(parentAsDocShell->GetAllowMedia() && mAllowMedia);
2518 if (mAllowWindowControl &&
2519 NS_SUCCEEDED(parentAsDocShell->GetAllowWindowControl(&value))((bool)(__builtin_expect(!!(!NS_FAILED_impl(parentAsDocShell->
GetAllowWindowControl(&value))), 1)))
) {
2520 SetAllowWindowControl(value);
2521 }
2522 if (NS_FAILED(parentAsDocShell->GetAllowDNSPrefetch(&value))((bool)(__builtin_expect(!!(NS_FAILED_impl(parentAsDocShell->
GetAllowDNSPrefetch(&value))), 0)))
) {
2523 value = false;
2524 }
2525 SetAllowDNSPrefetch(mAllowDNSPrefetch && value);
2526 }
2527
2528 nsCOMPtr<nsIURIContentListener> parentURIListener(do_GetInterface(parent));
2529 if (parentURIListener) {
2530 mContentListener->SetParentContentListener(parentURIListener);
2531 }
2532
2533 return NS_OK;
2534}
2535
2536void nsDocShell::MaybeRestoreWindowName() {
2537 if (!StaticPrefs::privacy_window_name_update_enabled()) {
2538 return;
2539 }
2540
2541 // We only restore window.name for the top-level content.
2542 if (!mBrowsingContext->IsTopContent()) {
2543 return;
2544 }
2545
2546 nsAutoString name;
2547
2548 // Following implements https://html.spec.whatwg.org/#history-traversal:
2549 // Step 4.4. Check if the loading entry has a name.
2550
2551 if (mLSHE) {
2552 mLSHE->GetName(name);
2553 }
2554
2555 if (mLoadingEntry) {
2556 name = mLoadingEntry->mInfo.GetName();
2557 }
2558
2559 if (name.IsEmpty()) {
2560 return;
2561 }
2562
2563 // Step 4.4.1. Set the name to the browsing context.
2564 Unused << mBrowsingContext->SetName(name);
2565
2566 // Step 4.4.2. Clear the name of all entries that are contiguous and
2567 // same-origin with the loading entry.
2568 if (mLSHE) {
2569 nsSHistory::WalkContiguousEntries(
2570 mLSHE, [](nsISHEntry* aEntry) { aEntry->SetName(EmptyString()); });
2571 }
2572
2573 if (mLoadingEntry) {
2574 // Clear the name of the session entry in the child side. For parent side,
2575 // the clearing will be done when we commit the history to the parent.
2576 mLoadingEntry->mInfo.SetName(EmptyString());
2577 }
2578}
2579
2580void nsDocShell::StoreWindowNameToSHEntries() {
2581 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()", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 2581); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mBrowsingContext->IsTopContent()"
")"); do { MOZ_CrashSequence(__null, 2581); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2582
2583 nsAutoString name;
2584 mBrowsingContext->GetName(name);
2585
2586 if (mOSHE) {
2587 nsSHistory::WalkContiguousEntries(
2588 mOSHE, [&](nsISHEntry* aEntry) { aEntry->SetName(name); });
2589 }
2590
2591 if (mozilla::SessionHistoryInParent()) {
2592 if (XRE_IsParentProcess()) {
2593 SessionHistoryEntry* entry =
2594 mBrowsingContext->Canonical()->GetActiveSessionHistoryEntry();
2595 if (entry) {
2596 nsSHistory::WalkContiguousEntries(
2597 entry, [&](nsISHEntry* aEntry) { aEntry->SetName(name); });
2598 }
2599 } else {
2600 // Ask parent process to store the name in entries.
2601 mozilla::Unused
2602 << ContentChild::GetSingleton()
2603 ->SendSessionHistoryEntryStoreWindowNameInContiguousEntries(
2604 mBrowsingContext, name);
2605 }
2606 }
2607}
2608
2609NS_IMETHODIMPnsresult
2610nsDocShell::GetInProcessSameTypeParent(nsIDocShellTreeItem** aParent) {
2611 if (BrowsingContext* parentBC = mBrowsingContext->GetParent()) {
2612 *aParent = do_AddRef(parentBC->GetDocShell()).take();
2613 }
2614 return NS_OK;
2615}
2616
2617NS_IMETHODIMPnsresult
2618nsDocShell::GetInProcessRootTreeItem(nsIDocShellTreeItem** aRootTreeItem) {
2619 NS_ENSURE_ARG_POINTER(aRootTreeItem)do { if ((__builtin_expect(!!(!(aRootTreeItem)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aRootTreeItem" ") failed"
, nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 2619); return NS_ERROR_INVALID_POINTER; } } while (false)
;
2620
2621 RefPtr<nsDocShell> root = this;
2622 RefPtr<nsDocShell> parent = root->GetInProcessParentDocshell();
2623 while (parent) {
2624 root = parent;
2625 parent = root->GetInProcessParentDocshell();
2626 }
2627
2628 root.forget(aRootTreeItem);
2629 return NS_OK;
2630}
2631
2632NS_IMETHODIMPnsresult
2633nsDocShell::GetInProcessSameTypeRootTreeItem(
2634 nsIDocShellTreeItem** aRootTreeItem) {
2635 NS_ENSURE_ARG_POINTER(aRootTreeItem)do { if ((__builtin_expect(!!(!(aRootTreeItem)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aRootTreeItem" ") failed"
, nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 2635); return NS_ERROR_INVALID_POINTER; } } while (false)
;
2636 *aRootTreeItem = static_cast<nsIDocShellTreeItem*>(this);
2637
2638 nsCOMPtr<nsIDocShellTreeItem> parent;
2639 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, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 2640); return NS_ERROR_FAILURE; } } while (false)
2640 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, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 2640); return NS_ERROR_FAILURE; } } while (false)
;
2641 while (parent) {
2642 *aRootTreeItem = parent;
2643 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, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 2645); return NS_ERROR_FAILURE; } } while (false)
2644 (*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, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 2645); return NS_ERROR_FAILURE; } } while (false)
2645 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, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 2645); return NS_ERROR_FAILURE; } } while (false)
;
2646 }
2647 NS_ADDREF(*aRootTreeItem)(*aRootTreeItem)->AddRef();
2648 return NS_OK;
2649}
2650
2651NS_IMETHODIMPnsresult
2652nsDocShell::GetTreeOwner(nsIDocShellTreeOwner** aTreeOwner) {
2653 NS_ENSURE_ARG_POINTER(aTreeOwner)do { if ((__builtin_expect(!!(!(aTreeOwner)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aTreeOwner" ") failed",
nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp",
2653); return NS_ERROR_INVALID_POINTER; } } while (false)
;
2654
2655 *aTreeOwner = mTreeOwner;
2656 NS_IF_ADDREF(*aTreeOwner)ns_if_addref(*aTreeOwner);
2657 return NS_OK;
2658}
2659
2660NS_IMETHODIMPnsresult
2661nsDocShell::SetTreeOwner(nsIDocShellTreeOwner* aTreeOwner) {
2662 if (mIsBeingDestroyed && aTreeOwner) {
2663 return NS_ERROR_FAILURE;
2664 }
2665
2666 // Don't automatically set the progress based on the tree owner for frames
2667 if (!IsSubframe()) {
2668 nsCOMPtr<nsIWebProgress> webProgress =
2669 do_QueryInterface(GetAsSupports(this));
2670
2671 if (webProgress) {
2672 nsCOMPtr<nsIWebProgressListener> oldListener =
2673 do_QueryInterface(mTreeOwner);
2674 nsCOMPtr<nsIWebProgressListener> newListener =
2675 do_QueryInterface(aTreeOwner);
2676
2677 if (oldListener) {
2678 webProgress->RemoveProgressListener(oldListener);
2679 }
2680
2681 if (newListener) {
2682 webProgress->AddProgressListener(newListener,
2683 nsIWebProgress::NOTIFY_ALL);
2684 }
2685 }
2686 }
2687
2688 mTreeOwner = aTreeOwner; // Weak reference per API
2689
2690 for (auto* childDocLoader : mChildList.ForwardRange()) {
2691 nsCOMPtr<nsIDocShellTreeItem> child = do_QueryObject(childDocLoader);
2692 NS_ENSURE_TRUE(child, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(child)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "child" ") failed", nullptr
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 2692); return
NS_ERROR_FAILURE; } } while (false)
;
2693
2694 if (child->ItemType() == mItemType) {
2695 child->SetTreeOwner(aTreeOwner);
2696 }
2697 }
2698
2699 // If we're in the content process and have had a TreeOwner set on us, extract
2700 // our BrowserChild actor. If we've already had our BrowserChild set, assert
2701 // that it hasn't changed.
2702 if (mTreeOwner && XRE_IsContentProcess()) {
2703 nsCOMPtr<nsIBrowserChild> newBrowserChild = do_GetInterface(mTreeOwner);
2704 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!" ")",
"/root/firefox-clang/docshell/base/nsDocShell.cpp", 2705); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "newBrowserChild" ") (" "No BrowserChild actor for tree owner in Content!"
")"); do { MOZ_CrashSequence(__null, 2705); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2705 "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!" ")",
"/root/firefox-clang/docshell/base/nsDocShell.cpp", 2705); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "newBrowserChild" ") (" "No BrowserChild actor for tree owner in Content!"
")"); do { MOZ_CrashSequence(__null, 2705); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2706
2707 if (mBrowserChild) {
2708 nsCOMPtr<nsIBrowserChild> oldBrowserChild =
2709 do_QueryReferent(mBrowserChild);
2710 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!"
")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 2712
); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "oldBrowserChild == newBrowserChild"
") (" "Cannot change BrowserChild during nsDocShell lifetime!"
")"); do { MOZ_CrashSequence(__null, 2712); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2711 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!"
")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 2712
); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "oldBrowserChild == newBrowserChild"
") (" "Cannot change BrowserChild during nsDocShell lifetime!"
")"); do { MOZ_CrashSequence(__null, 2712); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2712 "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!"
")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 2712
); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "oldBrowserChild == newBrowserChild"
") (" "Cannot change BrowserChild during nsDocShell lifetime!"
")"); do { MOZ_CrashSequence(__null, 2712); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2713 } else {
2714 mBrowserChild = do_GetWeakReference(newBrowserChild);
2715 }
2716 }
2717
2718 return NS_OK;
2719}
2720
2721NS_IMETHODIMPnsresult
2722nsDocShell::GetHistoryID(nsID& aID) {
2723 aID = mBrowsingContext->GetHistoryID();
2724 return NS_OK;
2725}
2726
2727const nsID& nsDocShell::HistoryID() { return mBrowsingContext->GetHistoryID(); }
2728
2729NS_IMETHODIMPnsresult
2730nsDocShell::GetIsInUnload(bool* aIsInUnload) {
2731 *aIsInUnload = mFiredUnloadEvent;
2732 return NS_OK;
2733}
2734
2735NS_IMETHODIMPnsresult
2736nsDocShell::GetInProcessChildCount(int32_t* aChildCount) {
2737 NS_ENSURE_ARG_POINTER(aChildCount)do { if ((__builtin_expect(!!(!(aChildCount)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aChildCount" ") failed"
, nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 2737); return NS_ERROR_INVALID_POINTER; } } while (false)
;
2738 *aChildCount = mChildList.Length();
2739 return NS_OK;
2740}
2741
2742NS_IMETHODIMPnsresult
2743nsDocShell::AddChild(nsIDocShellTreeItem* aChild) {
2744 NS_ENSURE_ARG_POINTER(aChild)do { if ((__builtin_expect(!!(!(aChild)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aChild" ") failed", nullptr
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 2744); return
NS_ERROR_INVALID_POINTER; } } while (false)
;
2745
2746 RefPtr<nsDocLoader> childAsDocLoader = GetAsDocLoader(aChild);
2747 NS_ENSURE_TRUE(childAsDocLoader, NS_ERROR_UNEXPECTED)do { if ((__builtin_expect(!!(!(childAsDocLoader)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "childAsDocLoader" ") failed"
, nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 2747); return NS_ERROR_UNEXPECTED; } } while (false)
;
2748
2749 // Make sure we're not creating a loop in the docshell tree
2750 nsDocLoader* ancestor = this;
2751 do {
2752 if (childAsDocLoader == ancestor) {
2753 return NS_ERROR_ILLEGAL_VALUE;
2754 }
2755 ancestor = ancestor->GetParent();
2756 } while (ancestor);
2757
2758 // Make sure to remove the child from its current parent.
2759 nsDocLoader* childsParent = childAsDocLoader->GetParent();
2760 if (childsParent) {
2761 nsresult rv = childsParent->RemoveChildLoader(childAsDocLoader);
2762 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, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 2762); return rv; } } while (false)
;
2763 }
2764
2765 // Make sure to clear the treeowner in case this child is a different type
2766 // from us.
2767 aChild->SetTreeOwner(nullptr);
2768
2769 nsresult res = AddChildLoader(childAsDocLoader);
2770 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, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 2770); return res; } } while (false)
;
2771 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()"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 2772); MOZ_PretendNoReturn
(); } } while (0)
2772 "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()"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 2772); MOZ_PretendNoReturn
(); } } while (0)
;
2773
2774 /* Set the child's global history if the parent has one */
2775 if (mBrowsingContext->GetUseGlobalHistory()) {
2776 // childDocShell->SetUseGlobalHistory(true);
2777 // this should be set through BC inherit
2778 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()",
"/root/firefox-clang/docshell/base/nsDocShell.cpp", 2778); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aChild->GetBrowsingContext()->GetUseGlobalHistory()"
")"); do { MOZ_CrashSequence(__null, 2778); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2779 }
2780
2781 if (aChild->ItemType() != mItemType) {
2782 return NS_OK;
2783 }
2784
2785 aChild->SetTreeOwner(mTreeOwner);
2786
2787 nsCOMPtr<nsIDocShell> childAsDocShell(do_QueryInterface(aChild));
2788 if (!childAsDocShell) {
2789 return NS_OK;
2790 }
2791
2792 // charset, style-disabling, and zoom will be inherited in SetupNewViewer()
2793
2794 // Now take this document's charset and set the child's parentCharset field
2795 // to it. We'll later use that field, in the loading process, for the
2796 // charset choosing algorithm.
2797 // If we fail, at any point, we just return NS_OK.
2798 // This code has some performance impact. But this will be reduced when
2799 // the current charset will finally be stored as an Atom, avoiding the
2800 // alias resolution extra look-up.
2801
2802 // we are NOT going to propagate the charset is this Chrome's docshell
2803 if (mItemType == nsIDocShellTreeItem::typeChrome) {
2804 return NS_OK;
2805 }
2806
2807 // get the parent's current charset
2808 if (!mDocumentViewer) {
2809 return NS_OK;
2810 }
2811 Document* doc = mDocumentViewer->GetDocument();
2812 if (!doc) {
2813 return NS_OK;
2814 }
2815
2816 const Encoding* parentCS = doc->GetDocumentCharacterSet();
2817 int32_t charsetSource = doc->GetDocumentCharacterSetSource();
2818 // set the child's parentCharset
2819 childAsDocShell->SetParentCharset(parentCS, charsetSource,
2820 doc->NodePrincipal());
2821
2822 // printf("### 1 >>> Adding child. Parent CS = %s. ItemType = %d.\n",
2823 // NS_LossyConvertUTF16toASCII(parentCS).get(), mItemType);
2824
2825 return NS_OK;
2826}
2827
2828NS_IMETHODIMPnsresult
2829nsDocShell::RemoveChild(nsIDocShellTreeItem* aChild) {
2830 NS_ENSURE_ARG_POINTER(aChild)do { if ((__builtin_expect(!!(!(aChild)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aChild" ") failed", nullptr
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 2830); return
NS_ERROR_INVALID_POINTER; } } while (false)
;
2831
2832 RefPtr<nsDocLoader> childAsDocLoader = GetAsDocLoader(aChild);
2833 NS_ENSURE_TRUE(childAsDocLoader, NS_ERROR_UNEXPECTED)do { if ((__builtin_expect(!!(!(childAsDocLoader)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "childAsDocLoader" ") failed"
, nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 2833); return NS_ERROR_UNEXPECTED; } } while (false)
;
2834
2835 nsresult rv = RemoveChildLoader(childAsDocLoader);
2836 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, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 2836); return rv; } } while (false)
;
2837
2838 aChild->SetTreeOwner(nullptr);
2839
2840 return nsDocLoader::AddDocLoaderAsChildOfRoot(childAsDocLoader);
2841}
2842
2843NS_IMETHODIMPnsresult
2844nsDocShell::GetInProcessChildAt(int32_t aIndex, nsIDocShellTreeItem** aChild) {
2845 NS_ENSURE_ARG_POINTER(aChild)do { if ((__builtin_expect(!!(!(aChild)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aChild" ") failed", nullptr
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 2845); return
NS_ERROR_INVALID_POINTER; } } while (false)
;
2846
2847 RefPtr<nsDocShell> child = GetInProcessChildAt(aIndex);
2848 NS_ENSURE_TRUE(child, NS_ERROR_UNEXPECTED)do { if ((__builtin_expect(!!(!(child)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "child" ") failed", nullptr
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 2848); return
NS_ERROR_UNEXPECTED; } } while (false)
;
2849
2850 child.forget(aChild);
2851
2852 return NS_OK;
2853}
2854
2855nsDocShell* nsDocShell::GetInProcessChildAt(int32_t aIndex) {
2856#ifdef DEBUG1
2857 if (aIndex < 0) {
2858 NS_WARNING("Negative index passed to GetChildAt")NS_DebugBreak(NS_DEBUG_WARNING, "Negative index passed to GetChildAt"
, nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 2858)
;
2859 } else if (static_cast<uint32_t>(aIndex) >= mChildList.Length()) {
2860 NS_WARNING("Too large an index passed to GetChildAt")NS_DebugBreak(NS_DEBUG_WARNING, "Too large an index passed to GetChildAt"
, nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 2860)
;
2861 }
2862#endif
2863
2864 nsIDocumentLoader* child = ChildAt(aIndex);
2865
2866 // child may be nullptr here.
2867 return static_cast<nsDocShell*>(child);
2868}
2869
2870nsresult nsDocShell::AddChildSHEntry(nsISHEntry* aCloneRef,
2871 nsISHEntry* aNewEntry,
2872 int32_t aChildOffset, uint32_t aLoadType,
2873 bool aCloneChildren) {
2874 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()", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 2874); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mozilla::SessionHistoryInParent()"
")"); do { MOZ_CrashSequence(__null, 2874); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2875 nsresult rv = NS_OK;
2876
2877 if (mLSHE && aLoadType != LOAD_PUSHSTATE) {
2878 /* You get here if you are currently building a
2879 * hierarchy ie.,you just visited a frameset page
2880 */
2881 if (NS_FAILED(mLSHE->ReplaceChild(aNewEntry))((bool)(__builtin_expect(!!(NS_FAILED_impl(mLSHE->ReplaceChild
(aNewEntry))), 0)))
) {
2882 rv = mLSHE->AddChild(aNewEntry, aChildOffset);
2883 }
2884 } else if (!aCloneRef) {
2885 /* This is an initial load in some subframe. Just append it if we can */
2886 if (mOSHE) {
2887 rv = mOSHE->AddChild(aNewEntry, aChildOffset, UseRemoteSubframes());
2888 }
2889 } else {
2890 RefPtr<ChildSHistory> shistory = GetRootSessionHistory();
2891 if (shistory) {
2892 rv = shistory->LegacySHistory()->AddNestedSHEntry(
2893 aCloneRef, aNewEntry, mBrowsingContext->Top(), aCloneChildren);
2894 }
2895 }
2896 return rv;
2897}
2898
2899nsresult nsDocShell::AddChildSHEntryToParent(nsISHEntry* aNewEntry,
2900 int32_t aChildOffset,
2901 bool aCloneChildren) {
2902 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()", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 2902); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mozilla::SessionHistoryInParent()"
")"); do { MOZ_CrashSequence(__null, 2902); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2903 /* You will get here when you are in a subframe and
2904 * a new url has been loaded on you.
2905 * The mOSHE in this subframe will be the previous url's
2906 * mOSHE. This mOSHE will be used as the identification
2907 * for this subframe in the CloneAndReplace function.
2908 */
2909
2910 // In this case, we will end up calling AddEntry, which increases the
2911 // current index by 1
2912 RefPtr<ChildSHistory> rootSH = GetRootSessionHistory();
2913 if (rootSH) {
2914 mPreviousEntryIndex = rootSH->Index();
2915 }
2916
2917 nsresult rv;
2918 // XXX(farre): this is not Fission safe, expect errors. This never
2919 // get's executed once session history in the parent is enabled.
2920 nsCOMPtr<nsIDocShell> parent = do_QueryInterface(GetAsSupports(mParent), &rv);
2921 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()"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 2924); }
} while (false)
2922 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()"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 2924); }
} while (false)
2923 "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()"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 2924); }
} while (false)
2924 "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()"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 2924); }
} while (false)
;
2925 if (parent) {
2926 rv = nsDocShell::Cast(parent)->AddChildSHEntry(
2927 mOSHE, aNewEntry, aChildOffset, mLoadType, aCloneChildren);
2928 }
2929
2930 if (rootSH) {
2931 mLoadedEntryIndex = rootSH->Index();
2932
2933 if (MOZ_UNLIKELY(MOZ_LOG_TEST(gPageCacheLog, LogLevel::Verbose))(__builtin_expect(!!((__builtin_expect(!!(mozilla::detail::log_test
(gPageCacheLog, LogLevel::Verbose)), 0))), 0))
) {
2934 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)
2935 ("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)
2936 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)
;
2937 }
2938 }
2939
2940 return rv;
2941}
2942
2943NS_IMETHODIMPnsresult
2944nsDocShell::GetCurrentSHEntry(nsISHEntry** aEntry, bool* aOSHE) {
2945 *aOSHE = false;
2946 *aEntry = nullptr;
2947 if (mLSHE) {
2948 NS_ADDREF(*aEntry = mLSHE)(*aEntry = mLSHE)->AddRef();
2949 } else if (mOSHE) {
2950 NS_ADDREF(*aEntry = mOSHE)(*aEntry = mOSHE)->AddRef();
2951 *aOSHE = true;
2952 }
2953 return NS_OK;
2954}
2955
2956NS_IMETHODIMPnsresult nsDocShell::SynchronizeLayoutHistoryState() {
2957 if (mActiveEntry && mActiveEntry->GetLayoutHistoryState() &&
2958 mBrowsingContext) {
2959 if (XRE_IsContentProcess()) {
2960 dom::ContentChild* contentChild = dom::ContentChild::GetSingleton();
2961 if (contentChild) {
2962 contentChild->SendSynchronizeLayoutHistoryState(
2963 mBrowsingContext, mActiveEntry->GetLayoutHistoryState());
2964 }
2965 } else {
2966 SessionHistoryEntry* entry =
2967 mBrowsingContext->Canonical()->GetActiveSessionHistoryEntry();
2968 if (entry) {
2969 entry->SetLayoutHistoryState(mActiveEntry->GetLayoutHistoryState());
2970 }
2971 }
2972 if (mLoadingEntry &&
2973 mLoadingEntry->mInfo.SharedId() == mActiveEntry->SharedId()) {
2974 mLoadingEntry->mInfo.SetLayoutHistoryState(
2975 mActiveEntry->GetLayoutHistoryState());
2976 }
2977 }
2978
2979 return NS_OK;
2980}
2981
2982void nsDocShell::SetLoadGroupDefaultLoadFlags(nsLoadFlags aLoadFlags) {
2983 if (mLoadGroup) {
2984 mLoadGroup->SetDefaultLoadFlags(aLoadFlags);
2985 } else {
2986 NS_WARNING(NS_DebugBreak(NS_DEBUG_WARNING, "nsDocShell::SetLoadGroupDefaultLoadFlags has no loadGroup to "
"propagate the mode to", nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 2988)
2987 "nsDocShell::SetLoadGroupDefaultLoadFlags has no loadGroup to "NS_DebugBreak(NS_DEBUG_WARNING, "nsDocShell::SetLoadGroupDefaultLoadFlags has no loadGroup to "
"propagate the mode to", nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 2988)
2988 "propagate the mode to")NS_DebugBreak(NS_DEBUG_WARNING, "nsDocShell::SetLoadGroupDefaultLoadFlags has no loadGroup to "
"propagate the mode to", nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 2988)
;
2989 }
2990}
2991
2992nsIScriptGlobalObject* nsDocShell::GetScriptGlobalObject() {
2993 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
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 2993); return
nullptr; } } while (false)
;
2994 return mScriptGlobal;
2995}
2996
2997Document* nsDocShell::GetDocument() {
2998 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
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 2998); return
nullptr; } } while (false)
;
2999 return mDocumentViewer->GetDocument();
3000}
3001
3002Document* nsDocShell::GetExtantDocument() {
3003 return mDocumentViewer ? mDocumentViewer->GetDocument() : nullptr;
3004}
3005
3006nsPIDOMWindowOuter* nsDocShell::GetWindow() {
3007 if (NS_FAILED(EnsureScriptEnvironment())((bool)(__builtin_expect(!!(NS_FAILED_impl(EnsureScriptEnvironment
())), 0)))
) {
3008 return nullptr;
3009 }
3010 return mScriptGlobal;
3011}
3012
3013NS_IMETHODIMPnsresult
3014nsDocShell::GetDomWindow(mozIDOMWindowProxy** aWindow) {
3015 NS_ENSURE_ARG_POINTER(aWindow)do { if ((__builtin_expect(!!(!(aWindow)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aWindow" ") failed", nullptr
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 3015); return
NS_ERROR_INVALID_POINTER; } } while (false)
;
3016
3017 nsresult rv = EnsureScriptEnvironment();
3018 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, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 3018); return rv; } } while (false)
;
3019
3020 RefPtr<nsGlobalWindowOuter> window = mScriptGlobal;
3021 window.forget(aWindow);
3022 return NS_OK;
3023}
3024
3025NS_IMETHODIMPnsresult
3026nsDocShell::GetMessageManager(ContentFrameMessageManager** aMessageManager) {
3027 RefPtr<ContentFrameMessageManager> mm;
3028 if (RefPtr<BrowserChild> browserChild = BrowserChild::GetFrom(this)) {
3029 mm = browserChild->GetMessageManager();
3030 } else if (nsPIDOMWindowOuter* win = GetWindow()) {
3031 mm = win->GetMessageManager();
3032 }
3033 mm.forget(aMessageManager);
3034 return NS_OK;
3035}
3036
3037NS_IMETHODIMPnsresult
3038nsDocShell::GetIsNavigating(bool* aOut) {
3039 *aOut = mIsNavigating;
3040 return NS_OK;
3041}
3042
3043void nsDocShell::ClearFrameHistory(nsISHEntry* aEntry) {
3044 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()", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 3044); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mozilla::SessionHistoryInParent()"
")"); do { MOZ_CrashSequence(__null, 3044); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3045 RefPtr<ChildSHistory> rootSH = GetRootSessionHistory();
3046 if (!rootSH || !aEntry) {
3047 return;
3048 }
3049
3050 rootSH->LegacySHistory()->RemoveFrameEntries(aEntry);
3051}
3052
3053//-------------------------------------
3054//-- Helper Method for Print discovery
3055//-------------------------------------
3056bool nsDocShell::NavigationBlockedByPrinting(bool aDisplayErrorDialog) {
3057 if (!mBrowsingContext->Top()->GetIsPrinting()) {
3058 return false;
3059 }
3060 if (aDisplayErrorDialog) {
3061 DisplayLoadError(NS_ERROR_DOCUMENT_IS_PRINTMODE, nullptr, nullptr, nullptr);
3062 }
3063 return true;
3064}
3065
3066bool nsDocShell::IsNavigationAllowed(bool aDisplayPrintErrorDialog,
3067 bool aCheckIfUnloadFired) {
3068 bool isAllowed = !NavigationBlockedByPrinting(aDisplayPrintErrorDialog) &&
3069 (!aCheckIfUnloadFired || !mFiredUnloadEvent);
3070 if (!isAllowed) {
3071 return false;
3072 }
3073 if (!mDocumentViewer) {
3074 return true;
3075 }
3076 bool firingBeforeUnload;
3077 mDocumentViewer->GetBeforeUnloadFiring(&firingBeforeUnload);
3078 return !firingBeforeUnload;
3079}
3080
3081//*****************************************************************************
3082// nsDocShell::nsIWebNavigation
3083//*****************************************************************************
3084
3085NS_IMETHODIMPnsresult
3086nsDocShell::GetCanGoBack(bool* aCanGoBack) {
3087 *aCanGoBack = false;
3088 if (!IsNavigationAllowed(false)) {
3089 return NS_OK; // JS may not handle returning of an error code
3090 }
3091 RefPtr<ChildSHistory> rootSH = GetRootSessionHistory();
3092 if (rootSH) {
3093 *aCanGoBack = rootSH->CanGo(
3094 -1, StaticPrefs::browser_navigation_requireUserInteraction());
3095 MOZ_LOG(gSHLog, LogLevel::Verbose,do { const ::mozilla::LogModule* moz_real_module = gSHLog; if
((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Verbose)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Verbose, "nsDocShell %p CanGoBack()->%d", this
, *aCanGoBack); } } while (0)
3096 ("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)
;
3097
3098 return NS_OK;
3099 }
3100 return NS_ERROR_FAILURE;
3101}
3102
3103NS_IMETHODIMPnsresult
3104nsDocShell::GetCanGoBackIgnoringUserInteraction(bool* aCanGoBack) {
3105 *aCanGoBack = false;
3106 if (!IsNavigationAllowed(false)) {
3107 return NS_OK; // JS may not handle returning of an error code
3108 }
3109 RefPtr<ChildSHistory> rootSH = GetRootSessionHistory();
3110 if (rootSH) {
3111 *aCanGoBack = rootSH->CanGo(-1, false);
3112 MOZ_LOG(gSHLog, LogLevel::Verbose,do { const ::mozilla::LogModule* moz_real_module = gSHLog; if
((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Verbose)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Verbose, "nsDocShell %p CanGoBackIgnoringUserInteraction()->%d"
, this, *aCanGoBack); } } while (0)
3113 ("nsDocShell %p CanGoBackIgnoringUserInteraction()->%d", this,do { const ::mozilla::LogModule* moz_real_module = gSHLog; if
((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Verbose)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Verbose, "nsDocShell %p CanGoBackIgnoringUserInteraction()->%d"
, this, *aCanGoBack); } } while (0)
3114 *aCanGoBack))do { const ::mozilla::LogModule* moz_real_module = gSHLog; if
((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Verbose)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Verbose, "nsDocShell %p CanGoBackIgnoringUserInteraction()->%d"
, this, *aCanGoBack); } } while (0)
;
3115
3116 return NS_OK;
3117 }
3118 return NS_ERROR_FAILURE;
3119}
3120
3121NS_IMETHODIMPnsresult
3122nsDocShell::GetCanGoForward(bool* aCanGoForward) {
3123 *aCanGoForward = false;
3124 if (!IsNavigationAllowed(false)) {
3125 return NS_OK; // JS may not handle returning of an error code
3126 }
3127 RefPtr<ChildSHistory> rootSH = GetRootSessionHistory();
3128 if (rootSH) {
3129 *aCanGoForward = rootSH->CanGo(
3130 1, StaticPrefs::browser_navigation_requireUserInteraction());
3131 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)
3132 ("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)
;
3133 return NS_OK;
3134 }
3135 return NS_ERROR_FAILURE;
3136}
3137
3138NS_IMETHODIMPnsresult
3139nsDocShell::GoBack(bool aRequireUserInteraction, bool aUserActivation) {
3140 if (!IsNavigationAllowed()) {
3141 return NS_OK; // JS may not handle returning of an error code
3142 }
3143
3144 auto cleanupIsNavigating = MakeScopeExit([&]() { mIsNavigating = false; });
3145 mIsNavigating = true;
3146
3147 RefPtr<ChildSHistory> rootSH = GetRootSessionHistory();
3148 NS_ENSURE_TRUE(rootSH, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(rootSH)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "rootSH" ") failed", nullptr
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 3148); return
NS_ERROR_FAILURE; } } while (false)
;
3149 ErrorResult rv;
3150 rootSH->Go(-1, aRequireUserInteraction, aUserActivation, rv);
3151 return rv.StealNSResult();
3152}
3153
3154NS_IMETHODIMPnsresult
3155nsDocShell::GoForward(bool aRequireUserInteraction, bool aUserActivation) {
3156 if (!IsNavigationAllowed()) {
3157 return NS_OK; // JS may not handle returning of an error code
3158 }
3159
3160 auto cleanupIsNavigating = MakeScopeExit([&]() { mIsNavigating = false; });
3161 mIsNavigating = true;
3162
3163 RefPtr<ChildSHistory> rootSH = GetRootSessionHistory();
3164 NS_ENSURE_TRUE(rootSH, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(rootSH)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "rootSH" ") failed", nullptr
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 3164); return
NS_ERROR_FAILURE; } } while (false)
;
3165 ErrorResult rv;
3166 rootSH->Go(1, aRequireUserInteraction, aUserActivation, rv);
3167 return rv.StealNSResult();
3168}
3169
3170// XXX(nika): We may want to stop exposing this API in the child process? Going
3171// to a specific index from multiple different processes could definitely race.
3172NS_IMETHODIMPnsresult
3173nsDocShell::GotoIndex(int32_t aIndex, bool aUserActivation) {
3174 if (!IsNavigationAllowed()) {
3175 return NS_OK; // JS may not handle returning of an error code
3176 }
3177
3178 auto cleanupIsNavigating = MakeScopeExit([&]() { mIsNavigating = false; });
3179 mIsNavigating = true;
3180
3181 RefPtr<ChildSHistory> rootSH = GetRootSessionHistory();
3182 NS_ENSURE_TRUE(rootSH, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(rootSH)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "rootSH" ") failed", nullptr
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 3182); return
NS_ERROR_FAILURE; } } while (false)
;
3183
3184 ErrorResult rv;
3185 rootSH->GotoIndex(aIndex, aIndex - rootSH->Index(), false, aUserActivation,
3186 rv);
3187 return rv.StealNSResult();
3188}
3189
3190nsresult nsDocShell::LoadURI(nsIURI* aURI,
3191 const LoadURIOptions& aLoadURIOptions) {
3192 if (!IsNavigationAllowed()) {
3193 return NS_OK; // JS may not handle returning of an error code
3194 }
3195 RefPtr<nsDocShellLoadState> loadState;
3196 nsresult rv = nsDocShellLoadState::CreateFromLoadURIOptions(
3197 mBrowsingContext, aURI, aLoadURIOptions, getter_AddRefs(loadState));
3198 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", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 3198); AnnotateMozCrashReason("MOZ_ASSERT" "(" "rv != NS_ERROR_MALFORMED_URI"
")"); do { MOZ_CrashSequence(__null, 3198); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3199 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) || !loadState) {
3200 return NS_ERROR_FAILURE;
3201 }
3202
3203 return LoadURI(loadState, true);
3204}
3205
3206NS_IMETHODIMPnsresult
3207nsDocShell::LoadURIFromScript(nsIURI* aURI,
3208 JS::Handle<JS::Value> aLoadURIOptions,
3209 JSContext* aCx) {
3210 // generate dictionary for aLoadURIOptions and forward call
3211 LoadURIOptions loadURIOptions;
3212 if (!loadURIOptions.Init(aCx, aLoadURIOptions)) {
3213 return NS_ERROR_INVALID_ARG;
3214 }
3215 return LoadURI(aURI, loadURIOptions);
3216}
3217
3218nsresult nsDocShell::FixupAndLoadURIString(
3219 const nsAString& aURIString, const LoadURIOptions& aLoadURIOptions) {
3220 if (!IsNavigationAllowed()) {
3221 return NS_OK; // JS may not handle returning of an error code
3222 }
3223
3224 RefPtr<nsDocShellLoadState> loadState;
3225 nsresult rv = nsDocShellLoadState::CreateFromLoadURIOptions(
3226 mBrowsingContext, aURIString, aLoadURIOptions, getter_AddRefs(loadState));
3227
3228 uint32_t loadFlags = aLoadURIOptions.mLoadFlags;
3229 if (NS_ERROR_MALFORMED_URI == rv) {
3230 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)
3231 ("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)
3232 "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)
3233 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)
;
3234
3235 // We need to store a session history entry. We don't have a valid URI, so
3236 // we use about:blank instead.
3237 nsCOMPtr<nsIURI> uri;
3238 MOZ_ALWAYS_SUCCEEDS(NS_NewURI(getter_AddRefs(uri), "about:blank"_ns))do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(NS_NewURI(getter_AddRefs(uri), "about:blank"_ns))), 1)))), 1
))) { } else { do { do { } while (false); MOZ_ReportCrash("" "NS_SUCCEEDED(NS_NewURI(getter_AddRefs(uri), \"about:blank\"_ns))"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 3238); AnnotateMozCrashReason
("MOZ_CRASH(" "NS_SUCCEEDED(NS_NewURI(getter_AddRefs(uri), \"about:blank\"_ns))"
")"); do { MOZ_CrashSequence(__null, 3238); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
;
3239 nsCOMPtr<nsIPrincipal> triggeringPrincipal;
3240 if (aLoadURIOptions.mTriggeringPrincipal) {
3241 triggeringPrincipal = aLoadURIOptions.mTriggeringPrincipal;
3242 } else {
3243 triggeringPrincipal = nsContentUtils::GetSystemPrincipal();
3244 }
3245 if (mozilla::SessionHistoryInParent()) {
3246 UniquePtr<SessionHistoryInfo> previousActiveEntry(mActiveEntry.release());
3247 mActiveEntry = MakeUnique<SessionHistoryInfo>(
3248 uri, triggeringPrincipal, nullptr, nullptr, nullptr,
3249 nsLiteralCString("text/html"));
3250 mBrowsingContext->SetActiveSessionHistoryEntry(
3251 Nothing(), mActiveEntry.get(), previousActiveEntry.get(),
3252 MAKE_LOAD_TYPE(LOAD_NORMAL, loadFlags)((LOAD_NORMAL) | ((loadFlags) << 16)),
3253 /* aUpdatedCacheKey = */ 0);
3254 }
3255 if (DisplayLoadError(rv, nullptr, PromiseFlatStringTPromiseFlatString<char16_t>(aURIString).get(),
3256 nullptr) &&
3257 (loadFlags & LOAD_FLAGS_ERROR_LOAD_CHANGES_RV) != 0) {
3258 return NS_ERROR_LOAD_SHOWED_ERRORPAGE;
3259 }
3260 }
3261
3262 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) || !loadState) {
3263 return NS_ERROR_FAILURE;
3264 }
3265
3266 return LoadURI(loadState, true);
3267}
3268
3269NS_IMETHODIMPnsresult
3270nsDocShell::FixupAndLoadURIStringFromScript(
3271 const nsAString& aURIString, JS::Handle<JS::Value> aLoadURIOptions,
3272 JSContext* aCx) {
3273 // generate dictionary for aLoadURIOptions and forward call
3274 LoadURIOptions loadURIOptions;
3275 if (!loadURIOptions.Init(aCx, aLoadURIOptions)) {
3276 return NS_ERROR_INVALID_ARG;
3277 }
3278 return FixupAndLoadURIString(aURIString, loadURIOptions);
3279}
3280
3281void nsDocShell::UnblockEmbedderLoadEventForFailure(bool aFireFrameErrorEvent) {
3282 // If we're not in a content frame, or are at a BrowsingContext tree boundary,
3283 // such as the content-chrome boundary, don't fire the error event.
3284 if (mBrowsingContext->IsTopContent() || mBrowsingContext->IsChrome()) {
3285 return;
3286 }
3287
3288 // If embedder is same-process, then unblocking the load event is already
3289 // handled by nsDocLoader. Fire the error event on our embedder element if
3290 // requested.
3291 //
3292 // XXX: Bug 1440212 is looking into potentially changing this behaviour to act
3293 // more like the remote case when in-process.
3294 RefPtr<Element> element = mBrowsingContext->GetEmbedderElement();
3295 if (element) {
3296 if (aFireFrameErrorEvent) {
3297 if (RefPtr<nsFrameLoaderOwner> flo = do_QueryObject(element)) {
3298 if (RefPtr<nsFrameLoader> fl = flo->GetFrameLoader()) {
3299 fl->FireErrorEvent();
3300 }
3301 }
3302 }
3303 return;
3304 }
3305
3306 // If we have a cross-process parent document, we must notify it that we no
3307 // longer block its load event. This is necessary for OOP sub-documents
3308 // because error documents do not result in a call to
3309 // SendMaybeFireEmbedderLoadEvents via any of the normal call paths.
3310 // (Obviously, we must do this before any of the returns below.)
3311 RefPtr<BrowserChild> browserChild = BrowserChild::GetFrom(this);
3312 if (browserChild &&
3313 !mBrowsingContext->GetParentWindowContext()->IsInProcess()) {
3314 mozilla::Unused << browserChild->SendMaybeFireEmbedderLoadEvents(
3315 aFireFrameErrorEvent ? EmbedderElementEventType::ErrorEvent
3316 : EmbedderElementEventType::NoEvent);
3317 }
3318}
3319
3320NS_IMETHODIMPnsresult
3321nsDocShell::DisplayLoadError(nsresult aError, nsIURI* aURI,
3322 const char16_t* aURL, nsIChannel* aFailedChannel,
3323 bool* aDisplayedErrorPage) {
3324 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
)
3325 ("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
)
3326 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
)
;
3327
3328 *aDisplayedErrorPage = false;
3329 // Get prompt and string bundle services
3330 nsCOMPtr<nsIPrompt> prompter;
3331 nsCOMPtr<nsIStringBundle> stringBundle;
3332 GetPromptAndStringBundle(getter_AddRefs(prompter),
3333 getter_AddRefs(stringBundle));
3334
3335 NS_ENSURE_TRUE(stringBundle, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(stringBundle)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "stringBundle" ") failed"
, nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 3335); return NS_ERROR_FAILURE; } } while (false)
;
3336 NS_ENSURE_TRUE(prompter, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(prompter)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "prompter" ") failed", nullptr
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 3336); return
NS_ERROR_FAILURE; } } while (false)
;
3337
3338 const char* error = nullptr;
3339 // The key used to select the appropriate error message from the properties
3340 // file.
3341 const char* errorDescriptionID = nullptr;
3342 AutoTArray<nsString, 3> formatStrs;
3343 bool addHostPort = false;
3344 bool isBadStsCertError = false;
3345 nsresult rv = NS_OK;
3346 nsAutoString messageStr;
3347 nsAutoCString cssClass;
3348 nsAutoCString errorPage;
3349
3350 errorPage.AssignLiteral("neterror");
3351
3352 // Turn the error code into a human readable error message.
3353 if (NS_ERROR_UNKNOWN_PROTOCOL == aError) {
3354 NS_ENSURE_ARG_POINTER(aURI)do { if ((__builtin_expect(!!(!(aURI)), 0))) { NS_DebugBreak(
NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aURI" ") failed", nullptr
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 3354); return
NS_ERROR_INVALID_POINTER; } } while (false)
;
3355
3356 // Extract the schemes into a comma delimited list.
3357 nsAutoCString scheme;
3358 aURI->GetScheme(scheme);
3359 CopyASCIItoUTF16(scheme, *formatStrs.AppendElement());
3360 nsCOMPtr<nsINestedURI> nestedURI = do_QueryInterface(aURI);
3361 while (nestedURI) {
3362 nsCOMPtr<nsIURI> tempURI;
3363 nsresult rv2;
3364 rv2 = nestedURI->GetInnerURI(getter_AddRefs(tempURI));
3365 if (NS_SUCCEEDED(rv2)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv2)), 1))) && tempURI) {
3366 tempURI->GetScheme(scheme);
3367 formatStrs[0].AppendLiteral(", ");
3368 AppendASCIItoUTF16(scheme, formatStrs[0]);
3369 }
3370 nestedURI = do_QueryInterface(tempURI);
3371 }
3372 error = "unknownProtocolFound";
3373 } else if (NS_ERROR_NET_EMPTY_RESPONSE == aError) {
3374 NS_ENSURE_ARG_POINTER(aURI)do { if ((__builtin_expect(!!(!(aURI)), 0))) { NS_DebugBreak(
NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aURI" ") failed", nullptr
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 3374); return
NS_ERROR_INVALID_POINTER; } } while (false)
;
3375 error = "httpErrorPage";
3376 } else if (NS_ERROR_NET_ERROR_RESPONSE == aError) {
3377 NS_ENSURE_ARG_POINTER(aURI)do { if ((__builtin_expect(!!(!(aURI)), 0))) { NS_DebugBreak(
NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aURI" ") failed", nullptr
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 3377); return
NS_ERROR_INVALID_POINTER; } } while (false)
;
3378 error = "serverError";
3379 } else if (NS_ERROR_FILE_NOT_FOUND == aError) {
3380 NS_ENSURE_ARG_POINTER(aURI)do { if ((__builtin_expect(!!(!(aURI)), 0))) { NS_DebugBreak(
NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aURI" ") failed", nullptr
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 3380); return
NS_ERROR_INVALID_POINTER; } } while (false)
;
3381 error = "fileNotFound";
3382 } else if (NS_ERROR_FILE_ACCESS_DENIED == aError) {
3383 NS_ENSURE_ARG_POINTER(aURI)do { if ((__builtin_expect(!!(!(aURI)), 0))) { NS_DebugBreak(
NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aURI" ") failed", nullptr
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 3383); return
NS_ERROR_INVALID_POINTER; } } while (false)
;
3384 error = "fileAccessDenied";
3385 } else if (NS_ERROR_UNKNOWN_HOST == aError) {
3386 NS_ENSURE_ARG_POINTER(aURI)do { if ((__builtin_expect(!!(!(aURI)), 0))) { NS_DebugBreak(
NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aURI" ") failed", nullptr
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 3386); return
NS_ERROR_INVALID_POINTER; } } while (false)
;
3387 // Get the host
3388 nsAutoCString host;
3389 nsCOMPtr<nsIURI> innermostURI = NS_GetInnermostURI(aURI);
3390 innermostURI->GetHost(host);
3391 CopyUTF8toUTF16(host, *formatStrs.AppendElement());
3392 errorDescriptionID = "dnsNotFound2";
3393 error = "dnsNotFound";
3394 } else if (NS_ERROR_CONNECTION_REFUSED == aError ||
3395 NS_ERROR_PROXY_BAD_GATEWAY == aError) {
3396 NS_ENSURE_ARG_POINTER(aURI)do { if ((__builtin_expect(!!(!(aURI)), 0))) { NS_DebugBreak(
NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aURI" ") failed", nullptr
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 3396); return
NS_ERROR_INVALID_POINTER; } } while (false)
;
3397 addHostPort = true;
3398 error = "connectionFailure";
3399 } else if (NS_ERROR_NET_INTERRUPT == aError) {
3400 NS_ENSURE_ARG_POINTER(aURI)do { if ((__builtin_expect(!!(!(aURI)), 0))) { NS_DebugBreak(
NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aURI" ") failed", nullptr
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 3400); return
NS_ERROR_INVALID_POINTER; } } while (false)
;
3401 addHostPort = true;
3402 error = "netInterrupt";
3403 } else if (NS_ERROR_NET_TIMEOUT == aError ||
3404 NS_ERROR_PROXY_GATEWAY_TIMEOUT == aError ||
3405 NS_ERROR_NET_TIMEOUT_EXTERNAL == aError) {
3406 NS_ENSURE_ARG_POINTER(aURI)do { if ((__builtin_expect(!!(!(aURI)), 0))) { NS_DebugBreak(
NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aURI" ") failed", nullptr
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 3406); return
NS_ERROR_INVALID_POINTER; } } while (false)
;
3407 // Get the host
3408 nsAutoCString host;
3409 aURI->GetHost(host);
3410 CopyUTF8toUTF16(host, *formatStrs.AppendElement());
3411 error = "netTimeout";
3412 } else if (NS_ERROR_CSP_FRAME_ANCESTOR_VIOLATION == aError ||
3413 NS_ERROR_CSP_FORM_ACTION_VIOLATION == aError) {
3414 // CSP error
3415 cssClass.AssignLiteral("neterror");
3416 error = "cspBlocked";
3417 } else if (NS_ERROR_XFO_VIOLATION == aError) {
3418 // XFO error
3419 cssClass.AssignLiteral("neterror");
3420 error = "xfoBlocked";
3421 } else if (NS_ERROR_GET_MODULE(aError) == NS_ERROR_MODULE_SECURITY21) {
3422 nsCOMPtr<nsINSSErrorsService> nsserr =
3423 do_GetService(NS_NSS_ERRORS_SERVICE_CONTRACTID"@mozilla.org/nss_errors_service;1");
3424
3425 uint32_t errorClass;
3426 if (!nsserr || NS_FAILED(nsserr->GetErrorClass(aError, &errorClass))((bool)(__builtin_expect(!!(NS_FAILED_impl(nsserr->GetErrorClass
(aError, &errorClass))), 0)))
) {
3427 errorClass = nsINSSErrorsService::ERROR_CLASS_SSL_PROTOCOL;
3428 }
3429
3430 nsCOMPtr<nsITransportSecurityInfo> tsi;
3431 if (aFailedChannel) {
3432 aFailedChannel->GetSecurityInfo(getter_AddRefs(tsi));
3433 }
3434 if (tsi) {
3435 uint32_t securityState;
3436 tsi->GetSecurityState(&securityState);
3437 if (securityState & nsIWebProgressListener::STATE_USES_SSL_3) {
3438 error = "sslv3Used";
3439 addHostPort = true;
3440 } else if (securityState &
3441 nsIWebProgressListener::STATE_USES_WEAK_CRYPTO) {
3442 error = "weakCryptoUsed";
Value stored to 'error' is never read
3443 addHostPort = true;
3444 }
3445 } else {
3446 // No channel, let's obtain the generic error message
3447 if (nsserr) {
3448 nsserr->GetErrorMessage(aError, messageStr);
3449 }
3450 }
3451 // We don't have a message string here anymore but DisplayLoadError
3452 // requires a non-empty messageStr.
3453 messageStr.Truncate();
3454 messageStr.AssignLiteral(u" ");
3455 if (errorClass == nsINSSErrorsService::ERROR_CLASS_BAD_CERT) {
3456 error = "nssBadCert";
3457
3458 // If this is an HTTP Strict Transport Security host or a pinned host
3459 // and the certificate is bad, don't allow overrides (RFC 6797 section
3460 // 12.1).
3461 bool isStsHost = false;
3462 bool isPinnedHost = false;
3463 OriginAttributes attrsForHSTS;
3464 if (aFailedChannel) {
3465 StoragePrincipalHelper::GetOriginAttributesForHSTS(aFailedChannel,
3466 attrsForHSTS);
3467 } else {
3468 attrsForHSTS = GetOriginAttributes();
3469 }
3470
3471 if (XRE_IsParentProcess()) {
3472 nsCOMPtr<nsISiteSecurityService> sss =
3473 do_GetService(NS_SSSERVICE_CONTRACTID"@mozilla.org/ssservice;1", &rv);
3474 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, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 3474); return rv; } } while (false)
;
3475 rv = sss->IsSecureURI(aURI, attrsForHSTS, &isStsHost);
3476 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, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 3476); return rv; } } while (false)
;
3477 } else {
3478 mozilla::dom::ContentChild* cc =
3479 mozilla::dom::ContentChild::GetSingleton();
3480 cc->SendIsSecureURI(aURI, attrsForHSTS, &isStsHost);
3481 }
3482 nsCOMPtr<nsIPublicKeyPinningService> pkps =
3483 do_GetService(NS_PKPSERVICE_CONTRACTID"@mozilla.org/security/publickeypinningservice;1", &rv);
3484 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, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 3484); return rv; } } while (false)
;
3485 rv = pkps->HostHasPins(aURI, &isPinnedHost);
3486
3487 if (Preferences::GetBool("browser.xul.error_pages.expert_bad_cert",
3488 false)) {
3489 cssClass.AssignLiteral("expertBadCert");
3490 }
3491
3492 // HSTS/pinning takes precedence over the expert bad cert pref. We
3493 // never want to show the "Add Exception" button for these sites.
3494 // In the future we should differentiate between an HSTS host and a
3495 // pinned host and display a more informative message to the user.
3496 if (isStsHost || isPinnedHost) {
3497 isBadStsCertError = true;
3498 cssClass.AssignLiteral("badStsCert");
3499 }
3500
3501 errorPage.Assign("certerror");
3502 } else {
3503 error = "nssFailure2";
3504 }
3505 } else if (NS_ERROR_PHISHING_URI == aError ||
3506 NS_ERROR_MALWARE_URI == aError ||
3507 NS_ERROR_UNWANTED_URI == aError ||
3508 NS_ERROR_HARMFUL_URI == aError) {
3509 nsAutoCString host;
3510 aURI->GetHost(host);
3511 CopyUTF8toUTF16(host, *formatStrs.AppendElement());
3512
3513 // Malware and phishing detectors may want to use an alternate error
3514 // page, but if the pref's not set, we'll fall back on the standard page
3515 nsAutoCString alternateErrorPage;
3516 nsresult rv = Preferences::GetCString("urlclassifier.alternate_error_page",
3517 alternateErrorPage);
3518 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
3519 errorPage.Assign(alternateErrorPage);
3520 }
3521
3522 if (NS_ERROR_PHISHING_URI == aError) {
3523 error = "deceptiveBlocked";
3524 } else if (NS_ERROR_MALWARE_URI == aError) {
3525 error = "malwareBlocked";
3526 } else if (NS_ERROR_UNWANTED_URI == aError) {
3527 error = "unwantedBlocked";
3528 } else if (NS_ERROR_HARMFUL_URI == aError) {
3529 error = "harmfulBlocked";
3530 }
3531
3532 cssClass.AssignLiteral("blacklist");
3533 } else if (NS_ERROR_CONTENT_CRASHED == aError) {
3534 errorPage.AssignLiteral("tabcrashed");
3535 error = "tabcrashed";
3536
3537 RefPtr<EventTarget> handler = mChromeEventHandler;
3538 if (handler) {
3539 nsCOMPtr<Element> element = do_QueryInterface(handler);
3540 element->GetAttribute(u"crashedPageTitle"_ns, messageStr);
3541 }
3542
3543 // DisplayLoadError requires a non-empty messageStr to proceed and call
3544 // LoadErrorPage. If the page doesn't have a title, we will use a blank
3545 // space which will be trimmed and thus treated as empty by the front-end.
3546 if (messageStr.IsEmpty()) {
3547 messageStr.AssignLiteral(u" ");
3548 }
3549 } else if (NS_ERROR_FRAME_CRASHED == aError) {
3550 errorPage.AssignLiteral("framecrashed");
3551 error = "framecrashed";
3552 messageStr.AssignLiteral(u" ");
3553 } else if (NS_ERROR_BUILDID_MISMATCH == aError) {
3554 errorPage.AssignLiteral("restartrequired");
3555 error = "restartrequired";
3556
3557 // DisplayLoadError requires a non-empty messageStr to proceed and call
3558 // LoadErrorPage. If the page doesn't have a title, we will use a blank
3559 // space which will be trimmed and thus treated as empty by the front-end.
3560 if (messageStr.IsEmpty()) {
3561 messageStr.AssignLiteral(u" ");
3562 }
3563 } else {
3564 // Errors requiring simple formatting
3565 switch (aError) {
3566 case NS_ERROR_MALFORMED_URI:
3567 // URI is malformed
3568 error = "malformedURI";
3569 errorDescriptionID = "malformedURI2";
3570 break;
3571 case NS_ERROR_REDIRECT_LOOP:
3572 // Doc failed to load because the server generated too many redirects
3573 error = "redirectLoop";
3574 break;
3575 case NS_ERROR_UNKNOWN_SOCKET_TYPE:
3576 // Doc failed to load because PSM is not installed
3577 error = "unknownSocketType";
3578 break;
3579 case NS_ERROR_NET_RESET:
3580 // Doc failed to load because the server kept reseting the connection
3581 // before we could read any data from it
3582 error = "netReset";
3583 break;
3584 case NS_ERROR_DOCUMENT_NOT_CACHED:
3585 // Doc failed to load because the cache does not contain a copy of
3586 // the document.
3587 error = "notCached";
3588 break;
3589 case NS_ERROR_OFFLINE:
3590 // Doc failed to load because we are offline.
3591 error = "netOffline";
3592 break;
3593 case NS_ERROR_DOCUMENT_IS_PRINTMODE:
3594 // Doc navigation attempted while Printing or Print Preview
3595 error = "isprinting";
3596 break;
3597 case NS_ERROR_PORT_ACCESS_NOT_ALLOWED:
3598 // Port blocked for security reasons
3599 addHostPort = true;
3600 error = "deniedPortAccess";
3601 break;
3602 case NS_ERROR_UNKNOWN_PROXY_HOST:
3603 // Proxy hostname could not be resolved.
3604 error = "proxyResolveFailure";
3605 break;
3606 case NS_ERROR_PROXY_CONNECTION_REFUSED:
3607 case NS_ERROR_PROXY_FORBIDDEN:
3608 case NS_ERROR_PROXY_NOT_IMPLEMENTED:
3609 case NS_ERROR_PROXY_AUTHENTICATION_FAILED:
3610 case NS_ERROR_PROXY_TOO_MANY_REQUESTS:
3611 // Proxy connection was refused.
3612 error = "proxyConnectFailure";
3613 break;
3614 case NS_ERROR_INVALID_CONTENT_ENCODING:
3615 // Bad Content Encoding.
3616 error = "contentEncodingError";
3617 break;
3618 case NS_ERROR_UNSAFE_CONTENT_TYPE:
3619 // Channel refused to load from an unrecognized content type.
3620 error = "unsafeContentType";
3621 break;
3622 case NS_ERROR_CORRUPTED_CONTENT:
3623 // Broken Content Detected. e.g. Content-MD5 check failure.
3624 error = "corruptedContentErrorv2";
3625 break;
3626 case NS_ERROR_INTERCEPTION_FAILED:
3627 // ServiceWorker intercepted request, but something went wrong.
3628 error = "corruptedContentErrorv2";
3629 break;
3630 case NS_ERROR_NET_INADEQUATE_SECURITY:
3631 // Server negotiated bad TLS for HTTP/2.
3632 error = "inadequateSecurityError";
3633 addHostPort = true;
3634 break;
3635 case NS_ERROR_BLOCKED_BY_POLICY:
3636 // Page blocked by policy
3637 error = "blockedByPolicy";
3638 break;
3639 case NS_ERROR_DOM_COOP_FAILED:
3640 error = "blockedByCOOP";
3641 errorDescriptionID = "blockedByCORP";
3642 break;
3643 case NS_ERROR_DOM_COEP_FAILED:
3644 error = "blockedByCOEP";
3645 errorDescriptionID = "blockedByCORP";
3646 break;
3647 case NS_ERROR_DOM_INVALID_HEADER_VALUE:
3648 error = "invalidHeaderValue";
3649 break;
3650 case NS_ERROR_NET_HTTP2_SENT_GOAWAY:
3651 case NS_ERROR_NET_HTTP3_PROTOCOL_ERROR:
3652 // HTTP/2 or HTTP/3 stack detected a protocol error
3653 error = "networkProtocolError";
3654 break;
3655 case NS_ERROR_BASIC_HTTP_AUTH_DISABLED:
3656 error = "basicHttpAuthDisabled";
3657 break;
3658 default:
3659 break;
3660 }
3661 }
3662
3663 nsresult delegateErrorCode = aError;
3664 // If the HTTPS-Only Mode upgraded this request and the upgrade might have
3665 // caused this error, we replace the error-page with about:httpsonlyerror
3666 if (nsHTTPSOnlyUtils::CouldBeHttpsOnlyError(aFailedChannel, aError)) {
3667 errorPage.AssignLiteral("httpsonlyerror");
3668 delegateErrorCode = NS_ERROR_HTTPS_ONLY;
3669 } else if (isBadStsCertError) {
3670 delegateErrorCode = NS_ERROR_BAD_HSTS_CERT;
3671 }
3672
3673 if (nsCOMPtr<nsILoadURIDelegate> loadURIDelegate = GetLoadURIDelegate()) {
3674 nsCOMPtr<nsIURI> errorPageURI;
3675 rv = loadURIDelegate->HandleLoadError(
3676 aURI, delegateErrorCode, NS_ERROR_GET_MODULE(delegateErrorCode),
3677 getter_AddRefs(errorPageURI));
3678 // If the docshell is going away there's no point in showing an error page.
3679 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) || mIsBeingDestroyed) {
3680 *aDisplayedErrorPage = false;
3681 return NS_OK;
3682 }
3683
3684 if (errorPageURI) {
3685 *aDisplayedErrorPage =
3686 NS_SUCCEEDED(LoadErrorPage(errorPageURI, aURI, aFailedChannel))((bool)(__builtin_expect(!!(!NS_FAILED_impl(LoadErrorPage(errorPageURI
, aURI, aFailedChannel))), 1)))
;
3687 return NS_OK;
3688 }
3689 }
3690
3691 // Test if the error should be displayed
3692 if (!error) {
3693 return NS_OK;
3694 }
3695
3696 if (!errorDescriptionID) {
3697 errorDescriptionID = error;
3698 }
3699
3700 Telemetry::AccumulateCategoricalKeyed(
3701 IsSubframe() ? "frame"_ns : "top"_ns,
3702 mozilla::dom::LoadErrorToTelemetryLabel(aError));
3703
3704 // Test if the error needs to be formatted
3705 if (!messageStr.IsEmpty()) {
3706 // already obtained message
3707 } else {
3708 if (addHostPort) {
3709 // Build up the host:port string.
3710 nsAutoCString hostport;
3711 if (aURI) {
3712 aURI->GetHostPort(hostport);
3713 } else {
3714 hostport.Assign('?');
3715 }
3716 CopyUTF8toUTF16(hostport, *formatStrs.AppendElement());
3717 }
3718
3719 nsAutoCString spec;
3720 rv = NS_ERROR_NOT_AVAILABLE;
3721 auto& nextFormatStr = *formatStrs.AppendElement();
3722 if (aURI) {
3723 // displaying "file://" is aesthetically unpleasing and could even be
3724 // confusing to the user
3725 if (aURI->SchemeIs("file")) {
3726 aURI->GetPathQueryRef(spec);
3727 } else {
3728 aURI->GetSpec(spec);
3729 }
3730
3731 nsCOMPtr<nsITextToSubURI> textToSubURI(
3732 do_GetService(NS_ITEXTTOSUBURI_CONTRACTID"@mozilla.org/intl/texttosuburi;1", &rv));
3733 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
3734 rv = textToSubURI->UnEscapeURIForUI(spec, nextFormatStr);
3735 }
3736 } else {
3737 spec.Assign('?');
3738 }
3739 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3740 CopyUTF8toUTF16(spec, nextFormatStr);
3741 }
3742 rv = NS_OK;
3743
3744 nsAutoString str;
3745 rv =
3746 stringBundle->FormatStringFromName(errorDescriptionID, formatStrs, str);
3747 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, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 3747); return rv; } } while (false)
;
3748 messageStr.Assign(str);
3749 }
3750
3751 // Display the error as a page or an alert prompt
3752 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, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 3752); return NS_ERROR_FAILURE; } } while (false)
;
3753
3754 if ((NS_ERROR_NET_INTERRUPT == aError || NS_ERROR_NET_RESET == aError) &&
3755 aURI->SchemeIs("https")) {
3756 // Maybe TLS intolerant. Treat this as an SSL error.
3757 error = "nssFailure2";
3758 }
3759
3760 if (mBrowsingContext->GetUseErrorPages()) {
3761 // Display an error page
3762 nsresult loadedPage =
3763 LoadErrorPage(aURI, aURL, errorPage.get(), error, messageStr.get(),
3764 cssClass.get(), aFailedChannel);
3765 *aDisplayedErrorPage = NS_SUCCEEDED(loadedPage)((bool)(__builtin_expect(!!(!NS_FAILED_impl(loadedPage)), 1))
)
;
3766 } else {
3767 // The prompter reqires that our private window has a document (or it
3768 // asserts). Satisfy that assertion now since GetDoc will force
3769 // creation of one if it hasn't already been created.
3770 if (mScriptGlobal) {
3771 Unused << mScriptGlobal->GetDoc();
3772 }
3773
3774 // Display a message box
3775 prompter->Alert(nullptr, messageStr.get());
3776 }
3777
3778 return NS_OK;
3779}
3780
3781#define PREF_SAFEBROWSING_ALLOWOVERRIDE"browser.safebrowsing.allowOverride" "browser.safebrowsing.allowOverride"
3782
3783nsresult nsDocShell::LoadErrorPage(nsIURI* aURI, const char16_t* aURL,
3784 const char* aErrorPage,
3785 const char* aErrorType,
3786 const char16_t* aDescription,
3787 const char* aCSSClass,
3788 nsIChannel* aFailedChannel) {
3789 if (mIsBeingDestroyed) {
3790 return NS_ERROR_NOT_AVAILABLE;
3791 }
3792
3793#if defined(DEBUG1)
3794 if (MOZ_LOG_TEST(gDocShellLog, LogLevel::Debug)(__builtin_expect(!!(mozilla::detail::log_test(gDocShellLog, LogLevel
::Debug)), 0))
) {
3795 nsAutoCString chanName;
3796 if (aFailedChannel) {
3797 aFailedChannel->GetName(chanName);
3798 } else {
3799 chanName.AssignLiteral("<no channel>");
3800 }
3801
3802 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)
3803 ("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)
3804 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)
3805 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)
;
3806 }
3807#endif
3808
3809 nsAutoCString url;
3810 if (aURI) {
3811 nsresult rv = aURI->GetSpec(url);
3812 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, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 3812); return rv; } } while (false)
;
3813 } else if (aURL) {
3814 CopyUTF16toUTF8(MakeStringSpan(aURL), url);
3815 } else {
3816 return NS_ERROR_INVALID_POINTER;
3817 }
3818
3819 // Create a URL to pass all the error information through to the page.
3820
3821#undef SAFE_ESCAPE
3822#define SAFE_ESCAPE(output, input, params)if (NS_warn_if_impl(!NS_Escape(input, output, params), "!NS_Escape(input, output, params)"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 3822)) {
return NS_ERROR_OUT_OF_MEMORY; }
\
3823 if (NS_WARN_IF(!NS_Escape(input, output, params))NS_warn_if_impl(!NS_Escape(input, output, params), "!NS_Escape(input, output, params)"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 3823)
) { \
3824 return NS_ERROR_OUT_OF_MEMORY; \
3825 }
3826
3827 nsCString escapedUrl, escapedError, escapedDescription, escapedCSSClass;
3828 SAFE_ESCAPE(escapedUrl, url, url_Path)if (NS_warn_if_impl(!NS_Escape(url, escapedUrl, url_Path), "!NS_Escape(url, escapedUrl, url_Path)"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 3828)) {
return NS_ERROR_OUT_OF_MEMORY; }
;
3829 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)"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 3829)) {
return NS_ERROR_OUT_OF_MEMORY; }
;
3830 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)"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 3831)) {
return NS_ERROR_OUT_OF_MEMORY; }
3831 url_Path)if (NS_warn_if_impl(!NS_Escape(NS_ConvertUTF16toUTF8(aDescription
), escapedDescription, url_Path), "!NS_Escape(NS_ConvertUTF16toUTF8(aDescription), escapedDescription, url_Path)"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 3831)) {
return NS_ERROR_OUT_OF_MEMORY; }
;
3832 if (aCSSClass) {
3833 nsCString cssClass(aCSSClass);
3834 SAFE_ESCAPE(escapedCSSClass, cssClass, url_Path)if (NS_warn_if_impl(!NS_Escape(cssClass, escapedCSSClass, url_Path
), "!NS_Escape(cssClass, escapedCSSClass, url_Path)", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 3834)) { return NS_ERROR_OUT_OF_MEMORY; }
;
3835 }
3836 nsCString errorPageUrl("about:");
3837 errorPageUrl.AppendASCII(aErrorPage);
3838 errorPageUrl.AppendLiteral("?e=");
3839
3840 errorPageUrl.AppendASCII(escapedError.get());
3841 errorPageUrl.AppendLiteral("&u=");
3842 errorPageUrl.AppendASCII(escapedUrl.get());
3843 if ((strcmp(aErrorPage, "blocked") == 0) &&
3844 Preferences::GetBool(PREF_SAFEBROWSING_ALLOWOVERRIDE"browser.safebrowsing.allowOverride", true)) {
3845 errorPageUrl.AppendLiteral("&o=1");
3846 }
3847 if (!escapedCSSClass.IsEmpty()) {
3848 errorPageUrl.AppendLiteral("&s=");
3849 errorPageUrl.AppendASCII(escapedCSSClass.get());
3850 }
3851 errorPageUrl.AppendLiteral("&c=UTF-8");
3852
3853 nsCOMPtr<nsICaptivePortalService> cps = do_GetService(NS_CAPTIVEPORTAL_CID{ 0xbdbe0555, 0xfc3d, 0x4f7b, {0x92, 0x05, 0xc3, 0x09, 0xce, 0xb2
, 0xd6, 0x41}}
);
3854 int32_t cpsState;
3855 if (cps && NS_SUCCEEDED(cps->GetState(&cpsState))((bool)(__builtin_expect(!!(!NS_FAILED_impl(cps->GetState(
&cpsState))), 1)))
&&
3856 cpsState == nsICaptivePortalService::LOCKED_PORTAL) {
3857 errorPageUrl.AppendLiteral("&captive=true");
3858 }
3859
3860 errorPageUrl.AppendLiteral("&d=");
3861 errorPageUrl.AppendASCII(escapedDescription.get());
3862
3863 nsCOMPtr<nsIURI> errorPageURI;
3864 nsresult rv = NS_NewURI(getter_AddRefs(errorPageURI), errorPageUrl);
3865 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, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 3865); return rv; } } while (false)
;
3866
3867 return LoadErrorPage(errorPageURI, aURI, aFailedChannel);
3868}
3869
3870nsresult nsDocShell::LoadErrorPage(nsIURI* aErrorURI, nsIURI* aFailedURI,
3871 nsIChannel* aFailedChannel) {
3872 mFailedChannel = aFailedChannel;
3873 mFailedURI = aFailedURI;
3874 mFailedLoadType = mLoadType;
3875
3876 if (mLSHE) {
3877 // Abandon mLSHE's BFCache entry and create a new one. This way, if
3878 // we go back or forward to another SHEntry with the same doc
3879 // identifier, the error page won't persist.
3880 mLSHE->AbandonBFCacheEntry();
3881 }
3882
3883 RefPtr<nsDocShellLoadState> loadState = new nsDocShellLoadState(aErrorURI);
3884 loadState->SetTriggeringPrincipal(nsContentUtils::GetSystemPrincipal());
3885 if (mBrowsingContext) {
3886 loadState->SetTriggeringSandboxFlags(mBrowsingContext->GetSandboxFlags());
3887 loadState->SetTriggeringWindowId(
3888 mBrowsingContext->GetCurrentInnerWindowId());
3889 nsPIDOMWindowInner* innerWin = mScriptGlobal->GetCurrentInnerWindow();
3890 if (innerWin) {
3891 loadState->SetTriggeringStorageAccess(innerWin->UsingStorageAccess());
3892 }
3893 }
3894 loadState->SetLoadType(LOAD_ERROR_PAGE);
3895 loadState->SetFirstParty(true);
3896 loadState->SetSourceBrowsingContext(mBrowsingContext);
3897 if (mozilla::SessionHistoryInParent() && mLoadingEntry) {
3898 // We keep the loading entry for the load that failed here. If the user
3899 // reloads we want to try to reload the original load, not the error page.
3900 loadState->SetLoadingSessionHistoryInfo(
3901 MakeUnique<LoadingSessionHistoryInfo>(*mLoadingEntry));
3902 }
3903 return InternalLoad(loadState);
3904}
3905
3906MOZ_CAN_RUN_SCRIPT_BOUNDARY NS_IMETHODIMPnsresult
3907nsDocShell::Reload(uint32_t aReloadFlags) {
3908 return ReloadNavigable(Nothing(), aReloadFlags, nullptr,
3909 UserNavigationInvolvement::BrowserUI);
3910}
3911
3912// https://html.spec.whatwg.org/#reload
3913// To reload a navigable navigable given an optional serialized state-or-null
3914// navigationAPIState (default null) and an optional user navigation
3915// involvement userInvolvement (default "none"):
3916nsresult nsDocShell::ReloadNavigable(
3917 mozilla::Maybe<NotNull<JSContext*>> aCx, uint32_t aReloadFlags,
3918 nsIStructuredCloneContainer* aNavigationAPIState,
3919 UserNavigationInvolvement aUserInvolvement) {
3920 if (!IsNavigationAllowed()) {
3921 return NS_OK; // JS may not handle returning of an error code
3922 }
3923
3924 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)"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 3925); MOZ_PretendNoReturn
(); } } while (0)
3925 "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)"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 3925); MOZ_PretendNoReturn
(); } } while (0)
;
3926 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"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 3927); MOZ_PretendNoReturn
(); } } while (0)
3927 "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"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 3927); MOZ_PretendNoReturn
(); } } while (0)
;
3928
3929 uint32_t loadType = MAKE_LOAD_TYPE(LOAD_RELOAD_NORMAL, aReloadFlags)((LOAD_RELOAD_NORMAL) | ((aReloadFlags) << 16));
3930 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, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 3930); return NS_ERROR_INVALID_ARG; } } while (false)
;
3931 NS_ENSURE_TRUE(do { if ((__builtin_expect(!!(!(aUserInvolvement == UserNavigationInvolvement
::BrowserUI || aCx)), 0))) { NS_DebugBreak(NS_DEBUG_WARNING, "NS_ENSURE_TRUE("
"aUserInvolvement == UserNavigationInvolvement::BrowserUI || aCx"
") failed", nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 3933); return NS_ERROR_INVALID_ARG; } } while (false)
3932 aUserInvolvement == UserNavigationInvolvement::BrowserUI || aCx,do { if ((__builtin_expect(!!(!(aUserInvolvement == UserNavigationInvolvement
::BrowserUI || aCx)), 0))) { NS_DebugBreak(NS_DEBUG_WARNING, "NS_ENSURE_TRUE("
"aUserInvolvement == UserNavigationInvolvement::BrowserUI || aCx"
") failed", nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 3933); return NS_ERROR_INVALID_ARG; } } while (false)
3933 NS_ERROR_INVALID_ARG)do { if ((__builtin_expect(!!(!(aUserInvolvement == UserNavigationInvolvement
::BrowserUI || aCx)), 0))) { NS_DebugBreak(NS_DEBUG_WARNING, "NS_ENSURE_TRUE("
"aUserInvolvement == UserNavigationInvolvement::BrowserUI || aCx"
") failed", nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 3933); return NS_ERROR_INVALID_ARG; } } while (false)
;
3934
3935 RefPtr<nsDocShell> docShell(this);
3936
3937 // 1. If userInvolvement is not "browser UI", then:
3938 if (aUserInvolvement != UserNavigationInvolvement::BrowserUI) {
3939 // 1.1 Let navigation be navigable's active window's navigation API.
3940 nsPIDOMWindowOuter* windowOuter = GetWindow();
3941 MOZ_DIAGNOSTIC_ASSERT(windowOuter)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(windowOuter)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(windowOuter))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("windowOuter", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 3941); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "windowOuter"
")"); do { MOZ_CrashSequence(__null, 3941); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3942 nsPIDOMWindowInner* windowInner = windowOuter->GetCurrentInnerWindow();
3943 MOZ_DIAGNOSTIC_ASSERT(windowInner)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(windowInner)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(windowInner))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("windowInner", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 3943); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "windowInner"
")"); do { MOZ_CrashSequence(__null, 3943); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3944 RefPtr navigation = windowInner->Navigation();
3945
3946 // 1.2 Let destinationNavigationAPIState be navigable's active session
3947 // history entry's navigation API state.
3948 // 1.3 If navigationAPIState is not null, then set
3949 // destinationNavigationAPIState to navigationAPIState.
3950 RefPtr<nsIStructuredCloneContainer> destinationNavigationAPIState =
3951 aNavigationAPIState;
3952 if (!destinationNavigationAPIState) {
3953 destinationNavigationAPIState =
3954 mActiveEntry ? mActiveEntry->GetNavigationState() : nullptr;
3955 }
3956
3957 // 1.4 Let continue be the result of firing a push/replace/reload navigate
3958 // event at navigation with navigationType set to "reload",
3959 // isSameDocument set to false, userInvolvement set to userInvolvement,
3960 // destinationURL set to navigable's active session history entry's URL,
3961 // and navigationAPIState set to destinationNavigationAPIState.
3962 // 1.5 If continue is false, then return.
3963 RefPtr destinationURL = mActiveEntry ? mActiveEntry->GetURI() : nullptr;
3964 if (navigation &&
3965 !navigation->FirePushReplaceReloadNavigateEvent(
3966 *aCx, NavigationType::Reload, destinationURL,
3967 /* aIsSameDocument */ false, /* aIsSync */ false,
3968 Some(aUserInvolvement),
3969 /* aSourceElement*/ nullptr, /* aFormDataEntryList */ nullptr,
3970 destinationNavigationAPIState,
3971 /* aClassiCHistoryAPIState */ nullptr)) {
3972 return NS_OK;
3973 }
3974 }
3975
3976 // The following steps are implemented by the remainder of ReloadNavigable.
3977
3978 // Send notifications to the HistoryListener if any, about the impending
3979 // reload
3980 RefPtr<ChildSHistory> rootSH = GetRootSessionHistory();
3981 if (mozilla::SessionHistoryInParent()) {
3982 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)
;
3983 bool forceReload = IsForceReloadType(loadType);
3984 if (!XRE_IsParentProcess()) {
3985 ++mPendingReloadCount;
3986 nsCOMPtr<nsIDocumentViewer> viewer(mDocumentViewer);
3987 NS_ENSURE_STATE(viewer)do { if ((__builtin_expect(!!(!(viewer)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "viewer" ") failed", nullptr
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 3987); return
NS_ERROR_UNEXPECTED; } } while (false)
;
3988
3989 bool okToUnload = true;
3990 MOZ_TRY(viewer->PermitUnload(&okToUnload))__extension__({ auto mozTryVarTempResult = ::mozilla::ToResult
(viewer->PermitUnload(&okToUnload)); if ((__builtin_expect
(!!(mozTryVarTempResult.isErr()), 0))) { return mozTryVarTempResult
.propagateErr(); } mozTryVarTempResult.unwrap(); })
;
3991 if (!okToUnload) {
3992 return NS_OK;
3993 }
3994
3995 RefPtr<Document> doc(GetDocument());
3996 RefPtr<BrowsingContext> browsingContext(mBrowsingContext);
3997 nsCOMPtr<nsIURI> currentURI(mCurrentURI);
3998 nsCOMPtr<nsIReferrerInfo> referrerInfo(mReferrerInfo);
3999 RefPtr<StopDetector> stopDetector = new StopDetector();
4000 nsCOMPtr<nsILoadGroup> loadGroup;
4001 GetLoadGroup(getter_AddRefs(loadGroup));
4002 if (loadGroup) {
4003 // loadGroup may be null in theory. In that case stopDetector just
4004 // doesn't do anything.
4005 loadGroup->AddRequest(stopDetector, nullptr);
4006 }
4007
4008 ContentChild::GetSingleton()->SendNotifyOnHistoryReload(
4009 mBrowsingContext, forceReload,
4010 [docShell, doc, loadType, browsingContext, currentURI, referrerInfo,
4011 loadGroup, stopDetector](
4012 std::tuple<bool, Maybe<NotNull<RefPtr<nsDocShellLoadState>>>,
4013 Maybe<bool>>&& aResult) {
4014 auto scopeExit = MakeScopeExit([loadGroup, stopDetector]() {
4015 if (loadGroup) {
4016 loadGroup->RemoveRequest(stopDetector, nullptr, NS_OK);
4017 }
4018 });
4019
4020 // Decrease mPendingReloadCount before any other early returns!
4021 if (--(docShell->mPendingReloadCount) > 0) {
4022 return;
4023 }
4024
4025 if (stopDetector->Canceled()) {
4026 return;
4027 }
4028 bool canReload;
4029 Maybe<NotNull<RefPtr<nsDocShellLoadState>>> loadState;
4030 Maybe<bool> reloadingActiveEntry;
4031
4032 std::tie(canReload, loadState, reloadingActiveEntry) = aResult;
4033
4034 if (!canReload) {
4035 return;
4036 }
4037
4038 if (loadState.isSome()) {
4039 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)
4040 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)
4041 ("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)
;
4042 loadState.ref()->SetNotifiedBeforeUnloadListeners(true);
4043 docShell->LoadHistoryEntry(loadState.ref(), loadType,
4044 reloadingActiveEntry.ref());
4045 } else {
4046 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)
4047 ("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)
;
4048 ReloadDocument(docShell, doc, loadType, browsingContext,
4049 currentURI, referrerInfo,
4050 /* aNotifiedBeforeUnloadListeners */ true);
4051 }
4052 },
4053 [](mozilla::ipc::ResponseRejectReason) {});
4054 } else {
4055 // Parent process
4056 bool canReload = false;
4057 Maybe<NotNull<RefPtr<nsDocShellLoadState>>> loadState;
4058 Maybe<bool> reloadingActiveEntry;
4059 if (!mBrowsingContext->IsDiscarded()) {
4060 mBrowsingContext->Canonical()->NotifyOnHistoryReload(
4061 forceReload, canReload, loadState, reloadingActiveEntry);
4062 }
4063 if (canReload) {
4064 if (loadState.isSome()) {
4065 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)
4066 ("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)
;
4067 LoadHistoryEntry(loadState.ref(), loadType,
4068 reloadingActiveEntry.ref());
4069 } else {
4070 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)
4071 ("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)
;
4072 RefPtr<Document> doc = GetDocument();
4073 RefPtr<BrowsingContext> bc = mBrowsingContext;
4074 nsCOMPtr<nsIURI> currentURI = mCurrentURI;
4075 nsCOMPtr<nsIReferrerInfo> referrerInfo = mReferrerInfo;
4076 ReloadDocument(this, doc, loadType, bc, currentURI, referrerInfo);
4077 }
4078 }
4079 }
4080 return NS_OK;
4081 }
4082
4083 bool canReload = true;
4084 if (rootSH) {
4085 rootSH->LegacySHistory()->NotifyOnHistoryReload(&canReload);
4086 }
4087
4088 if (!canReload) {
4089 return NS_OK;
4090 }
4091
4092 /* If you change this part of code, make sure bug 45297 does not re-occur */
4093 if (mOSHE) {
4094 nsCOMPtr<nsISHEntry> oshe = mOSHE;
4095 return LoadHistoryEntry(
4096 oshe, loadType,
4097 aReloadFlags & nsIWebNavigation::LOAD_FLAGS_USER_ACTIVATION);
4098 }
4099
4100 if (mLSHE) { // In case a reload happened before the current load is done
4101 nsCOMPtr<nsISHEntry> lshe = mLSHE;
4102 return LoadHistoryEntry(
4103 lshe, loadType,
4104 aReloadFlags & nsIWebNavigation::LOAD_FLAGS_USER_ACTIVATION);
4105 }
4106
4107 RefPtr<Document> doc = GetDocument();
4108 RefPtr<BrowsingContext> bc = mBrowsingContext;
4109 nsCOMPtr<nsIURI> currentURI = mCurrentURI;
4110 nsCOMPtr<nsIReferrerInfo> referrerInfo = mReferrerInfo;
4111 return ReloadDocument(this, doc, loadType, bc, currentURI, referrerInfo);
4112}
4113
4114/* static */
4115nsresult nsDocShell::ReloadDocument(nsDocShell* aDocShell, Document* aDocument,
4116 uint32_t aLoadType,
4117 BrowsingContext* aBrowsingContext,
4118 nsIURI* aCurrentURI,
4119 nsIReferrerInfo* aReferrerInfo,
4120 bool aNotifiedBeforeUnloadListeners) {
4121 if (!aDocument) {
4122 return NS_OK;
4123 }
4124
4125 // Do not inherit owner from document
4126 uint32_t flags = INTERNAL_LOAD_FLAGS_NONE;
4127 nsAutoString srcdoc;
4128 nsIURI* baseURI = nullptr;
4129 nsCOMPtr<nsIURI> originalURI;
4130 nsCOMPtr<nsIURI> resultPrincipalURI;
4131 bool loadReplace = false;
4132
4133 nsIPrincipal* triggeringPrincipal = aDocument->NodePrincipal();
4134 nsCOMPtr<nsIContentSecurityPolicy> csp = aDocument->GetCsp();
4135 uint32_t triggeringSandboxFlags = aDocument->GetSandboxFlags();
4136 uint64_t triggeringWindowId = aDocument->InnerWindowID();
4137 bool triggeringStorageAccess = aDocument->UsingStorageAccess();
4138 net::ClassificationFlags triggeringClassificationFlags =
4139 aDocument->GetScriptTrackingFlags();
4140
4141 nsAutoString contentTypeHint;
4142 aDocument->GetContentType(contentTypeHint);
4143
4144 if (aDocument->IsSrcdocDocument()) {
4145 aDocument->GetSrcdocData(srcdoc);
4146 flags |= INTERNAL_LOAD_FLAGS_IS_SRCDOC;
4147 baseURI = aDocument->GetBaseURI();
4148 } else {
4149 srcdoc = VoidString();
4150 }
4151 nsCOMPtr<nsIChannel> chan = aDocument->GetChannel();
4152 if (chan) {
4153 uint32_t loadFlags;
4154 chan->GetLoadFlags(&loadFlags);
4155 loadReplace = loadFlags & nsIChannel::LOAD_REPLACE;
4156 nsCOMPtr<nsIHttpChannel> httpChan(do_QueryInterface(chan));
4157 if (httpChan) {
4158 httpChan->GetOriginalURI(getter_AddRefs(originalURI));
4159 }
4160
4161 nsCOMPtr<nsILoadInfo> loadInfo = chan->LoadInfo();
4162 loadInfo->GetResultPrincipalURI(getter_AddRefs(resultPrincipalURI));
4163 }
4164
4165 if (!triggeringPrincipal) {
4166 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"
")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 4166
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") (" "Reload needs a valid triggeringPrincipal"
")"); do { MOZ_CrashSequence(__null, 4166); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4167 return NS_ERROR_FAILURE;
4168 }
4169
4170 // Stack variables to ensure changes to the member variables don't affect to
4171 // the call.
4172 nsCOMPtr<nsIURI> currentURI = aCurrentURI;
4173
4174 // Reload always rewrites result principal URI.
4175 Maybe<nsCOMPtr<nsIURI>> emplacedResultPrincipalURI;
4176 emplacedResultPrincipalURI.emplace(std::move(resultPrincipalURI));
4177
4178 RefPtr<WindowContext> context = aBrowsingContext->GetCurrentWindowContext();
4179 RefPtr<nsDocShellLoadState> loadState = new nsDocShellLoadState(currentURI);
4180 loadState->SetReferrerInfo(aReferrerInfo);
4181 loadState->SetOriginalURI(originalURI);
4182 loadState->SetMaybeResultPrincipalURI(emplacedResultPrincipalURI);
4183 loadState->SetLoadReplace(loadReplace);
4184 loadState->SetTriggeringPrincipal(triggeringPrincipal);
4185 loadState->SetTriggeringSandboxFlags(triggeringSandboxFlags);
4186 loadState->SetTriggeringWindowId(triggeringWindowId);
4187 loadState->SetTriggeringStorageAccess(triggeringStorageAccess);
4188 loadState->SetTriggeringClassificationFlags(triggeringClassificationFlags);
4189 loadState->SetPrincipalToInherit(triggeringPrincipal);
4190 loadState->SetCsp(csp);
4191 loadState->SetInternalLoadFlags(flags);
4192 loadState->SetTypeHint(NS_ConvertUTF16toUTF8(contentTypeHint));
4193 loadState->SetLoadType(aLoadType);
4194 loadState->SetFirstParty(true);
4195 loadState->SetSrcdocData(srcdoc);
4196 loadState->SetSourceBrowsingContext(aBrowsingContext);
4197 loadState->SetBaseURI(baseURI);
4198 loadState->SetHasValidUserGestureActivation(
4199 context && context->HasValidTransientUserGestureActivation());
4200
4201 loadState->SetTextDirectiveUserActivation(
4202 aDocument->ConsumeTextDirectiveUserActivation() ||
4203 loadState->HasValidUserGestureActivation());
4204
4205 loadState->SetNotifiedBeforeUnloadListeners(aNotifiedBeforeUnloadListeners);
4206 return aDocShell->InternalLoad(loadState);
4207}
4208
4209// TODO: Convert this to MOZ_CAN_RUN_SCRIPT (bug 1415230)
4210MOZ_CAN_RUN_SCRIPT_BOUNDARY NS_IMETHODIMPnsresult
4211nsDocShell::Stop(uint32_t aStopFlags) {
4212 RefPtr kungFuDeathGrip = this;
4213 if (RefPtr<Document> doc = GetDocument(); doc && !doc->ShouldIgnoreOpens()) {
4214 SetOngoingNavigation(Nothing());
4215 }
4216
4217 // Revoke any pending event related to content viewer restoration
4218 mRestorePresentationEvent.Revoke();
4219
4220 if (mLoadType == LOAD_ERROR_PAGE) {
4221 if (mLSHE) {
4222 // Since error page loads never unset mLSHE, do so now
4223 SetHistoryEntryAndUpdateBC(Some(nullptr), Some<nsISHEntry*>(mLSHE));
4224 }
4225 mActiveEntryIsLoadingFromSessionHistory = false;
4226
4227 mFailedChannel = nullptr;
4228 mFailedURI = nullptr;
4229 }
4230
4231 if (nsIWebNavigation::STOP_CONTENT & aStopFlags) {
4232 // Stop the document loading and animations
4233 if (mDocumentViewer) {
4234 nsCOMPtr<nsIDocumentViewer> viewer = mDocumentViewer;
4235 viewer->Stop();
4236 }
4237 } else if (nsIWebNavigation::STOP_NETWORK & aStopFlags) {
4238 // Stop the document loading only
4239 if (mDocumentViewer) {
4240 RefPtr<Document> doc = mDocumentViewer->GetDocument();
4241 if (doc) {
4242 doc->StopDocumentLoad();
4243 }
4244 }
4245 }
4246
4247 if (nsIWebNavigation::STOP_NETWORK & aStopFlags) {
4248 // Suspend any timers that were set for this loader. We'll clear
4249 // them out for good in CreateDocumentViewer.
4250 if (mRefreshURIList) {
4251 SuspendRefreshURIs();
4252 mSavedRefreshURIList.swap(mRefreshURIList);
4253 mRefreshURIList = nullptr;
4254 }
4255
4256 // XXXbz We could also pass |this| to nsIURILoader::Stop. That will
4257 // just call Stop() on us as an nsIDocumentLoader... We need fewer
4258 // redundant apis!
4259 Stop();
4260
4261 // Clear out mChannelToDisconnectOnPageHide. This page won't go in the
4262 // BFCache now, and the Stop above will have removed the DocumentChannel
4263 // from the loadgroup.
4264 mChannelToDisconnectOnPageHide = 0;
4265 }
4266
4267 for (auto* child : mChildList.ForwardRange()) {
4268 nsCOMPtr<nsIWebNavigation> shellAsNav(do_QueryObject(child));
4269 if (shellAsNav) {
4270 shellAsNav->Stop(aStopFlags);
4271 }
4272 }
4273
4274 return NS_OK;
4275}
4276
4277NS_IMETHODIMPnsresult
4278nsDocShell::GetDocument(Document** aDocument) {
4279 NS_ENSURE_ARG_POINTER(aDocument)do { if ((__builtin_expect(!!(!(aDocument)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aDocument" ") failed", nullptr
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 4279); return
NS_ERROR_INVALID_POINTER; } } while (false)
;
4280 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
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 4280); return
NS_ERROR_FAILURE; } } while (false)
;
4281
4282 RefPtr<Document> doc = mDocumentViewer->GetDocument();
4283 if (!doc) {
4284 return NS_ERROR_NOT_AVAILABLE;
4285 }
4286
4287 doc.forget(aDocument);
4288 return NS_OK;
4289}
4290
4291NS_IMETHODIMPnsresult
4292nsDocShell::GetCurrentURI(nsIURI** aURI) {
4293 NS_ENSURE_ARG_POINTER(aURI)do { if ((__builtin_expect(!!(!(aURI)), 0))) { NS_DebugBreak(
NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aURI" ") failed", nullptr
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 4293); return
NS_ERROR_INVALID_POINTER; } } while (false)
;
4294
4295 nsCOMPtr<nsIURI> uri = mCurrentURI;
4296 uri.forget(aURI);
4297 return NS_OK;
4298}
4299
4300NS_IMETHODIMPnsresult
4301nsDocShell::GetSessionHistoryXPCOM(nsISupports** aSessionHistory) {
4302 NS_ENSURE_ARG_POINTER(aSessionHistory)do { if ((__builtin_expect(!!(!(aSessionHistory)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aSessionHistory" ") failed"
, nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 4302); return NS_ERROR_INVALID_POINTER; } } while (false)
;
4303 RefPtr<ChildSHistory> shistory = GetSessionHistory();
4304 shistory.forget(aSessionHistory);
4305 return NS_OK;
4306}
4307
4308//*****************************************************************************
4309// nsDocShell::nsIWebPageDescriptor
4310//*****************************************************************************
4311
4312NS_IMETHODIMPnsresult
4313nsDocShell::LoadPageAsViewSource(nsIDocShell* aOtherDocShell,
4314 const nsAString& aURI) {
4315 if (!aOtherDocShell) {
4316 return NS_ERROR_INVALID_POINTER;
4317 }
4318 nsCOMPtr<nsIURI> newURI;
4319 nsresult rv = NS_NewURI(getter_AddRefs(newURI), aURI);
4320 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
4321 return rv;
4322 }
4323
4324 RefPtr<nsDocShellLoadState> loadState;
4325 uint32_t cacheKey;
4326 auto* otherDocShell = nsDocShell::Cast(aOtherDocShell);
4327 if (mozilla::SessionHistoryInParent()) {
4328 loadState = new nsDocShellLoadState(newURI);
4329 if (!otherDocShell->FillLoadStateFromCurrentEntry(*loadState)) {
4330 return NS_ERROR_INVALID_POINTER;
4331 }
4332 cacheKey = otherDocShell->GetCacheKeyFromCurrentEntry().valueOr(0);
4333 } else {
4334 nsCOMPtr<nsISHEntry> entry;
4335 bool isOriginalSHE;
4336 otherDocShell->GetCurrentSHEntry(getter_AddRefs(entry), &isOriginalSHE);
4337 if (!entry) {
4338 return NS_ERROR_INVALID_POINTER;
4339 }
4340 rv = entry->CreateLoadInfo(getter_AddRefs(loadState));
4341 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, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 4341); return rv; } } while (false)
;
4342 entry->GetCacheKey(&cacheKey);
4343 loadState->SetURI(newURI);
4344 loadState->SetSHEntry(nullptr);
4345 }
4346
4347 // We're doing a load of the page, via an API that
4348 // is only exposed to system code. The triggering principal for this load
4349 // should be the system principal.
4350 loadState->SetTriggeringPrincipal(nsContentUtils::GetSystemPrincipal());
4351 loadState->SetOriginalURI(nullptr);
4352 loadState->SetResultPrincipalURI(nullptr);
4353
4354 return InternalLoad(loadState, Some(cacheKey));
4355}
4356
4357NS_IMETHODIMPnsresult
4358nsDocShell::GetCurrentDescriptor(nsISupports** aPageDescriptor) {
4359 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?" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 4359); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPageDescriptor"
") (" "Null out param?" ")"); do { MOZ_CrashSequence(__null,
4359); __attribute__((nomerge)) ::abort(); } while (false); }
} while (false)
;
4360
4361 *aPageDescriptor = nullptr;
4362
4363 nsISHEntry* src = mOSHE ? mOSHE : mLSHE;
4364 if (src) {
4365 nsCOMPtr<nsISHEntry> dest;
4366
4367 nsresult rv = src->Clone(getter_AddRefs(dest));
4368 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
4369 return rv;
4370 }
4371
4372 // null out inappropriate cloned attributes...
4373 dest->SetParent(nullptr);
4374 dest->SetIsSubFrame(false);
4375
4376 return CallQueryInterface(dest, aPageDescriptor);
4377 }
4378
4379 return NS_ERROR_NOT_AVAILABLE;
4380}
4381
4382already_AddRefed<nsIInputStream> nsDocShell::GetPostDataFromCurrentEntry()
4383 const {
4384 nsCOMPtr<nsIInputStream> postData;
4385 if (mozilla::SessionHistoryInParent()) {
4386 if (mActiveEntry) {
4387 postData = mActiveEntry->GetPostData();
4388 } else if (mLoadingEntry) {
4389 postData = mLoadingEntry->mInfo.GetPostData();
4390 }
4391 } else {
4392 if (mOSHE) {
4393 postData = mOSHE->GetPostData();
4394 } else if (mLSHE) {
4395 postData = mLSHE->GetPostData();
4396 }
4397 }
4398
4399 return postData.forget();
4400}
4401
4402Maybe<uint32_t> nsDocShell::GetCacheKeyFromCurrentEntry() const {
4403 if (mozilla::SessionHistoryInParent()) {
4404 if (mActiveEntry) {
4405 return Some(mActiveEntry->GetCacheKey());
4406 }
4407
4408 if (mLoadingEntry) {
4409 return Some(mLoadingEntry->mInfo.GetCacheKey());
4410 }
4411 } else {
4412 if (mOSHE) {
4413 return Some(mOSHE->GetCacheKey());
4414 }
4415
4416 if (mLSHE) {
4417 return Some(mLSHE->GetCacheKey());
4418 }
4419 }
4420
4421 return Nothing();
4422}
4423
4424bool nsDocShell::FillLoadStateFromCurrentEntry(
4425 nsDocShellLoadState& aLoadState) {
4426 if (mLoadingEntry) {
4427 mLoadingEntry->mInfo.FillLoadInfo(aLoadState);
4428 return true;
4429 }
4430 if (mActiveEntry) {
4431 mActiveEntry->FillLoadInfo(aLoadState);
4432 return true;
4433 }
4434 return false;
4435}
4436
4437//*****************************************************************************
4438// nsDocShell::nsIBaseWindow
4439//*****************************************************************************
4440
4441NS_IMETHODIMPnsresult
4442nsDocShell::InitWindow(nsIWidget* aParentWidget, int32_t aX, int32_t aY,
4443 int32_t aWidth, int32_t aHeight) {
4444 SetParentWidget(aParentWidget);
4445 SetPositionAndSize(aX, aY, aWidth, aHeight, 0);
4446 NS_ENSURE_TRUE(Initialize(), NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(Initialize())), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "Initialize()" ") failed"
, nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 4446); return NS_ERROR_FAILURE; } } while (false)
;
4447 return NS_OK;
4448}
4449
4450NS_IMETHODIMPnsresult
4451nsDocShell::Destroy() {
4452 // XXX: We allow this function to be called just once. If you are going to
4453 // reset new variables in this function, please make sure the variables will
4454 // never be re-initialized. Adding assertions to check |mIsBeingDestroyed|
4455 // in the setter functions for the variables would be enough.
4456 if (mIsBeingDestroyed) {
4457 return NS_ERROR_DOCSHELL_DYING;
4458 }
4459
4460 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", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 4461); MOZ_PretendNoReturn(); } } while (0)
4461 "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", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 4461); MOZ_PretendNoReturn(); } } while (0)
;
4462
4463 nsCOMPtr<nsIObserverService> serv = services::GetObserverService();
4464 if (serv) {
4465 const char* msg = mItemType == typeContent
4466 ? NS_WEBNAVIGATION_DESTROY"webnavigation-destroy"
4467 : NS_CHROME_WEBNAVIGATION_DESTROY"chrome-webnavigation-destroy";
4468 serv->NotifyObservers(GetAsSupports(this), msg, nullptr);
4469 }
4470
4471 mIsBeingDestroyed = true;
4472
4473 // Brak the cycle with the initial client, if present.
4474 mInitialClientSource.reset();
4475
4476 // Make sure to blow away our mLoadingURI just in case. No loads
4477 // from inside this pagehide.
4478 mLoadingURI = nullptr;
4479
4480 // Fire unload event before we blow anything away.
4481 (void)FirePageHideNotification(true);
4482
4483 // Clear pointers to any detached nsEditorData that's lying
4484 // around in shistory entries. Breaks cycle. See bug 430921.
4485 if (mOSHE) {
4486 mOSHE->SetEditorData(nullptr);
4487 }
4488 if (mLSHE) {
4489 mLSHE->SetEditorData(nullptr);
4490 }
4491
4492 // Note: mContentListener can be null if Init() failed and we're being
4493 // called from the destructor.
4494 if (mContentListener) {
4495 mContentListener->DropDocShellReference();
4496 mContentListener->SetParentContentListener(nullptr);
4497 // Note that we do NOT set mContentListener to null here; that
4498 // way if someone tries to do a load in us after this point
4499 // the nsDSURIContentListener will block it. All of which
4500 // means that we should do this before calling Stop(), of
4501 // course.
4502 }
4503
4504 // Stop any URLs that are currently being loaded...
4505 Stop(nsIWebNavigation::STOP_ALL);
4506
4507 mEditorData = nullptr;
4508
4509 // Save the state of the current document, before destroying the window.
4510 // This is needed to capture the state of a frameset when the new document
4511 // causes the frameset to be destroyed...
4512 PersistLayoutHistoryState();
4513
4514 // Remove this docshell from its parent's child list
4515 nsCOMPtr<nsIDocShellTreeItem> docShellParentAsItem =
4516 do_QueryInterface(GetAsSupports(mParent));
4517 if (docShellParentAsItem) {
4518 docShellParentAsItem->RemoveChild(this);
4519 }
4520
4521 if (mDocumentViewer) {
4522 mDocumentViewer->Close(nullptr);
4523 mDocumentViewer->Destroy();
4524 mDocumentViewer = nullptr;
4525 }
4526
4527 nsDocLoader::Destroy();
4528
4529 mParentWidget = nullptr;
4530 SetCurrentURIInternal(nullptr);
4531
4532 if (mScriptGlobal) {
4533 mScriptGlobal->DetachFromDocShell(!mWillChangeProcess);
4534 mScriptGlobal = nullptr;
4535 }
4536
4537 if (GetSessionHistory()) {
4538 // We want to destroy these content viewers now rather than
4539 // letting their destruction wait for the session history
4540 // entries to get garbage collected. (Bug 488394)
4541 GetSessionHistory()->EvictLocalDocumentViewers();
4542 }
4543
4544 if (mWillChangeProcess && !mBrowsingContext->IsDiscarded()) {
4545 mBrowsingContext->PrepareForProcessChange();
4546 }
4547
4548 SetTreeOwner(nullptr);
4549
4550 mBrowserChild = nullptr;
4551
4552 mChromeEventHandler = nullptr;
4553
4554 mBCWebProgressStatusFilter = nullptr;
4555
4556 // Cancel any timers that were set for this docshell; this is needed
4557 // to break the cycle between us and the timers.
4558 CancelRefreshURITimers();
4559
4560 return NS_OK;
4561}
4562
4563double nsDocShell::GetWidgetCSSToDeviceScale() {
4564 if (mParentWidget) {
4565 return mParentWidget->GetDefaultScale().scale;
4566 }
4567 if (nsCOMPtr<nsIBaseWindow> ownerWindow = do_QueryInterface(mTreeOwner)) {
4568 return ownerWindow->GetWidgetCSSToDeviceScale();
4569 }
4570 return 1.0;
4571}
4572
4573NS_IMETHODIMPnsresult
4574nsDocShell::GetDevicePixelsPerDesktopPixel(double* aScale) {
4575 if (mParentWidget) {
4576 *aScale = mParentWidget->GetDesktopToDeviceScale().scale;
4577 return NS_OK;
4578 }
4579
4580 nsCOMPtr<nsIBaseWindow> ownerWindow(do_QueryInterface(mTreeOwner));
4581 if (ownerWindow) {
4582 return ownerWindow->GetDevicePixelsPerDesktopPixel(aScale);
4583 }
4584
4585 *aScale = 1.0;
4586 return NS_OK;
4587}
4588
4589NS_IMETHODIMPnsresult
4590nsDocShell::SetPosition(int32_t aX, int32_t aY) {
4591 mBounds.MoveTo(aX, aY);
4592
4593 if (mDocumentViewer) {
4594 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, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 4594); return NS_ERROR_FAILURE; } } while (false)
;
4595 }
4596
4597 return NS_OK;
4598}
4599
4600NS_IMETHODIMPnsresult
4601nsDocShell::SetPositionDesktopPix(int32_t aX, int32_t aY) {
4602 nsCOMPtr<nsIBaseWindow> ownerWindow(do_QueryInterface(mTreeOwner));
4603 if (ownerWindow) {
4604 return ownerWindow->SetPositionDesktopPix(aX, aY);
4605 }
4606
4607 double scale = 1.0;
4608 GetDevicePixelsPerDesktopPixel(&scale);
4609 return SetPosition(NSToIntRound(aX * scale), NSToIntRound(aY * scale));
4610}
4611
4612NS_IMETHODIMPnsresult
4613nsDocShell::GetPosition(int32_t* aX, int32_t* aY) {
4614 return GetPositionAndSize(aX, aY, nullptr, nullptr);
4615}
4616
4617NS_IMETHODIMPnsresult
4618nsDocShell::SetSize(int32_t aWidth, int32_t aHeight, bool aRepaint) {
4619 int32_t x = 0, y = 0;
4620 GetPosition(&x, &y);
4621 return SetPositionAndSize(x, y, aWidth, aHeight,
4622 aRepaint ? nsIBaseWindow::eRepaint : 0);
4623}
4624
4625NS_IMETHODIMPnsresult
4626nsDocShell::GetSize(int32_t* aWidth, int32_t* aHeight) {
4627 return GetPositionAndSize(nullptr, nullptr, aWidth, aHeight);
4628}
4629
4630NS_IMETHODIMPnsresult
4631nsDocShell::SetPositionAndSize(int32_t aX, int32_t aY, int32_t aWidth,
4632 int32_t aHeight, uint32_t aFlags) {
4633 mBounds.SetRect(aX, aY, aWidth, aHeight);
4634
4635 // Hold strong ref, since SetBounds can make us null out mDocumentViewer
4636 nsCOMPtr<nsIDocumentViewer> viewer = mDocumentViewer;
4637 if (viewer) {
4638 uint32_t cvflags = (aFlags & nsIBaseWindow::eDelayResize)
4639 ? nsIDocumentViewer::eDelayResize
4640 : 0;
4641 // XXX Border figured in here or is that handled elsewhere?
4642 nsresult rv = viewer->SetBoundsWithFlags(mBounds, cvflags);
4643 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
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 4643); return
NS_ERROR_FAILURE; } } while (false)
;
4644 }
4645
4646 return NS_OK;
4647}
4648
4649NS_IMETHODIMPnsresult
4650nsDocShell::GetPositionAndSize(int32_t* aX, int32_t* aY, int32_t* aWidth,
4651 int32_t* aHeight) {
4652 if (mParentWidget) {
4653 // ensure size is up-to-date if window has changed resolution
4654 LayoutDeviceIntRect r = mParentWidget->GetClientBounds();
4655 SetPositionAndSize(mBounds.X(), mBounds.Y(), r.Width(), r.Height(), 0);
4656 }
4657
4658 // We should really consider just getting this information from
4659 // our window instead of duplicating the storage and code...
4660 if (aWidth || aHeight) {
4661 // Caller wants to know our size; make sure to give them up to
4662 // date information.
4663 RefPtr<Document> doc(do_GetInterface(GetAsSupports(mParent)));
4664 if (doc) {
4665 doc->FlushPendingNotifications(FlushType::Layout);
4666 }
4667 }
4668
4669 DoGetPositionAndSize(aX, aY, aWidth, aHeight);
4670 return NS_OK;
4671}
4672
4673void nsDocShell::DoGetPositionAndSize(int32_t* aX, int32_t* aY, int32_t* aWidth,
4674 int32_t* aHeight) {
4675 if (aX) {
4676 *aX = mBounds.X();
4677 }
4678 if (aY) {
4679 *aY = mBounds.Y();
4680 }
4681 if (aWidth) {
4682 *aWidth = mBounds.Width();
4683 }
4684 if (aHeight) {
4685 *aHeight = mBounds.Height();
4686 }
4687}
4688
4689NS_IMETHODIMPnsresult
4690nsDocShell::SetDimensions(DimensionRequest&& aRequest) {
4691 return NS_ERROR_NOT_IMPLEMENTED;
4692}
4693
4694NS_IMETHODIMPnsresult
4695nsDocShell::GetDimensions(DimensionKind aDimensionKind, int32_t* aX,
4696 int32_t* aY, int32_t* aCX, int32_t* aCY) {
4697 return NS_ERROR_NOT_IMPLEMENTED;
4698}
4699
4700NS_IMETHODIMPnsresult
4701nsDocShell::Repaint(bool aForce) {
4702 PresShell* presShell = GetPresShell();
4703 NS_ENSURE_TRUE(presShell, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(presShell)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "presShell" ") failed", nullptr
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 4703); return
NS_ERROR_FAILURE; } } while (false)
;
4704
4705 RefPtr<nsViewManager> viewManager = presShell->GetViewManager();
4706 NS_ENSURE_TRUE(viewManager, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(viewManager)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "viewManager" ") failed"
, nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 4706); return NS_ERROR_FAILURE; } } while (false)
;
4707
4708 viewManager->InvalidateAllViews();
4709 return NS_OK;
4710}
4711
4712NS_IMETHODIMPnsresult
4713nsDocShell::GetParentWidget(nsIWidget** aParentWidget) {
4714 NS_ENSURE_ARG_POINTER(aParentWidget)do { if ((__builtin_expect(!!(!(aParentWidget)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aParentWidget" ") failed"
, nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 4714); return NS_ERROR_INVALID_POINTER; } } while (false)
;
4715
4716 *aParentWidget = mParentWidget;
4717 NS_IF_ADDREF(*aParentWidget)ns_if_addref(*aParentWidget);
4718
4719 return NS_OK;
4720}
4721
4722NS_IMETHODIMPnsresult
4723nsDocShell::SetParentWidget(nsIWidget* aParentWidget) {
4724 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"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 4724); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!mIsBeingDestroyed" ")"); do { MOZ_CrashSequence
(__null, 4724); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
4725 mParentWidget = aParentWidget;
4726
4727 return NS_OK;
4728}
4729
4730NS_IMETHODIMPnsresult
4731nsDocShell::GetNativeHandle(nsAString& aNativeHandle) {
4732 // the nativeHandle should be accessed from nsIAppWindow
4733 return NS_ERROR_NOT_IMPLEMENTED;
4734}
4735
4736NS_IMETHODIMPnsresult
4737nsDocShell::GetVisibility(bool* aVisibility) {
4738 NS_ENSURE_ARG_POINTER(aVisibility)do { if ((__builtin_expect(!!(!(aVisibility)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aVisibility" ") failed"
, nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 4738); return NS_ERROR_INVALID_POINTER; } } while (false)
;
4739
4740 *aVisibility = false;
4741
4742 if (!mDocumentViewer) {
4743 return NS_OK;
4744 }
4745
4746 PresShell* presShell = GetPresShell();
4747 if (!presShell) {
4748 return NS_OK;
4749 }
4750
4751 // get the view manager
4752 nsViewManager* vm = presShell->GetViewManager();
4753 NS_ENSURE_TRUE(vm, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(vm)), 0))) { NS_DebugBreak(NS_DEBUG_WARNING
, "NS_ENSURE_TRUE(" "vm" ") failed", nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 4753); return NS_ERROR_FAILURE; } } while (false)
;
4754
4755 // get the root view
4756 nsView* view = vm->GetRootView(); // views are not ref counted
4757 NS_ENSURE_TRUE(view, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(view)), 0))) { NS_DebugBreak(
NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "view" ") failed", nullptr
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 4757); return
NS_ERROR_FAILURE; } } while (false)
;
4758
4759 // if our root view is hidden, we are not visible
4760 if (view->GetVisibility() == ViewVisibility::Hide) {
4761 return NS_OK;
4762 }
4763
4764 // otherwise, we must walk up the document and view trees checking
4765 // for a hidden view, unless we're an off screen browser, which
4766 // would make this test meaningless.
4767
4768 RefPtr<nsDocShell> docShell = this;
4769 RefPtr<nsDocShell> parentItem = docShell->GetInProcessParentDocshell();
4770 while (parentItem) {
4771 // Null-check for crash in bug 267804
4772 if (!parentItem->GetPresShell()) {
4773 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" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 4773); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "parent docshell has null pres shell"
")"); do { MOZ_CrashSequence(__null, 4773); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4774 return NS_OK;
4775 }
4776
4777 vm = docShell->GetPresShell()->GetViewManager();
4778 if (vm) {
4779 view = vm->GetRootView();
4780 }
4781
4782 if (view) {
4783 view = view->GetParent(); // anonymous inner view
4784 if (view) {
4785 view = view->GetParent(); // subdocumentframe's view
4786 }
4787 }
4788
4789 nsIFrame* frame = view ? view->GetFrame() : nullptr;
4790 if (frame && !frame->IsVisibleConsideringAncestors(
4791 nsIFrame::VISIBILITY_CROSS_CHROME_CONTENT_BOUNDARY)) {
4792 return NS_OK;
4793 }
4794
4795 docShell = parentItem;
4796 parentItem = docShell->GetInProcessParentDocshell();
4797 }
4798
4799 nsCOMPtr<nsIBaseWindow> treeOwnerAsWin(do_QueryInterface(mTreeOwner));
4800 if (!treeOwnerAsWin) {
4801 *aVisibility = true;
4802 return NS_OK;
4803 }
4804
4805 // Check with the tree owner as well to give embedders a chance to
4806 // expose visibility as well.
4807 nsresult rv = treeOwnerAsWin->GetVisibility(aVisibility);
4808 if (rv == NS_ERROR_NOT_IMPLEMENTED) {
4809 // The tree owner had no opinion on our visibility.
4810 *aVisibility = true;
4811 return NS_OK;
4812 }
4813 return rv;
4814}
4815
4816void nsDocShell::ActivenessMaybeChanged() {
4817 const bool isActive = mBrowsingContext->IsActive();
4818 if (RefPtr<PresShell> presShell = GetPresShell()) {
4819 presShell->ActivenessMaybeChanged();
4820 }
4821
4822 // Tell the window about it
4823 if (mScriptGlobal) {
4824 mScriptGlobal->SetIsBackground(!isActive);
4825 if (RefPtr<Document> doc = mScriptGlobal->GetExtantDoc()) {
4826 // Update orientation when the top-level browsing context becomes active.
4827 if (isActive && mBrowsingContext->IsTop() &&
4828 !mBrowsingContext->Windowless()) {
4829 // We only care about the top-level browsing context.
4830 auto orientation = mBrowsingContext->GetOrientationLock();
4831 ScreenOrientation::UpdateActiveOrientationLock(orientation);
4832 }
4833
4834 doc->PostVisibilityUpdateEvent();
4835 }
4836 }
4837
4838 // Tell the nsDOMNavigationTiming about it
4839 RefPtr<nsDOMNavigationTiming> timing = mTiming;
4840 if (!timing && mDocumentViewer) {
4841 if (Document* doc = mDocumentViewer->GetDocument()) {
4842 timing = doc->GetNavigationTiming();
4843 }
4844 }
4845 if (timing) {
4846 timing->NotifyDocShellStateChanged(
4847 isActive ? nsDOMNavigationTiming::DocShellState::eActive
4848 : nsDOMNavigationTiming::DocShellState::eInactive);
4849 }
4850
4851 // Restart or stop meta refresh timers if necessary
4852 if (mDisableMetaRefreshWhenInactive) {
4853 if (isActive) {
4854 ResumeRefreshURIs();
4855 } else {
4856 SuspendRefreshURIs();
4857 }
4858 }
4859
4860 if (InputTaskManager::CanSuspendInputEvent()) {
4861 mBrowsingContext->Group()->UpdateInputTaskManagerIfNeeded(isActive);
4862 }
4863}
4864
4865NS_IMETHODIMPnsresult
4866nsDocShell::SetDefaultLoadFlags(uint32_t aDefaultLoadFlags) {
4867 if (!mWillChangeProcess) {
4868 // Intentionally ignoring handling discarded browsing contexts.
4869 Unused << mBrowsingContext->SetDefaultLoadFlags(aDefaultLoadFlags);
4870 } else {
4871 // Bug 1623565: DevTools tries to clean up defaultLoadFlags on
4872 // shutdown. Sorry DevTools, your DocShell is in another process.
4873 NS_WARNING("nsDocShell::SetDefaultLoadFlags called on Zombie DocShell")NS_DebugBreak(NS_DEBUG_WARNING, "nsDocShell::SetDefaultLoadFlags called on Zombie DocShell"
, nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 4873)
;
4874 }
4875 return NS_OK;
4876}
4877
4878NS_IMETHODIMPnsresult
4879nsDocShell::GetDefaultLoadFlags(uint32_t* aDefaultLoadFlags) {
4880 *aDefaultLoadFlags = mBrowsingContext->GetDefaultLoadFlags();
4881 return NS_OK;
4882}
4883
4884NS_IMETHODIMPnsresult
4885nsDocShell::GetFailedChannel(nsIChannel** aFailedChannel) {
4886 NS_ENSURE_ARG_POINTER(aFailedChannel)do { if ((__builtin_expect(!!(!(aFailedChannel)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aFailedChannel" ") failed"
, nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 4886); return NS_ERROR_INVALID_POINTER; } } while (false)
;
4887 Document* doc = GetDocument();
4888 if (!doc) {
4889 *aFailedChannel = nullptr;
4890 return NS_OK;
4891 }
4892 NS_IF_ADDREF(*aFailedChannel = doc->GetFailedChannel())ns_if_addref(*aFailedChannel = doc->GetFailedChannel());
4893 return NS_OK;
4894}
4895
4896NS_IMETHODIMPnsresult
4897nsDocShell::SetVisibility(bool aVisibility) {
4898 // Show()/Hide() may change mDocumentViewer.
4899 nsCOMPtr<nsIDocumentViewer> viewer = mDocumentViewer;
4900 if (!viewer) {
4901 return NS_OK;
4902 }
4903 if (aVisibility) {
4904 viewer->Show();
4905 } else {
4906 viewer->Hide();
4907 }
4908
4909 return NS_OK;
4910}
4911
4912NS_IMETHODIMPnsresult
4913nsDocShell::GetEnabled(bool* aEnabled) {
4914 NS_ENSURE_ARG_POINTER(aEnabled)do { if ((__builtin_expect(!!(!(aEnabled)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aEnabled" ") failed", nullptr
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 4914); return
NS_ERROR_INVALID_POINTER; } } while (false)
;
4915 *aEnabled = true;
4916 return NS_ERROR_NOT_IMPLEMENTED;
4917}
4918
4919NS_IMETHODIMPnsresult
4920nsDocShell::SetEnabled(bool aEnabled) { return NS_ERROR_NOT_IMPLEMENTED; }
4921
4922NS_IMETHODIMPnsresult
4923nsDocShell::GetMainWidget(nsIWidget** aMainWidget) {
4924 // We don't create our own widget, so simply return the parent one.
4925 return GetParentWidget(aMainWidget);
4926}
4927
4928NS_IMETHODIMPnsresult
4929nsDocShell::GetTitle(nsAString& aTitle) {
4930 aTitle = mTitle;
4931 return NS_OK;
4932}
4933
4934NS_IMETHODIMPnsresult
4935nsDocShell::SetTitle(const nsAString& aTitle) {
4936 // Avoid unnecessary updates of the title if the URI and the title haven't
4937 // changed.
4938 if (mTitleValidForCurrentURI && mTitle == aTitle) {
4939 return NS_OK;
4940 }
4941
4942 // Store local title
4943 mTitle = aTitle;
4944 mTitleValidForCurrentURI = true;
4945
4946 // When title is set on the top object it should then be passed to the
4947 // tree owner.
4948 if (mBrowsingContext->IsTop()) {
4949 nsCOMPtr<nsIBaseWindow> treeOwnerAsWin(do_QueryInterface(mTreeOwner));
4950 if (treeOwnerAsWin) {
4951 treeOwnerAsWin->SetTitle(aTitle);
4952 }
4953 }
4954
4955 if (mCurrentURI && mLoadType != LOAD_ERROR_PAGE) {
4956 UpdateGlobalHistoryTitle(mCurrentURI);
4957 }
4958
4959 // Update SessionHistory with the document's title.
4960 if (mLoadType != LOAD_BYPASS_HISTORY && mLoadType != LOAD_ERROR_PAGE) {
4961 SetTitleOnHistoryEntry(true);
4962 }
4963
4964 return NS_OK;
4965}
4966
4967void nsDocShell::SetTitleOnHistoryEntry(bool aUpdateEntryInSessionHistory) {
4968 if (mOSHE) {
4969 mOSHE->SetTitle(mTitle);
4970 }
4971
4972 if (mActiveEntry && mBrowsingContext) {
4973 mActiveEntry->SetTitle(mTitle);
4974 if (aUpdateEntryInSessionHistory) {
4975 if (XRE_IsParentProcess()) {
4976 SessionHistoryEntry* entry =
4977 mBrowsingContext->Canonical()->GetActiveSessionHistoryEntry();
4978 if (entry) {
4979 entry->SetTitle(mTitle);
4980 }
4981 } else {
4982 mozilla::Unused
4983 << ContentChild::GetSingleton()->SendSessionHistoryEntryTitle(
4984 mBrowsingContext, mTitle);
4985 }
4986 }
4987 }
4988}
4989
4990nsPoint nsDocShell::GetCurScrollPos() {
4991 nsPoint scrollPos;
4992 if (ScrollContainerFrame* sf = GetRootScrollContainerFrame()) {
4993 scrollPos = sf->GetVisualViewportOffset();
4994 }
4995 return scrollPos;
4996}
4997
4998nsresult nsDocShell::SetCurScrollPosEx(int32_t aCurHorizontalPos,
4999 int32_t aCurVerticalPos) {
5000 ScrollContainerFrame* sf = GetRootScrollContainerFrame();
5001 NS_ENSURE_TRUE(sf, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(sf)), 0))) { NS_DebugBreak(NS_DEBUG_WARNING
, "NS_ENSURE_TRUE(" "sf" ") failed", nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 5001); return NS_ERROR_FAILURE; } } while (false)
;
5002
5003 ScrollMode scrollMode =
5004 sf->IsSmoothScroll() ? ScrollMode::SmoothMsd : ScrollMode::Instant;
5005
5006 nsPoint targetPos(aCurHorizontalPos, aCurVerticalPos);
5007 sf->ScrollTo(targetPos, scrollMode);
5008
5009 // Set the visual viewport offset as well.
5010
5011 RefPtr<PresShell> presShell = GetPresShell();
5012 NS_ENSURE_TRUE(presShell, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(presShell)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "presShell" ") failed", nullptr
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 5012); return
NS_ERROR_FAILURE; } } while (false)
;
5013
5014 nsPresContext* presContext = presShell->GetPresContext();
5015 NS_ENSURE_TRUE(presContext, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(presContext)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "presContext" ") failed"
, nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 5015); return NS_ERROR_FAILURE; } } while (false)
;
5016
5017 // Only the root content document can have a distinct visual viewport offset.
5018 if (!presContext->IsRootContentDocumentCrossProcess()) {
5019 return NS_OK;
5020 }
5021
5022 // Not on a platform with a distinct visual viewport - don't bother setting
5023 // the visual viewport offset.
5024 if (!presShell->IsVisualViewportSizeSet()) {
5025 return NS_OK;
5026 }
5027
5028 presShell->ScrollToVisual(targetPos, layers::FrameMetrics::eMainThread,
5029 scrollMode);
5030
5031 return NS_OK;
5032}
5033
5034void nsDocShell::SetScrollbarPreference(mozilla::ScrollbarPreference aPref) {
5035 if (mScrollbarPref == aPref) {
5036 return;
5037 }
5038 mScrollbarPref = aPref;
5039 auto* ps = GetPresShell();
5040 if (!ps) {
5041 return;
5042 }
5043 nsIFrame* rootScrollContainerFrame = ps->GetRootScrollContainerFrame();
5044 if (!rootScrollContainerFrame) {
5045 return;
5046 }
5047 ps->FrameNeedsReflow(rootScrollContainerFrame,
5048 IntrinsicDirty::FrameAncestorsAndDescendants,
5049 NS_FRAME_IS_DIRTY);
5050}
5051
5052//*****************************************************************************
5053// nsDocShell::nsIRefreshURI
5054//*****************************************************************************
5055
5056NS_IMETHODIMPnsresult
5057nsDocShell::RefreshURI(nsIURI* aURI, nsIPrincipal* aPrincipal,
5058 uint32_t aDelay) {
5059 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"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 5059); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!mIsBeingDestroyed" ")"); do { MOZ_CrashSequence
(__null, 5059); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
5060
5061 NS_ENSURE_ARG(aURI)do { if ((__builtin_expect(!!(!(aURI)), 0))) { NS_DebugBreak(
NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aURI" ") failed", nullptr
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 5061); return
NS_ERROR_INVALID_ARG; } } while (false)
;
5062
5063 /* Check if Meta refresh/redirects are permitted. Some
5064 * embedded applications may not want to do this.
5065 * Must do this before sending out NOTIFY_REFRESH events
5066 * because listeners may have side effects (e.g. displaying a
5067 * button to manually trigger the refresh later).
5068 */
5069 bool allowRedirects = true;
5070 GetAllowMetaRedirects(&allowRedirects);
5071 if (!allowRedirects) {
5072 return NS_OK;
5073 }
5074
5075 // If any web progress listeners are listening for NOTIFY_REFRESH events,
5076 // give them a chance to block this refresh.
5077 bool sameURI;
5078 nsresult rv = aURI->Equals(mCurrentURI, &sameURI);
5079 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
5080 sameURI = false;
5081 }
5082 if (!RefreshAttempted(this, aURI, aDelay, sameURI)) {
5083 return NS_OK;
5084 }
5085
5086 nsCOMPtr<nsITimerCallback> refreshTimer =
5087 new nsRefreshTimer(this, aURI, aPrincipal, aDelay);
5088
5089 BusyFlags busyFlags = GetBusyFlags();
5090
5091 if (!mRefreshURIList) {
5092 mRefreshURIList = nsArray::Create();
5093 }
5094
5095 if (busyFlags & BUSY_FLAGS_BUSY ||
5096 (!mBrowsingContext->IsActive() && mDisableMetaRefreshWhenInactive)) {
5097 // We don't want to create the timer right now. Instead queue up the
5098 // request and trigger the timer in EndPageLoad() or whenever we become
5099 // active.
5100 mRefreshURIList->AppendElement(refreshTimer);
5101 } else {
5102 // There is no page loading going on right now. Create the
5103 // timer and fire it right away.
5104 nsCOMPtr<nsPIDOMWindowOuter> win = GetWindow();
5105 NS_ENSURE_TRUE(win, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(win)), 0))) { NS_DebugBreak(NS_DEBUG_WARNING
, "NS_ENSURE_TRUE(" "win" ") failed", nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 5105); return NS_ERROR_FAILURE; } } while (false)
;
5106
5107 nsCOMPtr<nsITimer> timer;
5108 MOZ_TRY_VAR(timer, NS_NewTimerWithCallback(refreshTimer, aDelay,(timer) = __extension__({ auto mozTryVarTempResult = ::mozilla
::ToResult(NS_NewTimerWithCallback(refreshTimer, aDelay, nsITimer
::TYPE_ONE_SHOT)); if ((__builtin_expect(!!(mozTryVarTempResult
.isErr()), 0))) { return mozTryVarTempResult.propagateErr(); }
mozTryVarTempResult.unwrap(); });
5109 nsITimer::TYPE_ONE_SHOT))(timer) = __extension__({ auto mozTryVarTempResult = ::mozilla
::ToResult(NS_NewTimerWithCallback(refreshTimer, aDelay, nsITimer
::TYPE_ONE_SHOT)); if ((__builtin_expect(!!(mozTryVarTempResult
.isErr()), 0))) { return mozTryVarTempResult.propagateErr(); }
mozTryVarTempResult.unwrap(); });
;
5110
5111 mRefreshURIList->AppendElement(timer); // owning timer ref
5112 }
5113 return NS_OK;
5114}
5115
5116nsresult nsDocShell::ForceRefreshURIFromTimer(nsIURI* aURI,
5117 nsIPrincipal* aPrincipal,
5118 uint32_t aDelay,
5119 nsITimer* aTimer) {
5120 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"
")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 5120
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aTimer" ") (" "Must have a timer here"
")"); do { MOZ_CrashSequence(__null, 5120); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5121
5122 // Remove aTimer from mRefreshURIList if needed
5123 if (mRefreshURIList) {
5124 uint32_t n = 0;
5125 mRefreshURIList->GetLength(&n);
5126
5127 for (uint32_t i = 0; i < n; ++i) {
5128 nsCOMPtr<nsITimer> timer = do_QueryElementAt(mRefreshURIList, i);
5129 if (timer == aTimer) {
5130 mRefreshURIList->RemoveElementAt(i);
5131 break;
5132 }
5133 }
5134 }
5135
5136 return ForceRefreshURI(aURI, aPrincipal, aDelay);
5137}
5138
5139NS_IMETHODIMPnsresult
5140nsDocShell::ForceRefreshURI(nsIURI* aURI, nsIPrincipal* aPrincipal,
5141 uint32_t aDelay) {
5142 NS_ENSURE_ARG(aURI)do { if ((__builtin_expect(!!(!(aURI)), 0))) { NS_DebugBreak(
NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aURI" ") failed", nullptr
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 5142); return
NS_ERROR_INVALID_ARG; } } while (false)
;
5143
5144 RefPtr<nsDocShellLoadState> loadState = new nsDocShellLoadState(aURI);
5145 loadState->SetOriginalURI(mCurrentURI);
5146 loadState->SetResultPrincipalURI(aURI);
5147 loadState->SetResultPrincipalURIIsSome(true);
5148 loadState->SetKeepResultPrincipalURIIfSet(true);
5149 loadState->SetIsMetaRefresh(true);
5150
5151 RefPtr<Document> doc = GetDocument();
5152 NS_ENSURE_STATE(doc)do { if ((__builtin_expect(!!(!(doc)), 0))) { NS_DebugBreak(NS_DEBUG_WARNING
, "NS_ENSURE_TRUE(" "doc" ") failed", nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 5152); return NS_ERROR_UNEXPECTED; } } while (false)
;
5153
5154 // Set the triggering pricipal to aPrincipal if available, or current
5155 // document's principal otherwise.
5156 nsCOMPtr<nsIPrincipal> principal = aPrincipal;
5157 if (!principal) {
5158 principal = doc->NodePrincipal();
5159 }
5160 loadState->SetTriggeringPrincipal(principal);
5161 loadState->SetCsp(doc->GetCsp());
5162 loadState->SetHasValidUserGestureActivation(
5163 doc->HasValidTransientUserGestureActivation());
5164
5165 loadState->SetTextDirectiveUserActivation(
5166 doc->ConsumeTextDirectiveUserActivation() ||
5167 loadState->HasValidUserGestureActivation());
5168 loadState->SetTriggeringSandboxFlags(doc->GetSandboxFlags());
5169 loadState->SetTriggeringWindowId(doc->InnerWindowID());
5170 loadState->SetTriggeringStorageAccess(doc->UsingStorageAccess());
5171 loadState->SetTriggeringClassificationFlags(doc->GetScriptTrackingFlags());
5172
5173 loadState->SetPrincipalIsExplicit(true);
5174
5175 /* Check if this META refresh causes a redirection
5176 * to another site.
5177 */
5178 bool equalUri = false;
5179 nsresult rv = aURI->Equals(mCurrentURI, &equalUri);
5180
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 } else {
5188 loadState->SetLoadType(LOAD_REFRESH);
5189 }
5190
5191 const bool sendReferrer = StaticPrefs::network_http_referer_sendFromRefresh();
5192 /* The document's referrer policy is needed instead of mReferrerInfo's
5193 * referrer policy.
5194 */
5195 const nsCOMPtr<nsIReferrerInfo> referrerInfo =
5196 new ReferrerInfo(*doc, sendReferrer);
5197 /* We mimic HTTP, which passes the original referrer. See step 3 of
5198 * <https://html.spec.whatwg.org/multipage/browsing-the-web.html#create-navigation-params-by-fetching>.
5199 */
5200 loadState->SetReferrerInfo(referrerInfo);
5201
5202 loadState->SetLoadFlags(
5203 nsIWebNavigation::LOAD_FLAGS_DISALLOW_INHERIT_PRINCIPAL);
5204 loadState->SetFirstParty(true);
5205
5206 /*
5207 * LoadURI(...) will cancel all refresh timers... This causes the
5208 * Timer and its refreshData instance to be released...
5209 */
5210 LoadURI(loadState, false);
5211
5212 return NS_OK;
5213}
5214
5215static const char16_t* SkipASCIIWhitespace(const char16_t* aStart,
5216 const char16_t* aEnd) {
5217 const char16_t* iter = aStart;
5218 while (iter != aEnd && mozilla::IsAsciiWhitespace(*iter)) {
5219 ++iter;
5220 }
5221 return iter;
5222}
5223
5224static std::tuple<const char16_t*, const char16_t*> ExtractURLString(
5225 const char16_t* aPosition, const char16_t* aEnd) {
5226 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"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 5226); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aPosition != aEnd" ")"); do { MOZ_CrashSequence
(__null, 5226); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
5227
5228 // 1. Let urlString be the substring of input from the code point at
5229 // position to the end of the string.
5230 const char16_t* urlStart = aPosition;
5231 const char16_t* urlEnd = aEnd;
5232
5233 // 2. If the code point in input pointed to by position is U+0055 (U) or
5234 // U+0075 (u), then advance position to the next code point.
5235 // Otherwise, jump to the step labeled skip quotes.
5236 if (*aPosition == 'U' || *aPosition == 'u') {
5237 ++aPosition;
5238
5239 // 3. If the code point in input pointed to by position is U+0052 (R) or
5240 // U+0072 (r), then advance position to the next code point.
5241 // Otherwise, jump to the step labeled parse.
5242 if (aPosition == aEnd || (*aPosition != 'R' && *aPosition != 'r')) {
5243 return std::make_tuple(urlStart, urlEnd);
5244 }
5245
5246 ++aPosition;
5247
5248 // 4. If the code point in input pointed to by position is U+004C (L) or
5249 // U+006C (l), then advance position to the next code point.
5250 // Otherwise, jump to the step labeled parse.
5251 if (aPosition == aEnd || (*aPosition != 'L' && *aPosition != 'l')) {
5252 return std::make_tuple(urlStart, urlEnd);
5253 }
5254
5255 ++aPosition;
5256
5257 // 5. Skip ASCII whitespace within input given position.
5258 aPosition = SkipASCIIWhitespace(aPosition, aEnd);
5259
5260 // 6. If the code point in input pointed to by position is U+003D (=),
5261 // then advance position to the next code point. Otherwise, jump to
5262 // the step labeled parse.
5263 if (aPosition == aEnd || *aPosition != '=') {
5264 return std::make_tuple(urlStart, urlEnd);
5265 }
5266
5267 ++aPosition;
5268
5269 // 7. Skip ASCII whitespace within input given position.
5270 aPosition = SkipASCIIWhitespace(aPosition, aEnd);
5271 }
5272
5273 // 8. Skip quotes: If the code point in input pointed to by position is
5274 // U+0027 (') or U+0022 ("), then let quote be that code point, and
5275 // advance position to the next code point. Otherwise, let quote be
5276 // the empty string.
5277 Maybe<char> quote;
5278 if (aPosition != aEnd && (*aPosition == '\'' || *aPosition == '"')) {
5279 quote.emplace(*aPosition);
5280 ++aPosition;
5281 }
5282
5283 // 9. Set urlString to the substring of input from the code point at
5284 // position to the end of the string.
5285 urlStart = aPosition;
5286 urlEnd = aEnd;
5287
5288 // 10. If quote is not the empty string, and there is a code point in
5289 // urlString equal to quote, then truncate urlString at that code
5290 // point, so that it and all subsequent code points are removed.
5291 const char16_t* quotePos;
5292 if (quote.isSome() &&
5293 (quotePos = nsCharTraits<char16_t>::find(
5294 urlStart, std::distance(urlStart, aEnd), quote.value()))) {
5295 urlEnd = quotePos;
5296 }
5297
5298 return std::make_tuple(urlStart, urlEnd);
5299}
5300
5301void nsDocShell::SetupRefreshURIFromHeader(Document* aDocument,
5302 const nsAString& aHeader) {
5303 if (mIsBeingDestroyed) {
5304 return;
5305 }
5306
5307 const char16_t* position = aHeader.BeginReading();
5308 const char16_t* end = aHeader.EndReading();
5309
5310 // See https://html.spec.whatwg.org/#shared-declarative-refresh-steps.
5311
5312 // 3. Skip ASCII whitespace
5313 position = SkipASCIIWhitespace(position, end);
5314
5315 // 4. Let time be 0.
5316 CheckedInt<uint32_t> milliSeconds;
5317
5318 // 5. Collect a sequence of code points that are ASCII digits
5319 const char16_t* digitsStart = position;
5320 while (position != end && mozilla::IsAsciiDigit(*position)) {
5321 ++position;
5322 }
5323
5324 if (position == digitsStart) {
5325 // 6. If timeString is the empty string, then:
5326 // 1. If the code point in input pointed to by position is not U+002E
5327 // (.), then return.
5328 if (position == end || *position != '.') {
5329 return;
5330 }
5331 } else {
5332 // 7. Otherwise, set time to the result of parsing timeString using the
5333 // rules for parsing non-negative integers.
5334 nsContentUtils::ParseHTMLIntegerResultFlags result;
5335 uint32_t seconds =
5336 nsContentUtils::ParseHTMLInteger(digitsStart, position, &result);
5337 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)"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 5337); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!(result & nsContentUtils::eParseHTMLInteger_Negative)"
")"); do { MOZ_CrashSequence(__null, 5337); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5338 if (result & nsContentUtils::eParseHTMLInteger_Error) {
5339 // The spec assumes no errors here (since we only pass ASCII digits in),
5340 // but we can still overflow, so this block should deal with that (and
5341 // only that).
5342 MOZ_ASSERT(do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!(result & ~(nsContentUtils::eParseHTMLInteger_DidNotConsumeAllInput
| nsContentUtils::eParseHTMLInteger_Error | nsContentUtils::
eParseHTMLInteger_ErrorOverflow)))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!(result & ~(nsContentUtils
::eParseHTMLInteger_DidNotConsumeAllInput | nsContentUtils::eParseHTMLInteger_Error
| nsContentUtils::eParseHTMLInteger_ErrorOverflow))))), 0)))
{ do { } while (false); MOZ_ReportAssertionFailure("!(result & ~(nsContentUtils::eParseHTMLInteger_DidNotConsumeAllInput | nsContentUtils::eParseHTMLInteger_Error | nsContentUtils::eParseHTMLInteger_ErrorOverflow))"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 5345); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!(result & ~(nsContentUtils::eParseHTMLInteger_DidNotConsumeAllInput | nsContentUtils::eParseHTMLInteger_Error | nsContentUtils::eParseHTMLInteger_ErrorOverflow))"
")"); do { MOZ_CrashSequence(__null, 5345); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
5343 !(result & ~(nsContentUtils::eParseHTMLInteger_DidNotConsumeAllInput |do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!(result & ~(nsContentUtils::eParseHTMLInteger_DidNotConsumeAllInput
| nsContentUtils::eParseHTMLInteger_Error | nsContentUtils::
eParseHTMLInteger_ErrorOverflow)))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!(result & ~(nsContentUtils
::eParseHTMLInteger_DidNotConsumeAllInput | nsContentUtils::eParseHTMLInteger_Error
| nsContentUtils::eParseHTMLInteger_ErrorOverflow))))), 0)))
{ do { } while (false); MOZ_ReportAssertionFailure("!(result & ~(nsContentUtils::eParseHTMLInteger_DidNotConsumeAllInput | nsContentUtils::eParseHTMLInteger_Error | nsContentUtils::eParseHTMLInteger_ErrorOverflow))"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 5345); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!(result & ~(nsContentUtils::eParseHTMLInteger_DidNotConsumeAllInput | nsContentUtils::eParseHTMLInteger_Error | nsContentUtils::eParseHTMLInteger_ErrorOverflow))"
")"); do { MOZ_CrashSequence(__null, 5345); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
5344 nsContentUtils::eParseHTMLInteger_Error |do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!(result & ~(nsContentUtils::eParseHTMLInteger_DidNotConsumeAllInput
| nsContentUtils::eParseHTMLInteger_Error | nsContentUtils::
eParseHTMLInteger_ErrorOverflow)))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!(result & ~(nsContentUtils
::eParseHTMLInteger_DidNotConsumeAllInput | nsContentUtils::eParseHTMLInteger_Error
| nsContentUtils::eParseHTMLInteger_ErrorOverflow))))), 0)))
{ do { } while (false); MOZ_ReportAssertionFailure("!(result & ~(nsContentUtils::eParseHTMLInteger_DidNotConsumeAllInput | nsContentUtils::eParseHTMLInteger_Error | nsContentUtils::eParseHTMLInteger_ErrorOverflow))"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 5345); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!(result & ~(nsContentUtils::eParseHTMLInteger_DidNotConsumeAllInput | nsContentUtils::eParseHTMLInteger_Error | nsContentUtils::eParseHTMLInteger_ErrorOverflow))"
")"); do { MOZ_CrashSequence(__null, 5345); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
5345 nsContentUtils::eParseHTMLInteger_ErrorOverflow)))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!(result & ~(nsContentUtils::eParseHTMLInteger_DidNotConsumeAllInput
| nsContentUtils::eParseHTMLInteger_Error | nsContentUtils::
eParseHTMLInteger_ErrorOverflow)))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!(result & ~(nsContentUtils
::eParseHTMLInteger_DidNotConsumeAllInput | nsContentUtils::eParseHTMLInteger_Error
| nsContentUtils::eParseHTMLInteger_ErrorOverflow))))), 0)))
{ do { } while (false); MOZ_ReportAssertionFailure("!(result & ~(nsContentUtils::eParseHTMLInteger_DidNotConsumeAllInput | nsContentUtils::eParseHTMLInteger_Error | nsContentUtils::eParseHTMLInteger_ErrorOverflow))"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 5345); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!(result & ~(nsContentUtils::eParseHTMLInteger_DidNotConsumeAllInput | nsContentUtils::eParseHTMLInteger_Error | nsContentUtils::eParseHTMLInteger_ErrorOverflow))"
")"); do { MOZ_CrashSequence(__null, 5345); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5346 return;
5347 }
5348 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)"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 5349); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!(result & nsContentUtils::eParseHTMLInteger_DidNotConsumeAllInput)"
")"); do { MOZ_CrashSequence(__null, 5349); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
5349 !(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)"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 5349); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!(result & nsContentUtils::eParseHTMLInteger_DidNotConsumeAllInput)"
")"); do { MOZ_CrashSequence(__null, 5349); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5350
5351 milliSeconds = seconds;
5352 milliSeconds *= 1000;
5353 if (!milliSeconds.isValid()) {
5354 return;
5355 }
5356 }
5357
5358 // 8. Collect a sequence of code points that are ASCII digits and U+002E FULL
5359 // STOP characters (.) from input given position. Ignore any collected
5360 // characters.
5361 while (position != end &&
5362 (mozilla::IsAsciiDigit(*position) || *position == '.')) {
5363 ++position;
5364 }
5365
5366 // 9. Let urlRecord be document's URL.
5367 nsCOMPtr<nsIURI> urlRecord(aDocument->GetDocumentURI());
5368
5369 // 10. If position is not past the end of input
5370 if (position != end) {
5371 // 1. If the code point in input pointed to by position is not U+003B (;),
5372 // U+002C (,), or ASCII whitespace, then return.
5373 if (*position != ';' && *position != ',' &&
5374 !mozilla::IsAsciiWhitespace(*position)) {
5375 return;
5376 }
5377
5378 // 2. Skip ASCII whitespace within input given position.
5379 position = SkipASCIIWhitespace(position, end);
5380
5381 // 3. If the code point in input pointed to by position is U+003B (;) or
5382 // U+002C (,), then advance position to the next code point.
5383 if (position != end && (*position == ';' || *position == ',')) {
5384 ++position;
5385
5386 // 4. Skip ASCII whitespace within input given position.
5387 position = SkipASCIIWhitespace(position, end);
5388 }
5389
5390 // 11. If position is not past the end of input, then:
5391 if (position != end) {
5392 const char16_t* urlStart;
5393 const char16_t* urlEnd;
5394
5395 // 1-10. See ExtractURLString.
5396 std::tie(urlStart, urlEnd) = ExtractURLString(position, end);
5397
5398 // 11. Parse: Parse urlString relative to document. If that fails, return.
5399 // Otherwise, set urlRecord to the resulting URL record.
5400 nsresult rv =
5401 NS_NewURI(getter_AddRefs(urlRecord),
5402 Substring(urlStart, std::distance(urlStart, urlEnd)),
5403 /* charset = */ nullptr, aDocument->GetDocBaseURI());
5404 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, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 5404); return; } } while (false)
;
5405 }
5406 }
5407
5408 nsIPrincipal* principal = aDocument->NodePrincipal();
5409 nsCOMPtr<nsIScriptSecurityManager> securityManager =
5410 nsContentUtils::GetSecurityManager();
5411 nsresult rv = securityManager->CheckLoadURIWithPrincipal(
5412 principal, urlRecord,
5413 nsIScriptSecurityManager::LOAD_IS_AUTOMATIC_DOCUMENT_REPLACEMENT,
5414 aDocument->InnerWindowID());
5415 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, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 5415); return; } } while (false)
;
5416
5417 bool isjs = true;
5418 rv = NS_URIChainHasFlags(
5419 urlRecord, nsIProtocolHandler::URI_OPENING_EXECUTES_SCRIPT, &isjs);
5420 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, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 5420); return; } } while (false)
;
5421
5422 if (isjs) {
5423 return;
5424 }
5425
5426 RefreshURI(urlRecord, principal, milliSeconds.value());
5427}
5428
5429static void DoCancelRefreshURITimers(nsIMutableArray* aTimerList) {
5430 if (!aTimerList) {
5431 return;
5432 }
5433
5434 uint32_t n = 0;
5435 aTimerList->GetLength(&n);
5436
5437 while (n) {
5438 nsCOMPtr<nsITimer> timer(do_QueryElementAt(aTimerList, --n));
5439
5440 aTimerList->RemoveElementAt(n); // bye bye owning timer ref
5441
5442 if (timer) {
5443 timer->Cancel();
5444 }
5445 }
5446}
5447
5448NS_IMETHODIMPnsresult
5449nsDocShell::CancelRefreshURITimers() {
5450 DoCancelRefreshURITimers(mRefreshURIList);
5451 DoCancelRefreshURITimers(mSavedRefreshURIList);
5452 DoCancelRefreshURITimers(mBFCachedRefreshURIList);
5453 mRefreshURIList = nullptr;
5454 mSavedRefreshURIList = nullptr;
5455 mBFCachedRefreshURIList = nullptr;
5456
5457 return NS_OK;
5458}
5459
5460NS_IMETHODIMPnsresult
5461nsDocShell::GetRefreshPending(bool* aResult) {
5462 if (!mRefreshURIList) {
5463 *aResult = false;
5464 return NS_OK;
5465 }
5466
5467 uint32_t count;
5468 nsresult rv = mRefreshURIList->GetLength(&count);
5469 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
5470 *aResult = (count != 0);
5471 }
5472 return rv;
5473}
5474
5475void nsDocShell::RefreshURIToQueue() {
5476 if (mRefreshURIList) {
5477 uint32_t n = 0;
5478 mRefreshURIList->GetLength(&n);
5479
5480 for (uint32_t i = 0; i < n; ++i) {
5481 nsCOMPtr<nsITimer> timer = do_QueryElementAt(mRefreshURIList, i);
5482 if (!timer) {
5483 continue; // this must be a nsRefreshURI already
5484 }
5485
5486 // Replace this timer object with a nsRefreshTimer object.
5487 nsCOMPtr<nsITimerCallback> callback;
5488 timer->GetCallback(getter_AddRefs(callback));
5489
5490 timer->Cancel();
5491
5492 mRefreshURIList->ReplaceElementAt(callback, i);
5493 }
5494 }
5495}
5496
5497NS_IMETHODIMPnsresult
5498nsDocShell::SuspendRefreshURIs() {
5499 RefreshURIToQueue();
5500
5501 // Suspend refresh URIs for our child shells as well.
5502 for (auto* child : mChildList.ForwardRange()) {
5503 nsCOMPtr<nsIDocShell> shell = do_QueryObject(child);
5504 if (shell) {
5505 shell->SuspendRefreshURIs();
5506 }
5507 }
5508
5509 return NS_OK;
5510}
5511
5512NS_IMETHODIMPnsresult
5513nsDocShell::ResumeRefreshURIs() {
5514 RefreshURIFromQueue();
5515
5516 // Resume refresh URIs for our child shells as well.
5517 for (auto* child : mChildList.ForwardRange()) {
5518 nsCOMPtr<nsIDocShell> shell = do_QueryObject(child);
5519 if (shell) {
5520 shell->ResumeRefreshURIs();
5521 }
5522 }
5523
5524 return NS_OK;
5525}
5526
5527nsresult nsDocShell::RefreshURIFromQueue() {
5528 if (!mRefreshURIList) {
5529 return NS_OK;
5530 }
5531 uint32_t n = 0;
5532 mRefreshURIList->GetLength(&n);
5533
5534 while (n) {
5535 nsCOMPtr<nsITimerCallback> refreshInfo =
5536 do_QueryElementAt(mRefreshURIList, --n);
5537
5538 if (refreshInfo) {
5539 // This is the nsRefreshTimer object, waiting to be
5540 // setup in a timer object and fired.
5541 // Create the timer and trigger it.
5542 uint32_t delay = static_cast<nsRefreshTimer*>(
5543 static_cast<nsITimerCallback*>(refreshInfo))
5544 ->GetDelay();
5545 nsCOMPtr<nsPIDOMWindowOuter> win = GetWindow();
5546 if (win) {
5547 nsCOMPtr<nsITimer> timer;
5548 NS_NewTimerWithCallback(getter_AddRefs(timer), refreshInfo, delay,
5549 nsITimer::TYPE_ONE_SHOT);
5550
5551 if (timer) {
5552 // Replace the nsRefreshTimer element in the queue with
5553 // its corresponding timer object, so that in case another
5554 // load comes through before the timer can go off, the timer will
5555 // get cancelled in CancelRefreshURITimer()
5556 mRefreshURIList->ReplaceElementAt(timer, n);
5557 }
5558 }
5559 }
5560 }
5561
5562 return NS_OK;
5563}
5564
5565static bool IsFollowupPartOfMultipart(nsIRequest* aRequest) {
5566 nsCOMPtr<nsIMultiPartChannel> multiPartChannel = do_QueryInterface(aRequest);
5567 bool firstPart = false;
5568 return multiPartChannel &&
5569 NS_SUCCEEDED(multiPartChannel->GetIsFirstPart(&firstPart))((bool)(__builtin_expect(!!(!NS_FAILED_impl(multiPartChannel->
GetIsFirstPart(&firstPart))), 1)))
&&
5570 !firstPart;
5571}
5572
5573nsresult nsDocShell::Embed(nsIDocumentViewer* aDocumentViewer,
5574 WindowGlobalChild* aWindowActor,
5575 bool aIsTransientAboutBlank, nsIRequest* aRequest,
5576 nsIURI* aPreviousURI) {
5577 // Save the LayoutHistoryState of the previous document, before
5578 // setting up new document
5579 PersistLayoutHistoryState();
5580
5581 nsresult rv = SetupNewViewer(aDocumentViewer, aWindowActor);
5582 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, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 5582); return rv; } } while (false)
;
5583
5584 // XXX What if SetupNewViewer fails?
5585 if (mozilla::SessionHistoryInParent() ? !!mLoadingEntry : !!mLSHE) {
5586 // Set history.state
5587 SetDocCurrentStateObj(mLSHE,
5588 mLoadingEntry ? &mLoadingEntry->mInfo : nullptr);
5589 }
5590
5591 if (mLSHE) {
5592 // Restore the editing state, if it's stored in session history.
5593 if (mLSHE->HasDetachedEditor()) {
5594 ReattachEditorToWindow(mLSHE);
5595 }
5596
5597 SetHistoryEntryAndUpdateBC(Nothing(), Some<nsISHEntry*>(mLSHE));
5598 }
5599
5600 if (!aIsTransientAboutBlank && mozilla::SessionHistoryInParent() &&
5601 !IsFollowupPartOfMultipart(aRequest)) {
5602 bool expired = false;
5603 uint32_t cacheKey = 0;
5604 nsCOMPtr<nsICacheInfoChannel> cacheChannel = do_QueryInterface(aRequest);
5605 if (cacheChannel) {
5606 // Check if the page has expired from cache
5607 uint32_t expTime = 0;
5608 cacheChannel->GetCacheTokenExpirationTime(&expTime);
5609 uint32_t now = PRTimeToSeconds(PR_Now());
5610 if (expTime <= now) {
5611 expired = true;
5612 }
5613
5614 // The checks for updating cache key are similar to the old session
5615 // history in OnNewURI. Try to update the cache key if
5616 // - we should update session history and aren't doing a session
5617 // history load.
5618 // - we're doing a forced reload.
5619 if (((!mLoadingEntry || !mLoadingEntry->mLoadIsFromSessionHistory) &&
5620 mBrowsingContext->ShouldUpdateSessionHistory(mLoadType)) ||
5621 IsForceReloadType(mLoadType)) {
5622 cacheChannel->GetCacheKey(&cacheKey);
5623 }
5624 }
5625
5626 nsCOMPtr<nsIPrincipal> partitionedPrincipal;
5627 RefPtr<Document> doc = GetDocument();
5628 if (doc) {
5629 partitionedPrincipal = doc->PartitionedPrincipal();
5630 }
5631
5632 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)
;
5633
5634 MoveLoadingToActiveEntry(expired, cacheKey, aPreviousURI,
5635 partitionedPrincipal);
5636 }
5637
5638 bool updateHistory = true;
5639
5640 // Determine if this type of load should update history
5641 switch (mLoadType) {
5642 case LOAD_NORMAL_REPLACE:
5643 case LOAD_REFRESH_REPLACE:
5644 case LOAD_STOP_CONTENT_AND_REPLACE:
5645 case LOAD_RELOAD_BYPASS_CACHE:
5646 case LOAD_RELOAD_BYPASS_PROXY:
5647 case LOAD_RELOAD_BYPASS_PROXY_AND_CACHE:
5648 case LOAD_REPLACE_BYPASS_CACHE:
5649 updateHistory = false;
5650 break;
5651 default:
5652 break;
5653 }
5654
5655 if (!updateHistory) {
5656 SetLayoutHistoryState(nullptr);
5657 }
5658
5659 return NS_OK;
5660}
5661
5662//*****************************************************************************
5663// nsDocShell::nsIWebProgressListener
5664//*****************************************************************************
5665
5666NS_IMETHODIMPnsresult
5667nsDocShell::OnProgressChange(nsIWebProgress* aProgress, nsIRequest* aRequest,
5668 int32_t aCurSelfProgress, int32_t aMaxSelfProgress,
5669 int32_t aCurTotalProgress,
5670 int32_t aMaxTotalProgress) {
5671 // Listeners in the parent process only care about aCurTotalProgress and
5672 // aMaxTotalProgress, which is internally managed by nsDocLoader. Because of
5673 // this, we don't send progress notifications except when they are recorded by
5674 // the toplevel context, and only report them on the toplevel context in the
5675 // parent process.
5676 //
5677 // FIXME: We should track progress for out-of-process iframes and manage total
5678 // progress in the parent process for more accurate notifications.
5679 MOZ_ASSERT(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()" " (" "notification excluded in AddProgressListener(...) for non-toplevel BCs"
")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 5681
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mBrowsingContext->IsTop()"
") (" "notification excluded in AddProgressListener(...) for non-toplevel BCs"
")"); do { MOZ_CrashSequence(__null, 5681); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
5680 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()" " (" "notification excluded in AddProgressListener(...) for non-toplevel BCs"
")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 5681
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mBrowsingContext->IsTop()"
") (" "notification excluded in AddProgressListener(...) for non-toplevel BCs"
")"); do { MOZ_CrashSequence(__null, 5681); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
5681 "notification excluded in AddProgressListener(...) for non-toplevel BCs")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()" " (" "notification excluded in AddProgressListener(...) for non-toplevel BCs"
")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 5681
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mBrowsingContext->IsTop()"
") (" "notification excluded in AddProgressListener(...) for non-toplevel BCs"
")"); do { MOZ_CrashSequence(__null, 5681); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5682
5683 if (nsCOMPtr<nsIWebProgressListener> listener = BCWebProgressListener()) {
5684 listener->OnProgressChange(aProgress, aRequest, aCurSelfProgress,
5685 aMaxSelfProgress, aCurTotalProgress,
5686 aMaxTotalProgress);
5687 }
5688
5689 return NS_OK;
5690}
5691
5692NS_IMETHODIMPnsresult
5693nsDocShell::OnStateChange(nsIWebProgress* aProgress, nsIRequest* aRequest,
5694 uint32_t aStateFlags, nsresult aStatus) {
5695 // If we're receiving a notification on ourselves which has at least one of
5696 // the state change flags in kStateChangeFlagFilter, also notify WebProgress
5697 // on BrowsingContextWebProgress, potentially over IPC.
5698 //
5699 // NOTE: We don't notify for bubbled notifications (aProgress != this), as
5700 // BrowsingContextWebProgress independently handles event bubbling in the
5701 // parent process.
5702 //
5703 // NOTE: We don't filter notifications when registering our listener, as
5704 // `STATE_IS_REDIRECTED_DOCUMENT` cannot be filtered for at registration time.
5705 static constexpr uint32_t kStateChangeFlagFilter =
5706 STATE_IS_NETWORK | STATE_IS_DOCUMENT | STATE_IS_WINDOW |
5707 STATE_IS_REDIRECTED_DOCUMENT;
5708 if (aProgress == this && (aStateFlags & kStateChangeFlagFilter) != 0) {
5709 if (nsCOMPtr<nsIWebProgressListener> listener = BCWebProgressListener()) {
5710 listener->OnStateChange(aProgress, aRequest, aStateFlags, aStatus);
5711 }
5712 }
5713
5714 if ((~aStateFlags & (STATE_START | STATE_IS_NETWORK)) == 0) {
5715 // Save timing statistics.
5716 nsCOMPtr<nsIChannel> channel(do_QueryInterface(aRequest));
5717 nsCOMPtr<nsIURI> uri;
5718 channel->GetURI(getter_AddRefs(uri));
5719 nsAutoCString aURI;
5720 uri->GetAsciiSpec(aURI);
5721
5722 if (this == aProgress) {
5723 mozilla::Unused << MaybeInitTiming();
5724 mTiming->NotifyFetchStart(uri,
5725 ConvertLoadTypeToNavigationType(mLoadType));
5726 // If we are starting a DocumentChannel, we need to pass the timing
5727 // statistics so that should a process switch occur, the starting type can
5728 // be passed to the new DocShell running in the other content process.
5729 if (RefPtr<DocumentChannel> docChannel = do_QueryObject(aRequest)) {
5730 docChannel->SetNavigationTiming(mTiming);
5731 }
5732 }
5733
5734 // Page has begun to load
5735 mBusyFlags = (BusyFlags)(BUSY_FLAGS_BUSY | BUSY_FLAGS_BEFORE_PAGE_LOAD);
5736
5737 if ((aStateFlags & STATE_RESTORING) == 0) {
5738 if (SessionStorePlatformCollection()) {
5739 if (IsForceReloadType(mLoadType)) {
5740 if (WindowContext* windowContext =
5741 mBrowsingContext->GetCurrentWindowContext()) {
5742 SessionStoreChild::From(windowContext->GetWindowGlobalChild())
5743 ->ResetSessionStore(mBrowsingContext,
5744 mBrowsingContext->GetSessionStoreEpoch());
5745 }
5746 }
5747 }
5748 }
5749 } else if ((~aStateFlags & (STATE_TRANSFERRING | STATE_IS_DOCUMENT)) == 0) {
5750 // Page is loading
5751 mBusyFlags = (BusyFlags)(BUSY_FLAGS_BUSY | BUSY_FLAGS_PAGE_LOADING);
5752 } else if ((aStateFlags & STATE_STOP) && (aStateFlags & STATE_IS_NETWORK)) {
5753 // Page has finished loading
5754 mBusyFlags = BUSY_FLAGS_NONE;
5755 }
5756
5757 if ((~aStateFlags & (STATE_IS_DOCUMENT | STATE_STOP)) == 0) {
5758 nsCOMPtr<nsIWebProgress> webProgress =
5759 do_QueryInterface(GetAsSupports(this));
5760 // Is the document stop notification for this document?
5761 if (aProgress == webProgress.get()) {
5762 nsCOMPtr<nsIChannel> channel(do_QueryInterface(aRequest));
5763 EndPageLoad(aProgress, channel, aStatus);
5764 }
5765 }
5766 // note that redirect state changes will go through here as well, but it
5767 // is better to handle those in OnRedirectStateChange where more
5768 // information is available.
5769 return NS_OK;
5770}
5771
5772NS_IMETHODIMPnsresult
5773nsDocShell::OnLocationChange(nsIWebProgress* aProgress, nsIRequest* aRequest,
5774 nsIURI* aURI, uint32_t aFlags) {
5775 // If we're receiving a notification on ourselves, also notify WebProgress on
5776 // BrowsingContextWebProgress, potentially over IPC.
5777 //
5778 // NOTE: We don't notify for bubbled notifications (aProgress != this), as
5779 // BrowsingContextWebProgress independently handles event bubbling in the
5780 // parent process.
5781 //
5782 // NOTE: Tests depend on this happening before UpdateSecurityState.
5783 if (aProgress == this) {
5784 if (nsCOMPtr<nsIWebProgressListener> listener = BCWebProgressListener()) {
5785 listener->OnLocationChange(aProgress, aRequest, aURI, aFlags);
5786 }
5787 }
5788
5789 // Since we've now changed Documents, notify the BrowsingContext that we've
5790 // changed. Ideally we'd just let the BrowsingContext do this when it
5791 // changes the current window global, but that happens before this and we
5792 // have a lot of tests that depend on the specific ordering of messages.
5793 bool isTopLevel = false;
5794 if (XRE_IsParentProcess() &&
5795 !(aFlags & nsIWebProgressListener::LOCATION_CHANGE_SAME_DOCUMENT) &&
5796 NS_SUCCEEDED(aProgress->GetIsTopLevel(&isTopLevel))((bool)(__builtin_expect(!!(!NS_FAILED_impl(aProgress->GetIsTopLevel
(&isTopLevel))), 1)))
&& isTopLevel) {
5797 GetBrowsingContext()->Canonical()->UpdateSecurityState();
5798 }
5799 return NS_OK;
5800}
5801
5802void nsDocShell::OnRedirectStateChange(nsIChannel* aOldChannel,
5803 nsIChannel* aNewChannel,
5804 uint32_t aRedirectFlags,
5805 uint32_t aStateFlags) {
5806 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", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 5807); MOZ_PretendNoReturn(); } } while (0)
5807 "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", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 5807); MOZ_PretendNoReturn(); } } while (0)
;
5808
5809 if (!(aStateFlags & STATE_IS_DOCUMENT)) {
5810 return; // not a toplevel document
5811 }
5812
5813 nsCOMPtr<nsIURI> oldURI, newURI;
5814 aOldChannel->GetURI(getter_AddRefs(oldURI));
5815 aNewChannel->GetURI(getter_AddRefs(newURI));
5816 if (!oldURI || !newURI) {
5817 return;
5818 }
5819
5820 // DocumentChannel adds redirect chain to global history in the parent
5821 // process. The redirect chain can't be queried from the content process, so
5822 // there's no need to update global history here.
5823 RefPtr<DocumentChannel> docChannel = do_QueryObject(aOldChannel);
5824 if (!docChannel) {
5825 // Below a URI visit is saved (see AddURIVisit method doc).
5826 // The visit chain looks something like:
5827 // ...
5828 // Site N - 1
5829 // => Site N
5830 // (redirect to =>) Site N + 1 (we are here!)
5831
5832 // Get N - 1 and transition type
5833 nsCOMPtr<nsIURI> previousURI;
5834 uint32_t previousFlags = 0;
5835 ExtractLastVisit(aOldChannel, getter_AddRefs(previousURI), &previousFlags);
5836
5837 if (aRedirectFlags & nsIChannelEventSink::REDIRECT_INTERNAL ||
5838 net::ChannelIsPost(aOldChannel)) {
5839 // 1. Internal redirects are ignored because they are specific to the
5840 // channel implementation.
5841 // 2. POSTs are not saved by global history.
5842 //
5843 // Regardless, we need to propagate the previous visit to the new
5844 // channel.
5845 SaveLastVisit(aNewChannel, previousURI, previousFlags);
5846 } else {
5847 // Get the HTTP response code, if available.
5848 uint32_t responseStatus = 0;
5849 nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(aOldChannel);
5850 if (httpChannel) {
5851 Unused << httpChannel->GetResponseStatus(&responseStatus);
5852 }
5853
5854 // Add visit N -1 => N
5855 AddURIVisit(oldURI, previousURI, previousFlags, responseStatus);
5856
5857 // Since N + 1 could be the final destination, we will not save N => N + 1
5858 // here. OnNewURI will do that, so we will cache it.
5859 SaveLastVisit(aNewChannel, oldURI, aRedirectFlags);
5860 }
5861 }
5862
5863 if (!(aRedirectFlags & nsIChannelEventSink::REDIRECT_INTERNAL) &&
5864 mLoadType & (LOAD_CMD_RELOAD | LOAD_CMD_HISTORY)) {
5865 mLoadType = LOAD_NORMAL_REPLACE;
5866 SetHistoryEntryAndUpdateBC(Some(nullptr), Nothing());
5867 }
5868}
5869
5870NS_IMETHODIMPnsresult
5871nsDocShell::OnStatusChange(nsIWebProgress* aWebProgress, nsIRequest* aRequest,
5872 nsresult aStatus, const char16_t* aMessage) {
5873 // If we're receiving a notification on ourselves, also notify WebProgress on
5874 // BrowsingContextWebProgress, potentially over IPC.
5875 //
5876 // NOTE: We don't notify for bubbled notifications (aWebProgress != this), as
5877 // BrowsingContextWebProgress independently handles event bubbling in the
5878 // parent process.
5879 if (aWebProgress == this) {
5880 if (nsCOMPtr<nsIWebProgressListener> listener = BCWebProgressListener()) {
5881 listener->OnStatusChange(aWebProgress, aRequest, aStatus, aMessage);
5882 }
5883 }
5884
5885 return NS_OK;
5886}
5887
5888NS_IMETHODIMPnsresult
5889nsDocShell::OnSecurityChange(nsIWebProgress* aWebProgress, nsIRequest* aRequest,
5890 uint32_t aState) {
5891 // If we're receiving a notification on ourselves, also notify WebProgress on
5892 // BrowsingContextWebProgress, potentially over IPC.
5893 //
5894 // NOTE: We don't notify for bubbled notifications (aWebProgress != this), as
5895 // BrowsingContextWebProgress independently handles event bubbling in the
5896 // parent process.
5897 if (aWebProgress == this) {
5898 if (nsCOMPtr<nsIWebProgressListener> listener = BCWebProgressListener()) {
5899 listener->OnSecurityChange(aWebProgress, aRequest, aState);
5900 }
5901 }
5902
5903 return NS_OK;
5904}
5905
5906NS_IMETHODIMPnsresult
5907nsDocShell::OnContentBlockingEvent(nsIWebProgress* aWebProgress,
5908 nsIRequest* aRequest, uint32_t aEvent) {
5909 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(...)" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 5909); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "notification excluded in AddProgressListener(...)"
")"); do { MOZ_CrashSequence(__null, 5909); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5910 return NS_OK;
5911}
5912
5913already_AddRefed<nsIWebProgressListener> nsDocShell::BCWebProgressListener() {
5914 // If this BrowsingContext has been replaced, we should discard any
5915 // notifications which would otherwise be delivered in-process.
5916 if (XRE_IsParentProcess() && mBrowsingContext->Canonical()->IsReplaced()) {
5917 return nullptr;
5918 }
5919
5920 // Create a nsBrowserStatusFilter to perform some throttling of
5921 // OnProgressChange and OnStatusChange notifications which are delivered to
5922 // our BCWebProgress listener. This reduces the amount of IPC traffic.
5923 if (!mBCWebProgressStatusFilter && !mIsBeingDestroyed) {
5924 nsCOMPtr<nsIWebProgressListener> innerListener;
5925 if (XRE_IsParentProcess()) {
5926 innerListener = mBrowsingContext->Canonical()->GetWebProgress();
5927 } else {
5928 innerListener = do_QueryReferent(mBrowserChild);
5929 }
5930 if (innerListener) {
5931 // NOTE: We need to disable filtering of StateChange events here, as
5932 // listeners on BrowsingContextWebProgress may depend on state change
5933 // notifications are otherwise filtered.
5934 // NOTE: Unlike other nsIWebProgress types, nsBrowserStatusFilter holds a
5935 // strong cycle-collected reference to the inner listener.
5936 mBCWebProgressStatusFilter =
5937 new nsBrowserStatusFilter(/* aDisableStateChangeFilters */ true);
5938 mBCWebProgressStatusFilter->AddProgressListener(
5939 innerListener, nsIWebProgress::NOTIFY_ALL);
5940 }
5941 }
5942
5943 return do_AddRef(mBCWebProgressStatusFilter);
5944}
5945
5946already_AddRefed<nsIURIFixupInfo> nsDocShell::KeywordToURI(
5947 const nsACString& aKeyword, bool aIsPrivateContext) {
5948 nsCOMPtr<nsIURIFixupInfo> info;
5949 if (!XRE_IsContentProcess()) {
5950 nsCOMPtr<nsIURIFixup> uriFixup = components::URIFixup::Service();
5951 if (uriFixup) {
5952 uriFixup->KeywordToURI(aKeyword, aIsPrivateContext, getter_AddRefs(info));
5953 }
5954 }
5955 return info.forget();
5956}
5957
5958/* static */
5959already_AddRefed<nsIURI> nsDocShell::MaybeFixBadCertDomainErrorURI(
5960 nsIChannel* aChannel, nsIURI* aUrl) {
5961 if (!aChannel) {
5962 return nullptr;
5963 }
5964
5965 nsresult rv = NS_OK;
5966 nsAutoCString host;
5967 rv = aUrl->GetAsciiHost(host);
5968 if (NS_WARN_IF(NS_FAILED(rv))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(rv
)), 0))), "NS_FAILED(rv)", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 5968)
) {
5969 return nullptr;
5970 }
5971
5972 // Return if fixup enable pref is turned off.
5973 if (!mozilla::StaticPrefs::security_bad_cert_domain_error_url_fix_enabled()) {
5974 return nullptr;
5975 }
5976
5977 // Return if scheme is not HTTPS.
5978 if (!aUrl->SchemeIs("https")) {
5979 return nullptr;
5980 }
5981
5982 nsCOMPtr<nsILoadInfo> info = aChannel->LoadInfo();
5983 if (!info) {
5984 return nullptr;
5985 }
5986
5987 // Skip doing the fixup if our channel was redirected, because we
5988 // shouldn't be guessing things about the post-redirect URI.
5989 if (!info->RedirectChain().IsEmpty()) {
5990 return nullptr;
5991 }
5992
5993 int32_t port = 0;
5994 rv = aUrl->GetPort(&port);
5995 if (NS_WARN_IF(NS_FAILED(rv))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(rv
)), 0))), "NS_FAILED(rv)", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 5995)
) {
5996 return nullptr;
5997 }
5998
5999 // Don't fix up hosts with ports.
6000 if (port != -1) {
6001 return nullptr;
6002 }
6003
6004 // Don't fix up localhost url.
6005 if (host == "localhost") {
6006 return nullptr;
6007 }
6008
6009 // Don't fix up hostnames with IP address.
6010 if (net_IsValidIPv4Addr(host) || net_IsValidIPv6Addr(host)) {
6011 return nullptr;
6012 }
6013
6014 nsAutoCString userPass;
6015 rv = aUrl->GetUserPass(userPass);
6016 if (NS_WARN_IF(NS_FAILED(rv))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(rv
)), 0))), "NS_FAILED(rv)", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 6016)
) {
6017 return nullptr;
6018 }
6019
6020 // Security - URLs with user / password info should NOT be modified.
6021 if (!userPass.IsEmpty()) {
6022 return nullptr;
6023 }
6024
6025 nsCOMPtr<nsITransportSecurityInfo> tsi;
6026 rv = aChannel->GetSecurityInfo(getter_AddRefs(tsi));
6027 if (NS_WARN_IF(NS_FAILED(rv))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(rv
)), 0))), "NS_FAILED(rv)", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 6027)
) {
6028 return nullptr;
6029 }
6030
6031 if (NS_WARN_IF(!tsi)NS_warn_if_impl(!tsi, "!tsi", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 6031)
) {
6032 return nullptr;
6033 }
6034
6035 nsCOMPtr<nsIX509Cert> cert;
6036 rv = tsi->GetServerCert(getter_AddRefs(cert));
6037 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", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 6037)
) {
6038 return nullptr;
6039 }
6040
6041 nsTArray<uint8_t> certBytes;
6042 rv = cert->GetRawDER(certBytes);
6043 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
6044 return nullptr;
6045 }
6046
6047 mozilla::pkix::Input serverCertInput;
6048 mozilla::pkix::Result result =
6049 serverCertInput.Init(certBytes.Elements(), certBytes.Length());
6050 if (result != mozilla::pkix::Success) {
6051 return nullptr;
6052 }
6053
6054 constexpr auto wwwPrefix = "www."_ns;
6055 nsAutoCString newHost;
6056 if (StringBeginsWith(host, wwwPrefix)) {
6057 // Try www.example.com -> example.com
6058 newHost.Assign(Substring(host, wwwPrefix.Length()));
6059 } else {
6060 // Try example.com -> www.example.com
6061 newHost.Assign(wwwPrefix);
6062 newHost.Append(host);
6063 }
6064
6065 mozilla::pkix::Input newHostInput;
6066 result = newHostInput.Init(
6067 BitwiseCast<const uint8_t*, const char*>(newHost.BeginReading()),
6068 newHost.Length());
6069 if (result != mozilla::pkix::Success) {
6070 return nullptr;
6071 }
6072
6073 // Because certificate verification returned Result::ERROR_BAD_CERT_DOMAIN /
6074 // SSL_ERROR_BAD_CERT_DOMAIN, a chain was built and we know whether or not
6075 // the root was a built-in.
6076 bool rootIsBuiltIn;
6077 if (NS_FAILED(tsi->GetIsBuiltCertChainRootBuiltInRoot(&rootIsBuiltIn))((bool)(__builtin_expect(!!(NS_FAILED_impl(tsi->GetIsBuiltCertChainRootBuiltInRoot
(&rootIsBuiltIn))), 0)))
) {
6078 return nullptr;
6079 }
6080 mozilla::psm::SkipInvalidSANsForNonBuiltInRootsPolicy nameMatchingPolicy(
6081 rootIsBuiltIn);
6082
6083 // Check if the certificate is valid for the new hostname.
6084 result = mozilla::pkix::CheckCertHostname(serverCertInput, newHostInput,
6085 nameMatchingPolicy);
6086 if (result != mozilla::pkix::Success) {
6087 return nullptr;
6088 }
6089
6090 nsCOMPtr<nsIURI> newURI;
6091 Unused << NS_MutateURI(aUrl).SetHost(newHost).Finalize(
6092 getter_AddRefs(newURI));
6093
6094 return newURI.forget();
6095}
6096
6097/* static */
6098already_AddRefed<nsIURI> nsDocShell::AttemptURIFixup(
6099 nsIChannel* aChannel, nsresult aStatus,
6100 const mozilla::Maybe<nsCString>& aOriginalURIString, uint32_t aLoadType,
6101 bool aIsTopFrame, bool aAllowKeywordFixup, bool aUsePrivateBrowsing,
6102 bool aNotifyKeywordSearchLoading, nsIInputStream** aNewPostData,
6103 nsILoadInfo::SchemelessInputType* outSchemelessInput) {
6104 if (aStatus != NS_ERROR_UNKNOWN_HOST && aStatus != NS_ERROR_NET_RESET &&
6105 aStatus != NS_ERROR_CONNECTION_REFUSED &&
6106 aStatus !=
6107 mozilla::psm::GetXPCOMFromNSSError(SSL_ERROR_BAD_CERT_DOMAIN)) {
6108 return nullptr;
6109 }
6110
6111 if (!(aLoadType == LOAD_NORMAL && aIsTopFrame) && !aAllowKeywordFixup) {
6112 return nullptr;
6113 }
6114
6115 nsCOMPtr<nsIURI> url;
6116 nsresult rv = aChannel->GetURI(getter_AddRefs(url));
6117 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
6118 return nullptr;
6119 }
6120
6121 //
6122 // Try and make an alternative URI from the old one
6123 //
6124 nsCOMPtr<nsIURI> newURI;
6125 nsCOMPtr<nsIInputStream> newPostData;
6126
6127 nsAutoCString oldSpec;
6128 url->GetSpec(oldSpec);
6129
6130 //
6131 // First try keyword fixup
6132 //
6133 nsAutoString keywordProviderName, keywordAsSent;
6134 if (aStatus == NS_ERROR_UNKNOWN_HOST && aAllowKeywordFixup) {
6135 // we should only perform a keyword search under the following
6136 // conditions:
6137 // (0) Pref keyword.enabled is true
6138 // (1) the url scheme is http (or https)
6139 // (2) the url does not have a protocol scheme
6140 // If we don't enforce such a policy, then we end up doing
6141 // keyword searchs on urls we don't intend like imap, file,
6142 // mailbox, etc. This could lead to a security problem where we
6143 // send data to the keyword server that we shouldn't be.
6144 // Someone needs to clean up keywords in general so we can
6145 // determine on a per url basis if we want keywords
6146 // enabled...this is just a bandaid...
6147 if (Preferences::GetBool("keyword.enabled", false) &&
6148 net::SchemeIsHttpOrHttps(url)) {
6149 bool attemptFixup = false;
6150 nsAutoCString host;
6151 Unused << url->GetHost(host);
6152 if (host.FindChar('.') == kNotFound) {
6153 attemptFixup = true;
6154 } else {
6155 // For domains with dots, we check the public suffix validity.
6156 nsCOMPtr<nsIEffectiveTLDService> tldService =
6157 do_GetService(NS_EFFECTIVETLDSERVICE_CONTRACTID"@mozilla.org/network/effective-tld-service;1");
6158 if (tldService) {
6159 nsAutoCString suffix;
6160 attemptFixup =
6161 NS_SUCCEEDED(tldService->GetKnownPublicSuffix(url, suffix))((bool)(__builtin_expect(!!(!NS_FAILED_impl(tldService->GetKnownPublicSuffix
(url, suffix))), 1)))
&&
6162 suffix.IsEmpty();
6163 }
6164 }
6165 if (attemptFixup) {
6166 nsCOMPtr<nsIURIFixupInfo> info;
6167 // only send non-qualified hosts to the keyword server
6168 if (aOriginalURIString && !aOriginalURIString->IsEmpty()) {
6169 info = KeywordToURI(*aOriginalURIString, aUsePrivateBrowsing);
6170 } else {
6171 //
6172 // If this string was passed through nsStandardURL by
6173 // chance, then it may have been converted from UTF-8 to
6174 // Punycode, which would result in a completely bogus keyword
6175 // query. Here we try to recover the original Unicode
6176 // value, but this is not 100% correct since the value may
6177 // have been normalized per the IDN normalization rules.
6178 //
6179 // Since we don't have access to the exact original string
6180 // that was entered by the user, this will just have to do.
6181 nsAutoCString utf8Host;
6182 mozilla_net_recover_keyword_from_punycode(&host, &utf8Host);
6183 info = KeywordToURI(utf8Host, aUsePrivateBrowsing);
6184 }
6185 if (info) {
6186 info->GetPreferredURI(getter_AddRefs(newURI));
6187 info->GetSchemelessInput(outSchemelessInput);
6188 if (newURI) {
6189 info->GetKeywordAsSent(keywordAsSent);
6190 info->GetKeywordProviderName(keywordProviderName);
6191 info->GetPostData(getter_AddRefs(newPostData));
6192 }
6193 }
6194 }
6195 }
6196 }
6197
6198 //
6199 // Now try change the address, e.g. turn http://foo into
6200 // http://www.foo.com, and if that doesn't work try https with
6201 // https://foo and https://www.foo.com.
6202 //
6203 if (aStatus == NS_ERROR_UNKNOWN_HOST || aStatus == NS_ERROR_NET_RESET) {
6204 // Skip fixup for anything except a normal document load
6205 // operation on the topframe.
6206 bool doCreateAlternate = aLoadType == LOAD_NORMAL && aIsTopFrame;
6207
6208 if (doCreateAlternate) {
6209 nsCOMPtr<nsILoadInfo> loadInfo = aChannel->LoadInfo();
6210 nsIPrincipal* principal = loadInfo->TriggeringPrincipal();
6211 // Only do this if our channel was loaded directly by the user from the
6212 // URL bar or similar (system principal) and not redirected, because we
6213 // shouldn't be guessing things about links from other sites, or a
6214 // post-redirect URI.
6215 doCreateAlternate = principal && principal->IsSystemPrincipal() &&
6216 loadInfo->RedirectChain().IsEmpty();
6217 }
6218 // Test if keyword lookup produced a new URI or not
6219 if (doCreateAlternate && newURI) {
6220 bool sameURI = false;
6221 url->Equals(newURI, &sameURI);
6222 if (!sameURI) {
6223 // Keyword lookup made a new URI so no need to try
6224 // an alternate one.
6225 doCreateAlternate = false;
6226 }
6227 }
6228 if (doCreateAlternate) {
6229 newURI = nullptr;
6230 newPostData = nullptr;
6231 keywordProviderName.Truncate();
6232 keywordAsSent.Truncate();
6233 nsCOMPtr<nsIURIFixup> uriFixup = components::URIFixup::Service();
6234 if (uriFixup) {
6235 nsCOMPtr<nsIURIFixupInfo> fixupInfo;
6236 uriFixup->GetFixupURIInfo(oldSpec, nsIURIFixup::FIXUP_FLAG_NONE,
6237 getter_AddRefs(fixupInfo));
6238 if (fixupInfo) {
6239 fixupInfo->GetPreferredURI(getter_AddRefs(newURI));
6240 }
6241 }
6242 }
6243 } else if (aStatus == NS_ERROR_CONNECTION_REFUSED &&
6244 Preferences::GetBool("browser.fixup.fallback-to-https", false)) {
6245 // Try HTTPS, since http didn't work
6246 if (url->SchemeIs("http")) {
6247 int32_t port = 0;
6248 url->GetPort(&port);
6249
6250 // Fall back to HTTPS only if port is default
6251 if (port == -1) {
6252 newURI = nullptr;
6253 newPostData = nullptr;
6254 Unused << NS_MutateURI(url)
6255 .SetScheme("https"_ns)
6256 .Finalize(getter_AddRefs(newURI));
6257 }
6258 }
6259 }
6260
6261 // If we have a SSL_ERROR_BAD_CERT_DOMAIN error, try adding or removing
6262 // "www." to/from the beginning of the domain name to see if we can avoid
6263 // showing the cert error page. For example, https://example.com ->
6264 // https://www.example.com or https://www.example.com -> https://example.com.
6265 if (aStatus ==
6266 mozilla::psm::GetXPCOMFromNSSError(SSL_ERROR_BAD_CERT_DOMAIN)) {
6267 newPostData = nullptr;
6268 newURI = MaybeFixBadCertDomainErrorURI(aChannel, url);
6269 }
6270
6271 // Did we make a new URI that is different to the old one? If so
6272 // load it.
6273 //
6274 if (newURI) {
6275 // Make sure the new URI is different from the old one,
6276 // otherwise there's little point trying to load it again.
6277 bool sameURI = false;
6278 url->Equals(newURI, &sameURI);
6279 if (!sameURI) {
6280 if (aNewPostData) {
6281 newPostData.forget(aNewPostData);
6282 }
6283 if (aNotifyKeywordSearchLoading) {
6284 // This notification is meant for Firefox Health Report so it
6285 // can increment counts from the search engine
6286 MaybeNotifyKeywordSearchLoading(keywordProviderName, keywordAsSent);
6287 }
6288 return newURI.forget();
6289 }
6290 }
6291
6292 return nullptr;
6293}
6294
6295nsresult nsDocShell::FilterStatusForErrorPage(
6296 nsresult aStatus, nsIChannel* aChannel, uint32_t aLoadType,
6297 bool aIsTopFrame, bool aUseErrorPages,
6298 bool* aSkippedUnknownProtocolNavigation) {
6299 // Errors to be shown only on top-level frames
6300 if ((aStatus == NS_ERROR_UNKNOWN_HOST ||
6301 aStatus == NS_ERROR_CONNECTION_REFUSED ||
6302 aStatus == NS_ERROR_UNKNOWN_PROXY_HOST ||
6303 aStatus == NS_ERROR_PROXY_CONNECTION_REFUSED ||
6304 aStatus == NS_ERROR_PROXY_FORBIDDEN ||
6305 aStatus == NS_ERROR_PROXY_NOT_IMPLEMENTED ||
6306 aStatus == NS_ERROR_PROXY_AUTHENTICATION_FAILED ||
6307 aStatus == NS_ERROR_PROXY_TOO_MANY_REQUESTS ||
6308 aStatus == NS_ERROR_MALFORMED_URI ||
6309 aStatus == NS_ERROR_BLOCKED_BY_POLICY ||
6310 aStatus == NS_ERROR_DOM_COOP_FAILED ||
6311 aStatus == NS_ERROR_DOM_COEP_FAILED ||
6312 aStatus == NS_ERROR_DOM_INVALID_HEADER_VALUE) &&
6313 (aIsTopFrame || aUseErrorPages)) {
6314 return aStatus;
6315 }
6316
6317 if (aStatus == NS_ERROR_NET_TIMEOUT ||
6318 aStatus == NS_ERROR_NET_TIMEOUT_EXTERNAL ||
6319 aStatus == NS_ERROR_NET_EMPTY_RESPONSE ||
6320 aStatus == NS_ERROR_NET_ERROR_RESPONSE ||
6321 aStatus == NS_ERROR_PROXY_GATEWAY_TIMEOUT ||
6322 aStatus == NS_ERROR_REDIRECT_LOOP ||
6323 aStatus == NS_ERROR_UNKNOWN_SOCKET_TYPE ||
6324 aStatus == NS_ERROR_NET_INTERRUPT || aStatus == NS_ERROR_NET_RESET ||
6325 aStatus == NS_ERROR_PROXY_BAD_GATEWAY || aStatus == NS_ERROR_OFFLINE ||
6326 aStatus == NS_ERROR_MALWARE_URI || aStatus == NS_ERROR_PHISHING_URI ||
6327 aStatus == NS_ERROR_UNWANTED_URI || aStatus == NS_ERROR_HARMFUL_URI ||
6328 aStatus == NS_ERROR_UNSAFE_CONTENT_TYPE ||
6329 aStatus == NS_ERROR_INTERCEPTION_FAILED ||
6330 aStatus == NS_ERROR_NET_INADEQUATE_SECURITY ||
6331 aStatus == NS_ERROR_NET_HTTP2_SENT_GOAWAY ||
6332 aStatus == NS_ERROR_NET_HTTP3_PROTOCOL_ERROR ||
6333 aStatus == NS_ERROR_BASIC_HTTP_AUTH_DISABLED ||
6334 aStatus == NS_ERROR_DOM_BAD_URI || aStatus == NS_ERROR_FILE_NOT_FOUND ||
6335 aStatus == NS_ERROR_FILE_ACCESS_DENIED ||
6336 aStatus == NS_ERROR_CORRUPTED_CONTENT ||
6337 aStatus == NS_ERROR_INVALID_CONTENT_ENCODING ||
6338 NS_ERROR_GET_MODULE(aStatus) == NS_ERROR_MODULE_SECURITY21) {
6339 // Errors to be shown for any frame
6340 return aStatus;
6341 }
6342
6343 if (aStatus == NS_ERROR_UNKNOWN_PROTOCOL) {
6344 // For unknown protocols we only display an error if the load is triggered
6345 // by the browser itself. Showing the error for page-triggered navigations
6346 // causes annoying behavior for users when a page tries to open an external
6347 // app which has not been installed, see bug 1528305. A missing WebExtension
6348 // protocol handlers will however always load the error page, as it is not
6349 // expected to be opened externally, see bug 1921426.
6350 nsCOMPtr<nsILoadInfo> info = aChannel->LoadInfo();
6351 if (!info->TriggeringPrincipal()->IsSystemPrincipal() &&
6352 !BasePrincipal::Cast(info->TriggeringPrincipal())->AddonPolicy()) {
6353 if (aSkippedUnknownProtocolNavigation) {
6354 *aSkippedUnknownProtocolNavigation = true;
6355 }
6356 return NS_OK;
6357 }
6358 return aStatus;
6359 }
6360
6361 if (aStatus == NS_ERROR_DOCUMENT_NOT_CACHED) {
6362 // Non-caching channels will simply return NS_ERROR_OFFLINE.
6363 // Caching channels would have to look at their flags to work
6364 // out which error to return. Or we can fix up the error here.
6365 if (!(aLoadType & LOAD_CMD_HISTORY)) {
6366 return NS_ERROR_OFFLINE;
6367 }
6368 return aStatus;
6369 }
6370
6371 return NS_OK;
6372}
6373
6374nsresult nsDocShell::EndPageLoad(nsIWebProgress* aProgress,
6375 nsIChannel* aChannel, nsresult aStatus) {
6376 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)
6377 ("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)
6378 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)
;
6379 if (!aChannel) {
6380 return NS_ERROR_NULL_POINTER;
6381 }
6382
6383 // Make sure to discard the initial client if we never created the initial
6384 // about:blank document. Do this before possibly returning from the method
6385 // due to an error.
6386 mInitialClientSource.reset();
6387
6388 nsCOMPtr<nsIConsoleReportCollector> reporter = do_QueryInterface(aChannel);
6389 if (reporter) {
6390 nsCOMPtr<nsILoadGroup> loadGroup;
6391 aChannel->GetLoadGroup(getter_AddRefs(loadGroup));
6392 if (loadGroup) {
6393 reporter->FlushConsoleReports(loadGroup);
6394 } else {
6395 reporter->FlushConsoleReports(GetDocument());
6396 }
6397 }
6398
6399 nsCOMPtr<nsIURI> url;
6400 nsresult rv = aChannel->GetURI(getter_AddRefs(url));
6401 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
6402 return rv;
6403 }
6404
6405 nsCOMPtr<nsITimedChannel> timingChannel = do_QueryInterface(aChannel);
6406 if (timingChannel) {
6407 TimeStamp channelCreationTime;
6408 rv = timingChannel->GetChannelCreation(&channelCreationTime);
6409 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && !channelCreationTime.IsNull()) {
6410 glean::performance_page::total_content_page_load.AccumulateRawDuration(
6411 TimeStamp::Now() - channelCreationTime);
6412 }
6413 }
6414
6415 // Timing is picked up by the window, we don't need it anymore
6416 mTiming = nullptr;
6417
6418 // clean up reload state for meta charset
6419 if (eCharsetReloadRequested == mCharsetReloadState) {
6420 mCharsetReloadState = eCharsetReloadStopOrigional;
6421 } else {
6422 mCharsetReloadState = eCharsetReloadInit;
6423 }
6424
6425 // Save a pointer to the currently-loading history entry.
6426 // nsDocShell::EndPageLoad will clear mLSHE, but we may need this history
6427 // entry further down in this method.
6428 nsCOMPtr<nsISHEntry> loadingSHE = mLSHE;
6429 mozilla::Unused << loadingSHE; // XXX: Not sure if we need this anymore
6430
6431 //
6432 // one of many safeguards that prevent death and destruction if
6433 // someone is so very very rude as to bring this window down
6434 // during this load handler.
6435 //
6436 nsCOMPtr<nsIDocShell> kungFuDeathGrip(this);
6437
6438 // Notify the DocumentViewer that the Document has finished loading. This
6439 // will cause any OnLoad(...) and PopState(...) handlers to fire.
6440 if (!mEODForCurrentDocument && mDocumentViewer) {
6441 mIsExecutingOnLoadHandler = true;
6442 nsCOMPtr<nsIDocumentViewer> viewer = mDocumentViewer;
6443 viewer->LoadComplete(aStatus);
6444 mIsExecutingOnLoadHandler = false;
6445
6446 mEODForCurrentDocument = true;
6447 }
6448 /* Check if the httpChannel has any cache-control related response headers,
6449 * like no-store, no-cache. If so, update SHEntry so that
6450 * when a user goes back/forward to this page, we appropriately do
6451 * form value restoration or load from server.
6452 */
6453 nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(aChannel));
6454 if (!httpChannel) {
6455 // HttpChannel could be hiding underneath a Multipart channel.
6456 GetHttpChannel(aChannel, getter_AddRefs(httpChannel));
6457 }
6458
6459 if (httpChannel) {
6460 // figure out if SH should be saving layout state.
6461 bool discardLayoutState = ShouldDiscardLayoutState(httpChannel);
6462 if (mLSHE && discardLayoutState && (mLoadType & LOAD_CMD_NORMAL) &&
6463 (mLoadType != LOAD_BYPASS_HISTORY) && (mLoadType != LOAD_ERROR_PAGE)) {
6464 mLSHE->SetSaveLayoutStateFlag(false);
6465 }
6466 }
6467
6468 // Clear mLSHE after calling the onLoadHandlers. This way, if the
6469 // onLoadHandler tries to load something different in
6470 // itself or one of its children, we can deal with it appropriately.
6471 if (mLSHE) {
6472 mLSHE->SetLoadType(LOAD_HISTORY);
6473
6474 // Clear the mLSHE reference to indicate document loading is done one
6475 // way or another.
6476 SetHistoryEntryAndUpdateBC(Some(nullptr), Nothing());
6477 }
6478 mActiveEntryIsLoadingFromSessionHistory = false;
6479
6480 // if there's a refresh header in the channel, this method
6481 // will set it up for us.
6482 if (mBrowsingContext->IsActive() || !mDisableMetaRefreshWhenInactive)
6483 RefreshURIFromQueue();
6484
6485 // Test whether this is the top frame or a subframe
6486 bool isTopFrame = mBrowsingContext->IsTop();
6487
6488 bool hadErrorStatus = false;
6489 // If status code indicates an error it means that DocumentChannel already
6490 // tried to fixup the uri and failed. Throw an error dialog box here.
6491 if (NS_FAILED(aStatus)((bool)(__builtin_expect(!!(NS_FAILED_impl(aStatus)), 0)))) {
6492 // If we got CONTENT_BLOCKED from EndPageLoad, then we need to fire
6493 // the error event to our embedder, since tests are relying on this.
6494 // The error event is usually fired by the caller of InternalLoad, but
6495 // this particular error can happen asynchronously.
6496 // Bug 1629201 is filed for having much clearer decision making around
6497 // which cases need error events.
6498 bool fireFrameErrorEvent = (aStatus == NS_ERROR_CONTENT_BLOCKED_SHOW_ALT ||
6499 aStatus == NS_ERROR_CONTENT_BLOCKED);
6500 UnblockEmbedderLoadEventForFailure(fireFrameErrorEvent);
6501
6502 bool skippedUnknownProtocolNavigation = false;
6503 aStatus = FilterStatusForErrorPage(aStatus, aChannel, mLoadType, isTopFrame,
6504 mBrowsingContext->GetUseErrorPages(),
6505 &skippedUnknownProtocolNavigation);
6506 hadErrorStatus = true;
6507 if (NS_FAILED(aStatus)((bool)(__builtin_expect(!!(NS_FAILED_impl(aStatus)), 0)))) {
6508 if (!mIsBeingDestroyed) {
6509 DisplayLoadError(aStatus, url, nullptr, aChannel);
6510 }
6511 } else if (skippedUnknownProtocolNavigation) {
6512 nsAutoCString sanitized;
6513 nsTArray<nsString> params;
6514 if (NS_SUCCEEDED(NS_GetSanitizedURIStringFromURI(url, sanitized))((bool)(__builtin_expect(!!(!NS_FAILED_impl(NS_GetSanitizedURIStringFromURI
(url, sanitized))), 1)))
) {
6515 params.AppendElement(NS_ConvertUTF8toUTF16(sanitized));
6516 } else {
6517 params.AppendElement(u"(unknown uri)"_ns);
6518 }
6519 nsContentUtils::ReportToConsole(
6520 nsIScriptError::warningFlag, "DOM"_ns, GetExtantDocument(),
6521 nsContentUtils::eDOM_PROPERTIES, "UnknownProtocolNavigationPrevented",
6522 params);
6523 }
6524 } else {
6525 // If we have a host
6526 nsCOMPtr<nsILoadInfo> loadInfo = aChannel->LoadInfo();
6527 PredictorLearnRedirect(url, aChannel, loadInfo->GetOriginAttributes());
6528 }
6529
6530 if (hadErrorStatus) {
6531 // Don't send session store updates if the reason EndPageLoad was called is
6532 // because we are process switching. Sometimes the update takes too long and
6533 // incorrectly overrides session store data from the following load.
6534 return NS_OK;
6535 }
6536 if (SessionStorePlatformCollection()) {
6537 if (WindowContext* windowContext =
6538 mBrowsingContext->GetCurrentWindowContext()) {
6539 using Change = SessionStoreChangeListener::Change;
6540
6541 // We've finished loading the page and now we want to collect all the
6542 // session store state that the page is initialized with.
6543 SessionStoreChangeListener::CollectSessionStoreData(
6544 windowContext,
6545 EnumSet<Change>(Change::Input, Change::Scroll, Change::SessionHistory,
6546 Change::WireFrame));
6547 }
6548 }
6549
6550 return NS_OK;
6551}
6552
6553//*****************************************************************************
6554// nsDocShell: Content Viewer Management
6555//*****************************************************************************
6556
6557nsresult nsDocShell::EnsureDocumentViewer() {
6558 if (mDocumentViewer) {
6559 return NS_OK;
6560 }
6561 if (mIsBeingDestroyed) {
6562 return NS_ERROR_FAILURE;
6563 }
6564
6565 nsCOMPtr<nsIContentSecurityPolicy> cspToInheritForAboutBlank;
6566 nsCOMPtr<nsIURI> baseURI;
6567 nsIPrincipal* principal = GetInheritedPrincipal(false);
6568 nsIPrincipal* partitionedPrincipal = GetInheritedPrincipal(false, true);
6569
6570 nsCOMPtr<nsIDocShellTreeItem> parentItem;
6571 GetInProcessSameTypeParent(getter_AddRefs(parentItem));
6572 if (parentItem) {
6573 if (nsCOMPtr<nsPIDOMWindowOuter> domWin = GetWindow()) {
6574 nsCOMPtr<Element> parentElement = domWin->GetFrameElementInternal();
6575 if (parentElement) {
6576 baseURI = parentElement->GetBaseURI();
6577 cspToInheritForAboutBlank = parentElement->GetCsp();
6578 }
6579 }
6580 }
6581
6582 nsresult rv = CreateAboutBlankDocumentViewer(
6583 principal, partitionedPrincipal, cspToInheritForAboutBlank, baseURI,
6584 /* aIsInitialDocument */ true);
6585
6586 NS_ENSURE_STATE(mDocumentViewer)do { if ((__builtin_expect(!!(!(mDocumentViewer)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "mDocumentViewer" ") failed"
, nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 6586); return NS_ERROR_UNEXPECTED; } } while (false)
;
6587
6588 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
6589 RefPtr<Document> doc(GetDocument());
6590 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!" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 6592); AnnotateMozCrashReason("MOZ_ASSERT" "(" "doc" ") (" "Should have doc if CreateAboutBlankDocumentViewer "
"succeeded!" ")"); do { MOZ_CrashSequence(__null, 6592); __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
6591 "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!" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 6592); AnnotateMozCrashReason("MOZ_ASSERT" "(" "doc" ") (" "Should have doc if CreateAboutBlankDocumentViewer "
"succeeded!" ")"); do { MOZ_CrashSequence(__null, 6592); __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
6592 "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!" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 6592); AnnotateMozCrashReason("MOZ_ASSERT" "(" "doc" ") (" "Should have doc if CreateAboutBlankDocumentViewer "
"succeeded!" ")"); do { MOZ_CrashSequence(__null, 6592); __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
;
6593 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" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 6593); AnnotateMozCrashReason("MOZ_ASSERT" "(" "doc->IsInitialDocument()"
") (" "Document should be initial document" ")"); do { MOZ_CrashSequence
(__null, 6593); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
6594
6595 // Documents created using EnsureDocumentViewer may be transient
6596 // placeholders created by framescripts before content has a
6597 // chance to load. In some cases, window.open(..., "noopener")
6598 // will create such a document and then synchronously tear it
6599 // down, firing a "pagehide" event. Doing so violates our
6600 // assertions about DocGroups. It's easier to silence the
6601 // assertion here than to avoid creating the extra document.
6602 doc->IgnoreDocGroupMismatches();
6603 }
6604
6605 return rv;
6606}
6607
6608nsresult nsDocShell::CreateAboutBlankDocumentViewer(
6609 nsIPrincipal* aPrincipal, nsIPrincipal* aPartitionedPrincipal,
6610 nsIContentSecurityPolicy* aCSP, nsIURI* aBaseURI, bool aIsInitialDocument,
6611 const Maybe<nsILoadInfo::CrossOriginEmbedderPolicy>& aCOEP,
6612 bool aTryToSaveOldPresentation, bool aCheckPermitUnload,
6613 WindowGlobalChild* aActor) {
6614 RefPtr<Document> blankDoc;
6615 nsCOMPtr<nsIDocumentViewer> viewer;
6616 nsresult rv = NS_ERROR_FAILURE;
6617
6618 PROFILER_MARKER_UNTYPED("CreateAboutBlankDocumentViewer", DOM,do { ; do { if (profiler_is_collecting_markers()) { ::profiler_add_marker_impl
("CreateAboutBlankDocumentViewer", ::geckoprofiler::category::
DOM, MarkerStack::Capture()); } } while (false); } while (false
)
6619 MarkerStack::Capture())do { ; do { if (profiler_is_collecting_markers()) { ::profiler_add_marker_impl
("CreateAboutBlankDocumentViewer", ::geckoprofiler::category::
DOM, MarkerStack::Capture()); } } while (false); } while (false
)
;
6620
6621 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"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 6621); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aActor->DocumentPrincipal() == aPrincipal"
")"); do { MOZ_CrashSequence(__null, 6621); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
6622
6623 /* mCreatingDocument should never be true at this point. However, it's
6624 a theoretical possibility. We want to know about it and make it stop,
6625 and this sounds like a job for an assertion. */
6626 NS_ASSERTION(!mCreatingDocument,do { if (!(!mCreatingDocument)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "infinite(?) loop creating document averted", "!mCreatingDocument"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 6627); MOZ_PretendNoReturn
(); } } while (0)
6627 "infinite(?) loop creating document averted")do { if (!(!mCreatingDocument)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "infinite(?) loop creating document averted", "!mCreatingDocument"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 6627); MOZ_PretendNoReturn
(); } } while (0)
;
6628 if (mCreatingDocument) {
6629 return NS_ERROR_FAILURE;
6630 }
6631
6632 if (!mBrowsingContext->AncestorsAreCurrent() ||
6633 (mozilla::SessionHistoryInParent() && mBrowsingContext->IsInBFCache())) {
6634 mBrowsingContext->RemoveRootFromBFCacheSync();
6635 return NS_ERROR_NOT_AVAILABLE;
6636 }
6637
6638 // mDocumentViewer->PermitUnload may release |this| docshell.
6639 nsCOMPtr<nsIDocShell> kungFuDeathGrip(this);
6640
6641 // Ensure that UsesOriginAgentCluster has been initialized for this
6642 // BrowsingContextGroup/principal pair before creating the document.
6643 if (aPrincipal) {
6644 mBrowsingContext->Group()->EnsureUsesOriginAgentClusterInitialized(
6645 aPrincipal);
6646 }
6647
6648 AutoRestore<bool> creatingDocument(mCreatingDocument);
6649 mCreatingDocument = true;
6650
6651 if (aPrincipal && !aPrincipal->IsSystemPrincipal() &&
6652 mItemType != typeChrome) {
6653 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()"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 6654); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aPrincipal->OriginAttributesRef() == mBrowsingContext->OriginAttributesRef()"
")"); do { MOZ_CrashSequence(__null, 6654); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6654 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()"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 6654); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aPrincipal->OriginAttributesRef() == mBrowsingContext->OriginAttributesRef()"
")"); do { MOZ_CrashSequence(__null, 6654); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6655 }
6656
6657 // Make sure timing is created. But first record whether we had it
6658 // already, so we don't clobber the timing for an in-progress load.
6659 bool hadTiming = mTiming;
6660 bool toBeReset = MaybeInitTiming();
6661 if (mDocumentViewer) {
6662 if (aCheckPermitUnload) {
6663 // We've got a content viewer already. Make sure the user
6664 // permits us to discard the current document and replace it
6665 // with about:blank. And also ensure we fire the unload events
6666 // in the current document.
6667
6668 // Unload gets fired first for
6669 // document loaded from the session history.
6670 mTiming->NotifyBeforeUnload();
6671
6672 bool okToUnload;
6673 rv = mDocumentViewer->PermitUnload(&okToUnload);
6674
6675 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && !okToUnload) {
6676 // The user chose not to unload the page, interrupt the load.
6677 MaybeResetInitTiming(toBeReset);
6678 return NS_ERROR_FAILURE;
6679 }
6680 if (mTiming) {
6681 mTiming->NotifyUnloadAccepted(mCurrentURI);
6682 }
6683 }
6684
6685 mSavingOldViewer =
6686 aTryToSaveOldPresentation &&
6687 CanSavePresentation(LOAD_NORMAL, nullptr, nullptr,
6688 /* aReportBFCacheComboTelemetry */ true);
6689
6690 // Make sure to blow away our mLoadingURI just in case. No loads
6691 // from inside this pagehide.
6692 mLoadingURI = nullptr;
6693
6694 // Stop any in-progress loading, so that we don't accidentally trigger any
6695 // PageShow notifications from Embed() interrupting our loading below.
6696 Stop();
6697
6698 // Notify the current document that it is about to be unloaded!!
6699 //
6700 // It is important to fire the unload() notification *before* any state
6701 // is changed within the DocShell - otherwise, javascript will get the
6702 // wrong information :-(
6703 //
6704 (void)FirePageHideNotification(!mSavingOldViewer);
6705 // pagehide notification might destroy this docshell.
6706 if (mIsBeingDestroyed) {
6707 return NS_ERROR_DOCSHELL_DYING;
6708 }
6709 }
6710
6711 // Now make sure we don't think we're in the middle of firing unload after
6712 // this point. This will make us fire unload when the about:blank document
6713 // unloads... but that's ok, more or less. Would be nice if it fired load
6714 // too, of course.
6715 mFiredUnloadEvent = false;
6716
6717 nsCOMPtr<nsIDocumentLoaderFactory> docFactory =
6718 nsContentUtils::FindInternalDocumentViewer("text/html"_ns);
6719
6720 if (docFactory) {
6721 nsCOMPtr<nsIPrincipal> principal, partitionedPrincipal;
6722 const uint32_t sandboxFlags =
6723 mBrowsingContext->GetHasLoadedNonInitialDocument()
6724 ? mBrowsingContext->GetSandboxFlags()
6725 : mBrowsingContext->GetInitialSandboxFlags();
6726 // If we're sandboxed, then create a new null principal. We skip
6727 // this if we're being created from WindowGlobalChild, since in
6728 // that case we already have a null principal if required.
6729 // We can't compare againt the BrowsingContext sandbox flag, since
6730 // the value was taken when the load initiated and may have since
6731 // changed.
6732 if ((sandboxFlags & SANDBOXED_ORIGIN) && !aActor) {
6733 if (aPrincipal) {
6734 principal = NullPrincipal::CreateWithInheritedAttributes(aPrincipal);
6735 } else {
6736 principal = NullPrincipal::Create(GetOriginAttributes());
6737 }
6738 partitionedPrincipal = principal;
6739 } else {
6740 principal = aPrincipal;
6741 partitionedPrincipal = aPartitionedPrincipal;
6742 }
6743
6744 // We cannot get the foreign partitioned prinicpal for the initial
6745 // about:blank page. So, we change to check if we need to use the
6746 // partitioned principal for the service worker here.
6747 MaybeCreateInitialClientSource(
6748 StoragePrincipalHelper::ShouldUsePartitionPrincipalForServiceWorker(
6749 this)
6750 ? partitionedPrincipal
6751 : principal);
6752
6753 // generate (about:blank) document to load
6754 blankDoc = nsContentDLF::CreateBlankDocument(mLoadGroup, principal,
6755 partitionedPrincipal, this);
6756 if (blankDoc) {
6757 // Hack: manually set the CSP for the new document
6758 // Please create an actual copy of the CSP (do not share the same
6759 // reference) otherwise appending a new policy within the new
6760 // document will be incorrectly propagated to the opening doc.
6761 if (aCSP) {
6762 RefPtr<nsCSPContext> cspToInherit = new nsCSPContext();
6763 cspToInherit->InitFromOther(static_cast<nsCSPContext*>(aCSP));
6764 blankDoc->SetCsp(cspToInherit);
6765 }
6766
6767 blankDoc->SetIsInitialDocument(aIsInitialDocument);
6768
6769 blankDoc->SetEmbedderPolicy(aCOEP);
6770
6771 // Hack: set the base URI manually, since this document never
6772 // got Reset() with a channel.
6773 blankDoc->SetBaseURI(aBaseURI);
6774
6775 // Copy our sandbox flags to the document. These are immutable
6776 // after being set here.
6777 blankDoc->SetSandboxFlags(sandboxFlags);
6778
6779 // We inherit the classification flags from the parent document if the
6780 // principal matches.
6781 nsCOMPtr<nsIDocShellTreeItem> parentItem;
6782 GetInProcessSameTypeParent(getter_AddRefs(parentItem));
6783 if (parentItem) {
6784 RefPtr<Document> parentDocument = parentItem->GetDocument();
6785 if (parentDocument && principal &&
6786 principal->Equals(parentDocument->NodePrincipal())) {
6787 blankDoc->SetClassificationFlags(
6788 parentDocument->GetClassificationFlags());
6789 }
6790 }
6791
6792 // create a content viewer for us and the new document
6793 docFactory->CreateInstanceForDocument(
6794 NS_ISUPPORTS_CAST(nsIDocShell*, this)static_cast<nsISupports*>(static_cast<nsIDocShell*>
(this))
, blankDoc, "view",
6795 getter_AddRefs(viewer));
6796
6797 // hook 'em up
6798 if (viewer) {
6799 viewer->SetContainer(this);
6800 if (mLoadingEntry && mBrowsingContext->IsTop()) {
6801 mLoadingEntry->mInfo.SetTransient();
6802 }
6803 rv = Embed(viewer, aActor, true, nullptr, mCurrentURI);
6804 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, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 6804); return rv; } } while (false)
;
6805
6806 SetCurrentURI(blankDoc->GetDocumentURI(), nullptr,
6807 /* aFireLocationChange */ true,
6808 /* aIsInitialAboutBlank */ true,
6809 /* aLocationFlags */ 0);
6810 rv = mIsBeingDestroyed ? NS_ERROR_NOT_AVAILABLE : NS_OK;
6811 }
6812
6813 if (Element* embedderElement = blankDoc->GetEmbedderElement()) {
6814 blankDoc->InitFeaturePolicy(AsVariant(embedderElement));
6815 } else {
6816 blankDoc->InitFeaturePolicy(AsVariant(Nothing{}));
6817 }
6818 }
6819 }
6820
6821 // The transient about:blank viewer doesn't have a session history entry.
6822 SetHistoryEntryAndUpdateBC(Nothing(), Some(nullptr));
6823
6824 // Clear out our mTiming like we would in EndPageLoad, if we didn't
6825 // have one before entering this function.
6826 if (!hadTiming) {
6827 mTiming = nullptr;
6828 mBlankTiming = true;
6829 }
6830
6831 return rv;
6832}
6833
6834NS_IMETHODIMPnsresult
6835nsDocShell::CreateAboutBlankDocumentViewer(nsIPrincipal* aPrincipal,
6836 nsIPrincipal* aPartitionedPrincipal,
6837 nsIContentSecurityPolicy* aCSP) {
6838 return CreateAboutBlankDocumentViewer(aPrincipal, aPartitionedPrincipal, aCSP,
6839 nullptr,
6840 /* aIsInitialDocument */ false);
6841}
6842
6843nsresult nsDocShell::CreateDocumentViewerForActor(
6844 WindowGlobalChild* aWindowActor) {
6845 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", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 6845); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aWindowActor"
")"); do { MOZ_CrashSequence(__null, 6845); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6846
6847 // FIXME: WindowGlobalChild should provide the PartitionedPrincipal.
6848 // FIXME: We may want to support non-initial documents here.
6849 nsresult rv = CreateAboutBlankDocumentViewer(
6850 aWindowActor->DocumentPrincipal(), aWindowActor->DocumentPrincipal(),
6851 /* aCsp */ nullptr,
6852 /* aBaseURI */ nullptr,
6853 /* aIsInitialDocument */ true,
6854 /* aCOEP */ Nothing(),
6855 /* aTryToSaveOldPresentation */ true,
6856 /* aCheckPermitUnload */ true, aWindowActor);
6857#ifdef DEBUG1
6858 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
6859 RefPtr<Document> doc(GetDocument());
6860 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"
")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 6862
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "doc" ") (" "Should have a document if CreateAboutBlankDocumentViewer succeeded"
")"); do { MOZ_CrashSequence(__null, 6862); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6861 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"
")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 6862
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "doc" ") (" "Should have a document if CreateAboutBlankDocumentViewer succeeded"
")"); do { MOZ_CrashSequence(__null, 6862); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6862 "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"
")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 6862
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "doc" ") (" "Should have a document if CreateAboutBlankDocumentViewer succeeded"
")"); do { MOZ_CrashSequence(__null, 6862); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6863 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"
")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 6864
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "doc->GetOwnerGlobal() == aWindowActor->GetWindowGlobal()"
") (" "New document should be in the same global as our actor"
")"); do { MOZ_CrashSequence(__null, 6864); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6864 "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"
")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 6864
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "doc->GetOwnerGlobal() == aWindowActor->GetWindowGlobal()"
") (" "New document should be in the same global as our actor"
")"); do { MOZ_CrashSequence(__null, 6864); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6865 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" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 6866); AnnotateMozCrashReason("MOZ_ASSERT" "(" "doc->IsInitialDocument()"
") (" "New document should be an initial document" ")"); do {
MOZ_CrashSequence(__null, 6866); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
6866 "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" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 6866); AnnotateMozCrashReason("MOZ_ASSERT" "(" "doc->IsInitialDocument()"
") (" "New document should be an initial document" ")"); do {
MOZ_CrashSequence(__null, 6866); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
6867 }
6868#endif
6869
6870 return rv;
6871}
6872
6873bool nsDocShell::CanSavePresentation(uint32_t aLoadType,
6874 nsIRequest* aNewRequest,
6875 Document* aNewDocument,
6876 bool aReportBFCacheComboTelemetry) {
6877 if (!mOSHE) {
6878 return false; // no entry to save into
6879 }
6880
6881 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"
")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 6882
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mozilla::SessionHistoryInParent()"
") (" "mOSHE cannot be non-null with SHIP" ")"); do { MOZ_CrashSequence
(__null, 6882); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
6882 "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"
")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 6882
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mozilla::SessionHistoryInParent()"
") (" "mOSHE cannot be non-null with SHIP" ")"); do { MOZ_CrashSequence
(__null, 6882); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
6883 nsCOMPtr<nsIDocumentViewer> viewer = mOSHE->GetDocumentViewer();
6884 if (viewer) {
6885 NS_WARNING("mOSHE already has a content viewer!")NS_DebugBreak(NS_DEBUG_WARNING, "mOSHE already has a content viewer!"
, nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 6885)
;
6886 return false;
6887 }
6888
6889 // Only save presentation for "normal" loads and link loads. Anything else
6890 // probably wants to refetch the page, so caching the old presentation
6891 // would be incorrect.
6892 if (aLoadType != LOAD_NORMAL && aLoadType != LOAD_HISTORY &&
6893 aLoadType != LOAD_LINK && aLoadType != LOAD_STOP_CONTENT &&
6894 aLoadType != LOAD_STOP_CONTENT_AND_REPLACE &&
6895 aLoadType != LOAD_ERROR_PAGE) {
6896 return false;
6897 }
6898
6899 // If the session history entry has the saveLayoutState flag set to false,
6900 // then we should not cache the presentation.
6901 if (!mOSHE->GetSaveLayoutStateFlag()) {
6902 return false;
6903 }
6904
6905 // If the document is not done loading, don't cache it.
6906 if (!mScriptGlobal || mScriptGlobal->IsLoading()) {
6907 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)
6908 ("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)
;
6909 return false;
6910 }
6911
6912 if (mScriptGlobal->WouldReuseInnerWindow(aNewDocument)) {
6913 return false;
6914 }
6915
6916 // Avoid doing the work of saving the presentation state in the case where
6917 // the content viewer cache is disabled.
6918 if (nsSHistory::GetMaxTotalViewers() == 0) {
6919 return false;
6920 }
6921
6922 // Don't cache the content viewer if we're in a subframe.
6923 if (mBrowsingContext->GetParent()) {
6924 return false; // this is a subframe load
6925 }
6926
6927 // If the document does not want its presentation cached, then don't.
6928 RefPtr<Document> doc = mScriptGlobal->GetExtantDoc();
6929
6930 uint32_t bfCacheCombo = 0;
6931 bool canSavePresentation =
6932 doc->CanSavePresentation(aNewRequest, bfCacheCombo, true);
6933 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", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 6933); AnnotateMozCrashReason("MOZ_ASSERT" "(" "bfCacheCombo == 0"
")"); do { MOZ_CrashSequence(__null, 6933); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
6934 if (canSavePresentation && doc->IsTopLevelContentDocument()) {
6935 auto* browsingContextGroup = mBrowsingContext->Group();
6936 nsTArray<RefPtr<BrowsingContext>>& topLevelContext =
6937 browsingContextGroup->Toplevels();
6938
6939 for (const auto& browsingContext : topLevelContext) {
6940 if (browsingContext != mBrowsingContext) {
6941 if (StaticPrefs::docshell_shistory_bfcache_require_no_opener()) {
6942 canSavePresentation = false;
6943 }
6944 bfCacheCombo |= BFCacheStatus::NOT_ONLY_TOPLEVEL_IN_BCG;
6945 break;
6946 }
6947 }
6948 }
6949
6950 if (aReportBFCacheComboTelemetry) {
6951 ReportBFCacheComboTelemetry(bfCacheCombo);
6952 }
6953 return doc && canSavePresentation;
6954}
6955
6956/* static */
6957void nsDocShell::ReportBFCacheComboTelemetry(uint32_t aCombo) {
6958 // There are 11 possible reasons to make a request fails to use BFCache
6959 // (see BFCacheStatus in dom/base/Document.h), and we'd like to record
6960 // the common combinations for reasons which make requests fail to use
6961 // BFCache. These combinations are generated based on some local browsings,
6962 // we need to adjust them when necessary.
6963 enum BFCacheStatusCombo : uint32_t {
6964 BFCACHE_SUCCESS,
6965 NOT_ONLY_TOPLEVEL = mozilla::dom::BFCacheStatus::NOT_ONLY_TOPLEVEL_IN_BCG,
6966 // If both unload and beforeunload listeners are presented, it'll be
6967 // recorded as unload
6968 UNLOAD = mozilla::dom::BFCacheStatus::UNLOAD_LISTENER,
6969 UNLOAD_REQUEST = mozilla::dom::BFCacheStatus::UNLOAD_LISTENER |
6970 mozilla::dom::BFCacheStatus::REQUEST,
6971 REQUEST = mozilla::dom::BFCacheStatus::REQUEST,
6972 UNLOAD_REQUEST_PEER = mozilla::dom::BFCacheStatus::UNLOAD_LISTENER |
6973 mozilla::dom::BFCacheStatus::REQUEST |
6974 mozilla::dom::BFCacheStatus::ACTIVE_PEER_CONNECTION,
6975 UNLOAD_REQUEST_PEER_MSE =
6976 mozilla::dom::BFCacheStatus::UNLOAD_LISTENER |
6977 mozilla::dom::BFCacheStatus::REQUEST |
6978 mozilla::dom::BFCacheStatus::ACTIVE_PEER_CONNECTION |
6979 mozilla::dom::BFCacheStatus::CONTAINS_MSE_CONTENT,
6980 UNLOAD_REQUEST_MSE = mozilla::dom::BFCacheStatus::UNLOAD_LISTENER |
6981 mozilla::dom::BFCacheStatus::REQUEST |
6982 mozilla::dom::BFCacheStatus::CONTAINS_MSE_CONTENT,
6983 SUSPENDED_UNLOAD_REQUEST_PEER =
6984 mozilla::dom::BFCacheStatus::SUSPENDED |
6985 mozilla::dom::BFCacheStatus::UNLOAD_LISTENER |
6986 mozilla::dom::BFCacheStatus::REQUEST |
6987 mozilla::dom::BFCacheStatus::ACTIVE_PEER_CONNECTION,
6988 REMOTE_SUBFRAMES = mozilla::dom::BFCacheStatus::CONTAINS_REMOTE_SUBFRAMES,
6989 BEFOREUNLOAD = mozilla::dom::BFCacheStatus::BEFOREUNLOAD_LISTENER,
6990 };
6991
6992 // Beforeunload is recorded as a blocker only if it is the only one to block
6993 // bfcache.
6994 if (aCombo != mozilla::dom::BFCacheStatus::BEFOREUNLOAD_LISTENER) {
6995 aCombo &= ~mozilla::dom::BFCacheStatus::BEFOREUNLOAD_LISTENER;
6996 }
6997 switch (aCombo) {
6998 case BFCACHE_SUCCESS:
6999 glean::bfcache::combo.EnumGet(glean::bfcache::ComboLabel::eBfcacheSuccess)
7000 .Add();
7001 break;
7002 case NOT_ONLY_TOPLEVEL:
7003 if (StaticPrefs::docshell_shistory_bfcache_require_no_opener()) {
7004 glean::bfcache::combo.EnumGet(glean::bfcache::ComboLabel::eOther).Add();
7005 break;
7006 }
7007 glean::bfcache::combo.EnumGet(glean::bfcache::ComboLabel::eBfcacheSuccess)
7008 .Add();
7009 glean::bfcache::combo
7010 .EnumGet(glean::bfcache::ComboLabel::eSuccessNotToplevel)
7011 .Add();
7012 break;
7013 case UNLOAD:
7014 glean::bfcache::combo.EnumGet(glean::bfcache::ComboLabel::eUnload).Add();
7015 break;
7016 case BEFOREUNLOAD:
7017 glean::bfcache::combo.EnumGet(glean::bfcache::ComboLabel::eBeforeunload)
7018 .Add();
7019 break;
7020 case UNLOAD_REQUEST:
7021 glean::bfcache::combo.EnumGet(glean::bfcache::ComboLabel::eUnloadReq)
7022 .Add();
7023 break;
7024 case REQUEST:
7025 glean::bfcache::combo.EnumGet(glean::bfcache::ComboLabel::eReq).Add();
7026 break;
7027 case UNLOAD_REQUEST_PEER:
7028 glean::bfcache::combo.EnumGet(glean::bfcache::ComboLabel::eUnloadReqPeer)
7029 .Add();
7030 break;
7031 case UNLOAD_REQUEST_PEER_MSE:
7032 glean::bfcache::combo
7033 .EnumGet(glean::bfcache::ComboLabel::eUnloadReqPeerMse)
7034 .Add();
7035 break;
7036 case UNLOAD_REQUEST_MSE:
7037 glean::bfcache::combo.EnumGet(glean::bfcache::ComboLabel::eUnloadReqMse)
7038 .Add();
7039 break;
7040 case SUSPENDED_UNLOAD_REQUEST_PEER:
7041 glean::bfcache::combo
7042 .EnumGet(glean::bfcache::ComboLabel::eSpdUnloadReqPeer)
7043 .Add();
7044 break;
7045 case REMOTE_SUBFRAMES:
7046 glean::bfcache::combo
7047 .EnumGet(glean::bfcache::ComboLabel::eRemoteSubframes)
7048 .Add();
7049 break;
7050 default:
7051 glean::bfcache::combo.EnumGet(glean::bfcache::ComboLabel::eOther).Add();
7052 break;
7053 }
7054};
7055
7056void nsDocShell::ReattachEditorToWindow(nsISHEntry* aSHEntry) {
7057 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()", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 7057); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mozilla::SessionHistoryInParent()"
")"); do { MOZ_CrashSequence(__null, 7057); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7058 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"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 7058); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!mIsBeingDestroyed" ")"); do { MOZ_CrashSequence
(__null, 7058); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
7059
7060 NS_ASSERTION(!mEditorData,do { if (!(!mEditorData)) { NS_DebugBreak(NS_DEBUG_ASSERTION,
"Why reattach an editor when we already have one?", "!mEditorData"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 7061); MOZ_PretendNoReturn
(); } } while (0)
7061 "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"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 7061); MOZ_PretendNoReturn
(); } } while (0)
;
7062 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()", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 7063); MOZ_PretendNoReturn(); } } while (0)
7063 "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()", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 7063); MOZ_PretendNoReturn(); } } while (0)
;
7064
7065 if (mEditorData || !aSHEntry) {
7066 return;
7067 }
7068
7069 mEditorData = WrapUnique(aSHEntry->ForgetEditorData());
7070 if (mEditorData) {
7071#ifdef DEBUG1
7072 nsresult rv =
7073#endif
7074 mEditorData->ReattachToWindow(this);
7075 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)", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 7075); MOZ_PretendNoReturn(); } } while (0)
;
7076 }
7077}
7078
7079void nsDocShell::DetachEditorFromWindow() {
7080 if (!mEditorData || mEditorData->WaitingForLoad()) {
7081 // If there's nothing to detach, or if the editor data is actually set
7082 // up for the _new_ page that's coming in, don't detach.
7083 return;
7084 }
7085
7086 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()", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 7087); MOZ_PretendNoReturn(); } } while (0)
7087 "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()", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 7087); MOZ_PretendNoReturn(); } } while (0)
;
7088
7089 nsresult res = mEditorData->DetachFromWindow();
7090 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)", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 7090); MOZ_PretendNoReturn(); } } while (0)
;
7091
7092 if (NS_SUCCEEDED(res)((bool)(__builtin_expect(!!(!NS_FAILED_impl(res)), 1)))) {
7093 // Make mOSHE hold the owning ref to the editor data.
7094 if (mOSHE) {
7095 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" ")"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 7097); 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 { MOZ_CrashSequence(__null, 7097); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
7096 "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" ")"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 7097); 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 { MOZ_CrashSequence(__null, 7097); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
7097 "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" ")"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 7097); 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 { MOZ_CrashSequence(__null, 7097); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7098 mOSHE->SetEditorData(mEditorData.release());
7099 } else {
7100 mEditorData = nullptr;
7101 }
7102 }
7103
7104#ifdef DEBUG1
7105 {
7106 bool isEditable;
7107 GetEditable(&isEditable);
7108 NS_ASSERTION(!isEditable,do { if (!(!isEditable)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "Window is still editable after detaching editor."
, "!isEditable", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 7109); MOZ_PretendNoReturn(); } } while (0)
7109 "Window is still editable after detaching editor.")do { if (!(!isEditable)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "Window is still editable after detaching editor."
, "!isEditable", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 7109); MOZ_PretendNoReturn(); } } while (0)
;
7110 }
7111#endif // DEBUG
7112}
7113
7114nsresult nsDocShell::CaptureState() {
7115 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()", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 7115); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mozilla::SessionHistoryInParent()"
")"); do { MOZ_CrashSequence(__null, 7115); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7116
7117 if (!mOSHE || mOSHE == mLSHE) {
7118 // No entry to save into, or we're replacing the existing entry.
7119 return NS_ERROR_FAILURE;
7120 }
7121
7122 if (!mScriptGlobal) {
7123 return NS_ERROR_FAILURE;
7124 }
7125
7126 nsCOMPtr<nsISupports> windowState = mScriptGlobal->SaveWindowState();
7127 NS_ENSURE_TRUE(windowState, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(windowState)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "windowState" ") failed"
, nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 7127); return NS_ERROR_FAILURE; } } while (false)
;
7128
7129 if (MOZ_UNLIKELY(MOZ_LOG_TEST(gPageCacheLog, LogLevel::Debug))(__builtin_expect(!!((__builtin_expect(!!(mozilla::detail::log_test
(gPageCacheLog, LogLevel::Debug)), 0))), 0))
) {
7130 nsAutoCString spec;
7131 nsCOMPtr<nsIURI> uri = mOSHE->GetURI();
7132 if (uri) {
7133 uri->GetSpec(spec);
7134 }
7135 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)
7136 ("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)
;
7137 }
7138
7139 mOSHE->SetWindowState(windowState);
7140
7141 // Suspend refresh URIs and save off the timer queue
7142 mOSHE->SetRefreshURIList(mSavedRefreshURIList);
7143
7144 // Capture the current content viewer bounds.
7145 if (mDocumentViewer) {
7146 LayoutDeviceIntRect bounds;
7147 mDocumentViewer->GetBounds(bounds);
7148 mOSHE->SetViewerBounds(bounds.ToUnknownRect());
7149 }
7150
7151 // Capture the docshell hierarchy.
7152 mOSHE->ClearChildShells();
7153
7154 uint32_t childCount = mChildList.Length();
7155 for (uint32_t i = 0; i < childCount; ++i) {
7156 nsCOMPtr<nsIDocShellTreeItem> childShell = do_QueryInterface(ChildAt(i));
7157 NS_ASSERTION(childShell, "null child shell")do { if (!(childShell)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "null child shell"
, "childShell", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 7157); MOZ_PretendNoReturn(); } } while (0)
;
7158
7159 mOSHE->AddChildShell(childShell);
7160 }
7161
7162 return NS_OK;
7163}
7164
7165NS_IMETHODIMPnsresult
7166nsDocShell::RestorePresentationEvent::Run() {
7167 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()", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 7167); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mozilla::SessionHistoryInParent()"
")"); do { MOZ_CrashSequence(__null, 7167); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7168
7169 if (mDocShell && NS_FAILED(mDocShell->RestoreFromHistory())((bool)(__builtin_expect(!!(NS_FAILED_impl(mDocShell->RestoreFromHistory
())), 0)))
) {
7170 NS_WARNING("RestoreFromHistory failed")NS_DebugBreak(NS_DEBUG_WARNING, "RestoreFromHistory failed", nullptr
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 7170)
;
7171 }
7172 return NS_OK;
7173}
7174
7175NS_IMETHODIMPnsresult
7176nsDocShell::BeginRestore(nsIDocumentViewer* aDocumentViewer, bool aTop) {
7177 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()", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 7177); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mozilla::SessionHistoryInParent()"
")"); do { MOZ_CrashSequence(__null, 7177); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7178
7179 nsresult rv;
7180 if (!aDocumentViewer) {
7181 rv = EnsureDocumentViewer();
7182 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, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 7182); return rv; } } while (false)
;
7183
7184 aDocumentViewer = mDocumentViewer;
7185 }
7186
7187 // Dispatch events for restoring the presentation. We try to simulate
7188 // the progress notifications loading the document would cause, so we add
7189 // the document's channel to the loadgroup to initiate stateChange
7190 // notifications.
7191
7192 RefPtr<Document> doc = aDocumentViewer->GetDocument();
7193 if (doc) {
7194 nsIChannel* channel = doc->GetChannel();
7195 if (channel) {
7196 mEODForCurrentDocument = false;
7197 mIsRestoringDocument = true;
7198 mLoadGroup->AddRequest(channel, nullptr);
7199 mIsRestoringDocument = false;
7200 }
7201 }
7202
7203 if (!aTop) {
7204 // This point corresponds to us having gotten OnStartRequest or
7205 // STATE_START, so do the same thing that CreateDocumentViewer does at
7206 // this point to ensure that unload/pagehide events for this document
7207 // will fire when it's unloaded again.
7208 mFiredUnloadEvent = false;
7209
7210 // For non-top frames, there is no notion of making sure that the
7211 // previous document is in the domwindow when STATE_START notifications
7212 // happen. We can just call BeginRestore for all of the child shells
7213 // now.
7214 rv = BeginRestoreChildren();
7215 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, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 7215); return rv; } } while (false)
;
7216 }
7217
7218 return NS_OK;
7219}
7220
7221nsresult nsDocShell::BeginRestoreChildren() {
7222 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()", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 7222); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mozilla::SessionHistoryInParent()"
")"); do { MOZ_CrashSequence(__null, 7222); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7223
7224 for (auto* childDocLoader : mChildList.ForwardRange()) {
7225 nsCOMPtr<nsIDocShell> child = do_QueryObject(childDocLoader);
7226 if (child) {
7227 nsresult rv = child->BeginRestore(nullptr, false);
7228 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, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 7228); return rv; } } while (false)
;
7229 }
7230 }
7231 return NS_OK;
7232}
7233
7234NS_IMETHODIMPnsresult
7235nsDocShell::FinishRestore() {
7236 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()", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 7236); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mozilla::SessionHistoryInParent()"
")"); do { MOZ_CrashSequence(__null, 7236); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7237
7238 // First we call finishRestore() on our children. In the simulated load,
7239 // all of the child frames finish loading before the main document.
7240
7241 for (auto* childDocLoader : mChildList.ForwardRange()) {
7242 nsCOMPtr<nsIDocShell> child = do_QueryObject(childDocLoader);
7243 if (child) {
7244 child->FinishRestore();
7245 }
7246 }
7247
7248 if (mOSHE && mOSHE->HasDetachedEditor()) {
7249 ReattachEditorToWindow(mOSHE);
7250 }
7251
7252 RefPtr<Document> doc = GetDocument();
7253 if (doc) {
7254 // Finally, we remove the request from the loadgroup. This will
7255 // cause onStateChange(STATE_STOP) to fire, which will fire the
7256 // pageshow event to the chrome.
7257
7258 nsIChannel* channel = doc->GetChannel();
7259 if (channel) {
7260 mIsRestoringDocument = true;
7261 mLoadGroup->RemoveRequest(channel, nullptr, NS_OK);
7262 mIsRestoringDocument = false;
7263 }
7264 }
7265
7266 return NS_OK;
7267}
7268
7269NS_IMETHODIMPnsresult
7270nsDocShell::GetRestoringDocument(bool* aRestoring) {
7271 *aRestoring = mIsRestoringDocument;
7272 return NS_OK;
7273}
7274
7275nsresult nsDocShell::RestorePresentation(nsISHEntry* aSHEntry,
7276 bool* aRestoring) {
7277 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()", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 7277); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mozilla::SessionHistoryInParent()"
")"); do { MOZ_CrashSequence(__null, 7277); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7278 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"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 7278); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!mIsBeingDestroyed" ")"); do { MOZ_CrashSequence
(__null, 7278); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
7279
7280 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", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 7281); MOZ_PretendNoReturn(); } } while (0)
7281 "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", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 7281); MOZ_PretendNoReturn(); } } while (0)
;
7282
7283 nsCOMPtr<nsIDocumentViewer> viewer = aSHEntry->GetDocumentViewer();
7284
7285 nsAutoCString spec;
7286 if (MOZ_UNLIKELY(MOZ_LOG_TEST(gPageCacheLog, LogLevel::Debug))(__builtin_expect(!!((__builtin_expect(!!(mozilla::detail::log_test
(gPageCacheLog, LogLevel::Debug)), 0))), 0))
) {
7287 nsCOMPtr<nsIURI> uri = aSHEntry->GetURI();
7288 if (uri) {
7289 uri->GetSpec(spec);
7290 }
7291 }
7292
7293 *aRestoring = false;
7294
7295 if (!viewer) {
7296 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)
7297 ("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)
;
7298 return NS_OK;
7299 }
7300
7301 // We need to make sure the content viewer's container is this docshell.
7302 // In subframe navigation, it's possible for the docshell that the
7303 // content viewer was originally loaded into to be replaced with a
7304 // different one. We don't currently support restoring the presentation
7305 // in that case.
7306
7307 nsCOMPtr<nsIDocShell> container;
7308 viewer->GetContainer(getter_AddRefs(container));
7309 if (!::SameCOMIdentity(container, GetAsSupports(this))) {
7310 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)
7311 ("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)
;
7312 aSHEntry->SetDocumentViewer(nullptr);
7313 return NS_ERROR_FAILURE;
7314 }
7315
7316 NS_ASSERTION(mDocumentViewer != viewer, "Restoring existing presentation")do { if (!(mDocumentViewer != viewer)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "Restoring existing presentation", "mDocumentViewer != viewer"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 7316); MOZ_PretendNoReturn
(); } } while (0)
;
7317
7318 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)
7319 ("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)
;
7320
7321 SetHistoryEntryAndUpdateBC(Some(aSHEntry), Nothing());
7322
7323 // Post an event that will remove the request after we've returned
7324 // to the event loop. This mimics the way it is called by nsIChannel
7325 // implementations.
7326
7327 // Revoke any pending restore (just in case).
7328 NS_ASSERTION(!mRestorePresentationEvent.IsPending(),do { if (!(!mRestorePresentationEvent.IsPending())) { NS_DebugBreak
(NS_DEBUG_ASSERTION, "should only have one RestorePresentationEvent"
, "!mRestorePresentationEvent.IsPending()", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 7329); MOZ_PretendNoReturn(); } } while (0)
7329 "should only have one RestorePresentationEvent")do { if (!(!mRestorePresentationEvent.IsPending())) { NS_DebugBreak
(NS_DEBUG_ASSERTION, "should only have one RestorePresentationEvent"
, "!mRestorePresentationEvent.IsPending()", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 7329); MOZ_PretendNoReturn(); } } while (0)
;
7330 mRestorePresentationEvent.Revoke();
7331
7332 RefPtr<RestorePresentationEvent> evt = new RestorePresentationEvent(this);
7333 nsresult rv = Dispatch(do_AddRef(evt));
7334 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
7335 mRestorePresentationEvent = evt.get();
7336 // The rest of the restore processing will happen on our event
7337 // callback.
7338 *aRestoring = true;
7339 }
7340
7341 return rv;
7342}
7343
7344namespace {
7345class MOZ_STACK_CLASS PresentationEventForgetter {
7346 public:
7347 explicit PresentationEventForgetter(
7348 nsRevocableEventPtr<nsDocShell::RestorePresentationEvent>&
7349 aRestorePresentationEvent)
7350 : mRestorePresentationEvent(aRestorePresentationEvent),
7351 mEvent(aRestorePresentationEvent.get()) {}
7352
7353 ~PresentationEventForgetter() { Forget(); }
7354
7355 void Forget() {
7356 if (mRestorePresentationEvent.get() == mEvent) {
7357 mRestorePresentationEvent.Forget();
7358 mEvent = nullptr;
7359 }
7360 }
7361
7362 private:
7363 nsRevocableEventPtr<nsDocShell::RestorePresentationEvent>&
7364 mRestorePresentationEvent;
7365 RefPtr<nsDocShell::RestorePresentationEvent> mEvent;
7366};
7367
7368} // namespace
7369
7370bool nsDocShell::SandboxFlagsImplyCookies(const uint32_t& aSandboxFlags) {
7371 return (aSandboxFlags & (SANDBOXED_ORIGIN | SANDBOXED_SCRIPTS)) == 0;
7372}
7373
7374nsresult nsDocShell::RestoreFromHistory() {
7375 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()", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 7375); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mozilla::SessionHistoryInParent()"
")"); do { MOZ_CrashSequence(__null, 7375); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7376 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()"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 7376); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "mRestorePresentationEvent.IsPending()" ")"
); do { MOZ_CrashSequence(__null, 7376); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7377 PresentationEventForgetter forgetter(mRestorePresentationEvent);
7378
7379 // This section of code follows the same ordering as CreateDocumentViewer.
7380 if (!mLSHE) {
7381 return NS_ERROR_FAILURE;
7382 }
7383
7384 nsCOMPtr<nsIDocumentViewer> viewer = mLSHE->GetDocumentViewer();
7385 if (!viewer) {
7386 return NS_ERROR_FAILURE;
7387 }
7388
7389 if (mSavingOldViewer) {
7390 // We determined that it was safe to cache the document presentation
7391 // at the time we initiated the new load. We need to check whether
7392 // it's still safe to do so, since there may have been DOM mutations
7393 // or new requests initiated.
7394 RefPtr<Document> doc = viewer->GetDocument();
7395 nsIRequest* request = nullptr;
7396 if (doc) {
7397 request = doc->GetChannel();
7398 }
7399 mSavingOldViewer = CanSavePresentation(
7400 mLoadType, request, doc, /* aReportBFCacheComboTelemetry */ false);
7401 }
7402
7403 // Protect against mLSHE going away via a load triggered from
7404 // pagehide or unload.
7405 nsCOMPtr<nsISHEntry> origLSHE = mLSHE;
7406
7407 // Make sure to blow away our mLoadingURI just in case. No loads
7408 // from inside this pagehide.
7409 mLoadingURI = nullptr;
7410
7411 // Notify the old content viewer that it's being hidden.
7412 FirePageHideNotification(!mSavingOldViewer);
7413 // pagehide notification might destroy this docshell.
7414 if (mIsBeingDestroyed) {
7415 return NS_ERROR_DOCSHELL_DYING;
7416 }
7417
7418 // If mLSHE was changed as a result of the pagehide event, then
7419 // something else was loaded. Don't finish restoring.
7420 if (mLSHE != origLSHE) {
7421 return NS_OK;
7422 }
7423
7424 // Add the request to our load group. We do this before swapping out
7425 // the content viewers so that consumers of STATE_START can access
7426 // the old document. We only deal with the toplevel load at this time --
7427 // to be consistent with normal document loading, subframes cannot start
7428 // loading until after data arrives, which is after STATE_START completes.
7429
7430 RefPtr<RestorePresentationEvent> currentPresentationRestoration =
7431 mRestorePresentationEvent.get();
7432 Stop();
7433 // Make sure we're still restoring the same presentation.
7434 // If we aren't, docshell is in process doing another load already.
7435 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, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 7436); return NS_ERROR_UNEXPECTED; } } while (false)
7436 mRestorePresentationEvent.get())do { if ((__builtin_expect(!!(!(currentPresentationRestoration
== mRestorePresentationEvent.get())), 0))) { NS_DebugBreak(NS_DEBUG_WARNING
, "NS_ENSURE_TRUE(" "currentPresentationRestoration == mRestorePresentationEvent.get()"
") failed", nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 7436); return NS_ERROR_UNEXPECTED; } } while (false)
;
7437 BeginRestore(viewer, true);
7438 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, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 7439); return NS_ERROR_UNEXPECTED; } } while (false)
7439 mRestorePresentationEvent.get())do { if ((__builtin_expect(!!(!(currentPresentationRestoration
== mRestorePresentationEvent.get())), 0))) { NS_DebugBreak(NS_DEBUG_WARNING
, "NS_ENSURE_TRUE(" "currentPresentationRestoration == mRestorePresentationEvent.get()"
") failed", nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 7439); return NS_ERROR_UNEXPECTED; } } while (false)
;
7440 forgetter.Forget();
7441
7442 // Set mFiredUnloadEvent = false so that the unload handler for the
7443 // *new* document will fire.
7444 mFiredUnloadEvent = false;
7445
7446 mURIResultedInDocument = true;
7447 RefPtr<ChildSHistory> rootSH = GetRootSessionHistory();
7448 if (rootSH) {
7449 mPreviousEntryIndex = rootSH->Index();
7450 rootSH->LegacySHistory()->UpdateIndex();
7451 mLoadedEntryIndex = rootSH->Index();
7452 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)
7453 ("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)
7454 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)
;
7455 }
7456
7457 // Rather than call Embed(), we will retrieve the viewer from the session
7458 // history entry and swap it in.
7459 // XXX can we refactor this so that we can just call Embed()?
7460 PersistLayoutHistoryState();
7461 nsresult rv;
7462 if (mDocumentViewer) {
7463 if (mSavingOldViewer && NS_FAILED(CaptureState())((bool)(__builtin_expect(!!(NS_FAILED_impl(CaptureState())), 0
)))
) {
7464 if (mOSHE) {
7465 mOSHE->SyncPresentationState();
7466 }
7467 mSavingOldViewer = false;
7468 }
7469 }
7470
7471 mSavedRefreshURIList = nullptr;
7472
7473 // In cases where we use a transient about:blank viewer between loads,
7474 // we never show the transient viewer, so _its_ previous viewer is never
7475 // unhooked from the view hierarchy. Destroy any such previous viewer now,
7476 // before we grab the root view sibling, so that we don't grab a view
7477 // that's about to go away.
7478
7479 if (mDocumentViewer) {
7480 // Make sure to hold a strong ref to previousViewer here while we
7481 // drop the reference to it from mDocumentViewer.
7482 nsCOMPtr<nsIDocumentViewer> previousViewer =
7483 mDocumentViewer->GetPreviousViewer();
7484 if (previousViewer) {
7485 mDocumentViewer->SetPreviousViewer(nullptr);
7486 previousViewer->Destroy();
7487 }
7488 }
7489
7490 // Save off the root view's parent and sibling so that we can insert the
7491 // new content viewer's root view at the same position. Also save the
7492 // bounds of the root view's widget.
7493
7494 nsView* rootViewSibling = nullptr;
7495 nsView* rootViewParent = nullptr;
7496 LayoutDeviceIntRect newBounds(0, 0, 0, 0);
7497
7498 PresShell* oldPresShell = GetPresShell();
7499 if (oldPresShell) {
7500 nsViewManager* vm = oldPresShell->GetViewManager();
7501 if (vm) {
7502 nsView* oldRootView = vm->GetRootView();
7503
7504 if (oldRootView) {
7505 rootViewSibling = oldRootView->GetNextSibling();
7506 rootViewParent = oldRootView->GetParent();
7507
7508 mDocumentViewer->GetBounds(newBounds);
7509 }
7510 }
7511 }
7512
7513 nsCOMPtr<nsIContent> container;
7514 RefPtr<Document> sibling;
7515 if (rootViewParent && rootViewParent->GetParent()) {
7516 nsIFrame* frame = rootViewParent->GetParent()->GetFrame();
7517 container = frame ? frame->GetContent() : nullptr;
7518 }
7519 if (rootViewSibling) {
7520 nsIFrame* frame = rootViewSibling->GetFrame();
7521 sibling = frame ? frame->PresShell()->GetDocument() : nullptr;
7522 }
7523
7524 // Transfer ownership to mDocumentViewer. By ensuring that either the
7525 // docshell or the session history, but not both, have references to the
7526 // content viewer, we prevent the viewer from being torn down after
7527 // Destroy() is called.
7528
7529 if (mDocumentViewer) {
7530 mDocumentViewer->Close(mSavingOldViewer ? mOSHE.get() : nullptr);
7531 viewer->SetPreviousViewer(mDocumentViewer);
7532 }
7533 if (mOSHE && (!mDocumentViewer || !mSavingOldViewer)) {
7534 // We don't plan to save a viewer in mOSHE; tell it to drop
7535 // any other state it's holding.
7536 mOSHE->SyncPresentationState();
7537 }
7538
7539 // Order the mDocumentViewer setup just like Embed does.
7540 mDocumentViewer = nullptr;
7541
7542 // Now that we're about to switch documents, forget all of our children.
7543 // Note that we cached them as needed up in CaptureState above.
7544 DestroyChildren();
7545
7546 mDocumentViewer.swap(viewer);
7547
7548 // Grab all of the related presentation from the SHEntry now.
7549 // Clearing the viewer from the SHEntry will clear all of this state.
7550 nsCOMPtr<nsISupports> windowState = mLSHE->GetWindowState();
7551 mLSHE->SetWindowState(nullptr);
7552
7553 bool sticky = mLSHE->GetSticky();
7554
7555 RefPtr<Document> document = mDocumentViewer->GetDocument();
7556
7557 nsCOMArray<nsIDocShellTreeItem> childShells;
7558 int32_t i = 0;
7559 nsCOMPtr<nsIDocShellTreeItem> child;
7560 while (NS_SUCCEEDED(mLSHE->ChildShellAt(i++, getter_AddRefs(child)))((bool)(__builtin_expect(!!(!NS_FAILED_impl(mLSHE->ChildShellAt
(i++, getter_AddRefs(child)))), 1)))
&&
7561 child) {
7562 childShells.AppendObject(child);
7563 }
7564
7565 // get the previous content viewer size
7566 nsIntRect oldBounds(0, 0, 0, 0);
7567 mLSHE->GetViewerBounds(oldBounds);
7568
7569 // Restore the refresh URI list. The refresh timers will be restarted
7570 // when EndPageLoad() is called.
7571 nsCOMPtr<nsIMutableArray> refreshURIList = mLSHE->GetRefreshURIList();
7572
7573 // Reattach to the window object.
7574 mIsRestoringDocument = true; // for MediaDocument::BecomeInteractive
7575 rv = mDocumentViewer->Open(windowState, mLSHE);
7576 mIsRestoringDocument = false;
7577
7578 // Hack to keep nsDocShellEditorData alive across the
7579 // SetDocumentViewer(nullptr) call below.
7580 UniquePtr<nsDocShellEditorData> data(mLSHE->ForgetEditorData());
7581
7582 // Now remove it from the cached presentation.
7583 mLSHE->SetDocumentViewer(nullptr);
7584 mEODForCurrentDocument = false;
7585
7586 mLSHE->SetEditorData(data.release());
7587
7588#ifdef DEBUG1
7589 {
7590 nsCOMPtr<nsIMutableArray> refreshURIs = mLSHE->GetRefreshURIList();
7591 nsCOMPtr<nsIDocShellTreeItem> childShell;
7592 mLSHE->ChildShellAt(0, getter_AddRefs(childShell));
7593 NS_ASSERTION(!refreshURIs && !childShell,do { if (!(!refreshURIs && !childShell)) { NS_DebugBreak
(NS_DEBUG_ASSERTION, "SHEntry should have cleared presentation state"
, "!refreshURIs && !childShell", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 7594); MOZ_PretendNoReturn(); } } while (0)
7594 "SHEntry should have cleared presentation state")do { if (!(!refreshURIs && !childShell)) { NS_DebugBreak
(NS_DEBUG_ASSERTION, "SHEntry should have cleared presentation state"
, "!refreshURIs && !childShell", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 7594); MOZ_PretendNoReturn(); } } while (0)
;
7595 }
7596#endif
7597
7598 // Restore the sticky state of the viewer. The viewer has set this state
7599 // on the history entry in Destroy() just before marking itself non-sticky,
7600 // to avoid teardown of the presentation.
7601 mDocumentViewer->SetSticky(sticky);
7602
7603 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, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 7603); return rv; } } while (false)
;
7604
7605 // mLSHE is now our currently-loaded document.
7606 SetHistoryEntryAndUpdateBC(Nothing(), Some<nsISHEntry*>(mLSHE));
7607
7608 // We aren't going to restore any items from the LayoutHistoryState,
7609 // but we don't want them to stay around in case the page is reloaded.
7610 SetLayoutHistoryState(nullptr);
7611
7612 // This is the end of our Embed() replacement
7613
7614 mSavingOldViewer = false;
7615 mEODForCurrentDocument = false;
7616
7617 if (document) {
7618 RefPtr<nsDocShell> parent = GetInProcessParentDocshell();
7619 if (parent) {
7620 RefPtr<Document> d = parent->GetDocument();
7621 if (d) {
7622 if (d->EventHandlingSuppressed()) {
7623 document->SuppressEventHandling(d->EventHandlingSuppressed());
7624 }
7625 }
7626 }
7627
7628 // Use the uri from the mLSHE we had when we entered this function
7629 // (which need not match the document's URI if anchors are involved),
7630 // since that's the history entry we're loading. Note that if we use
7631 // origLSHE we don't have to worry about whether the entry in question
7632 // is still mLSHE or whether it's now mOSHE.
7633 nsCOMPtr<nsIURI> uri = origLSHE->GetURI();
7634 SetCurrentURI(uri, document->GetChannel(), /* aFireLocationChange */ true,
7635 /* aIsInitialAboutBlank */ false,
7636 /* aLocationFlags */ 0);
7637 }
7638
7639 // This is the end of our CreateDocumentViewer() replacement.
7640 // Now we simulate a load. First, we restore the state of the javascript
7641 // window object.
7642 nsCOMPtr<nsPIDOMWindowOuter> privWin = GetWindow();
7643 NS_ASSERTION(privWin, "could not get nsPIDOMWindow interface")do { if (!(privWin)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "could not get nsPIDOMWindow interface"
, "privWin", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 7643); MOZ_PretendNoReturn(); } } while (0)
;
7644
7645 // Now, dispatch a title change event which would happen as the
7646 // <head> is parsed.
7647 document->NotifyPossibleTitleChange(false);
7648
7649 // Now we simulate appending child docshells for subframes.
7650 for (i = 0; i < childShells.Count(); ++i) {
7651 nsIDocShellTreeItem* childItem = childShells.ObjectAt(i);
7652 nsCOMPtr<nsIDocShell> childShell = do_QueryInterface(childItem);
7653
7654 // Make sure to not clobber the state of the child. Since AddChild
7655 // always clobbers it, save it off first.
7656 bool allowRedirects;
7657 childShell->GetAllowMetaRedirects(&allowRedirects);
7658
7659 bool allowSubframes;
7660 childShell->GetAllowSubframes(&allowSubframes);
7661
7662 bool allowImages;
7663 childShell->GetAllowImages(&allowImages);
7664
7665 bool allowMedia = childShell->GetAllowMedia();
7666
7667 bool allowDNSPrefetch;
7668 childShell->GetAllowDNSPrefetch(&allowDNSPrefetch);
7669
7670 bool allowContentRetargeting = childShell->GetAllowContentRetargeting();
7671 bool allowContentRetargetingOnChildren =
7672 childShell->GetAllowContentRetargetingOnChildren();
7673
7674 // this.AddChild(child) calls child.SetDocLoaderParent(this), meaning that
7675 // the child inherits our state. Among other things, this means that the
7676 // child inherits our mPrivateBrowsingId, which is what we want.
7677 AddChild(childItem);
7678
7679 childShell->SetAllowMetaRedirects(allowRedirects);
7680 childShell->SetAllowSubframes(allowSubframes);
7681 childShell->SetAllowImages(allowImages);
7682 childShell->SetAllowMedia(allowMedia);
7683 childShell->SetAllowDNSPrefetch(allowDNSPrefetch);
7684 childShell->SetAllowContentRetargeting(allowContentRetargeting);
7685 childShell->SetAllowContentRetargetingOnChildren(
7686 allowContentRetargetingOnChildren);
7687
7688 rv = childShell->BeginRestore(nullptr, false);
7689 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, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 7689); return rv; } } while (false)
;
7690 }
7691
7692 // Make sure to restore the window state after adding the child shells back
7693 // to the tree. This is necessary for Thaw() and Resume() to propagate
7694 // properly.
7695 rv = privWin->RestoreWindowState(windowState);
7696 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, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 7696); return rv; } } while (false)
;
7697
7698 RefPtr<PresShell> presShell = GetPresShell();
7699
7700 // We may be displayed on a different monitor (or in a different
7701 // HiDPI mode) than when we got into the history list. So we need
7702 // to check if this has happened. See bug 838239.
7703
7704 // Because the prescontext normally handles resolution changes via
7705 // a runnable (see nsPresContext::UIResolutionChanged), its device
7706 // context won't be -immediately- updated as a result of calling
7707 // presShell->BackingScaleFactorChanged().
7708
7709 // But we depend on that device context when adjusting the view size
7710 // via mDocumentViewer->SetBounds(newBounds) below. So we need to
7711 // explicitly tell it to check for changed resolution here.
7712 if (presShell) {
7713 RefPtr<nsPresContext> pc = presShell->GetPresContext();
7714 if (pc->DeviceContext()->CheckDPIChange()) {
7715 presShell->BackingScaleFactorChanged();
7716 }
7717 // Recompute zoom and text-zoom and such.
7718 pc->RecomputeBrowsingContextDependentData();
7719 }
7720
7721 nsViewManager* newVM = presShell ? presShell->GetViewManager() : nullptr;
7722 nsView* newRootView = newVM ? newVM->GetRootView() : nullptr;
7723
7724 // Insert the new root view at the correct location in the view tree.
7725 if (container) {
7726 nsSubDocumentFrame* subDocFrame =
7727 do_QueryFrame(container->GetPrimaryFrame());
7728 rootViewParent = subDocFrame ? subDocFrame->EnsureInnerView() : nullptr;
7729 } else {
7730 rootViewParent = nullptr;
7731 }
7732 if (sibling && sibling->GetPresShell() &&
7733 sibling->GetPresShell()->GetViewManager()) {
7734 rootViewSibling = sibling->GetPresShell()->GetViewManager()->GetRootView();
7735 } else {
7736 rootViewSibling = nullptr;
7737 }
7738 if (rootViewParent && newRootView &&
7739 newRootView->GetParent() != rootViewParent) {
7740 nsViewManager* parentVM = rootViewParent->GetViewManager();
7741 if (parentVM) {
7742 // InsertChild(parent, child, sib, true) inserts the child after
7743 // sib in content order, which is before sib in view order. BUT
7744 // when sib is null it inserts at the end of the the document
7745 // order, i.e., first in view order. But when oldRootSibling is
7746 // null, the old root as at the end of the view list --- last in
7747 // content order --- and we want to call InsertChild(parent, child,
7748 // nullptr, false) in that case.
7749 parentVM->InsertChild(rootViewParent, newRootView, rootViewSibling,
7750 rootViewSibling ? true : false);
7751
7752 NS_ASSERTION(newRootView->GetNextSibling() == rootViewSibling,do { if (!(newRootView->GetNextSibling() == rootViewSibling
)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "error in InsertChild"
, "newRootView->GetNextSibling() == rootViewSibling", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 7753); MOZ_PretendNoReturn(); } } while (0)
7753 "error in InsertChild")do { if (!(newRootView->GetNextSibling() == rootViewSibling
)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "error in InsertChild"
, "newRootView->GetNextSibling() == rootViewSibling", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 7753); MOZ_PretendNoReturn(); } } while (0)
;
7754 }
7755 }
7756
7757 nsCOMPtr<nsPIDOMWindowInner> privWinInner = privWin->GetCurrentInnerWindow();
7758
7759 // If parent is suspended, increase suspension count.
7760 // This can't be done as early as event suppression since this
7761 // depends on docshell tree.
7762 privWinInner->SyncStateFromParentWindow();
7763
7764 // Now that all of the child docshells have been put into place, we can
7765 // restart the timers for the window and all of the child frames.
7766 privWinInner->Resume();
7767
7768 // Now that we have found the inner window of the page restored
7769 // from the history, we have to make sure that
7770 // performance.navigation.type is 2.
7771 Performance* performance = privWinInner->GetPerformance();
7772 if (performance) {
7773 performance->GetDOMTiming()->NotifyRestoreStart();
7774 }
7775
7776 // Restore the refresh URI list. The refresh timers will be restarted
7777 // when EndPageLoad() is called.
7778 mRefreshURIList = refreshURIList;
7779
7780 // Meta-refresh timers have been restarted for this shell, but not
7781 // for our children. Walk the child shells and restart their timers.
7782 for (auto* childDocLoader : mChildList.ForwardRange()) {
7783 nsCOMPtr<nsIDocShell> child = do_QueryObject(childDocLoader);
7784 if (child) {
7785 child->ResumeRefreshURIs();
7786 }
7787 }
7788
7789 // Make sure this presentation is the same size as the previous
7790 // presentation. If this is not the same size we showed it at last time,
7791 // then we need to resize the widget.
7792
7793 // XXXbryner This interacts poorly with Firefox's infobar. If the old
7794 // presentation had the infobar visible, then we will resize the new
7795 // presentation to that smaller size. However, firing the locationchanged
7796 // event will hide the infobar, which will immediately resize the window
7797 // back to the larger size. A future optimization might be to restore
7798 // the presentation at the "wrong" size, then fire the locationchanged
7799 // event and check whether the docshell's new size is the same as the
7800 // cached viewer size (skipping the resize if they are equal).
7801
7802 if (newRootView) {
7803 if (!newBounds.IsEmpty() &&
7804 !newBounds.ToUnknownRect().IsEqualEdges(oldBounds)) {
7805 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)
7806 ("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)
7807 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)
;
7808 mDocumentViewer->SetBounds(newBounds);
7809 } else if (ScrollContainerFrame* sf =
7810 presShell->GetRootScrollContainerFrame()) {
7811 sf->PostScrolledAreaEventForCurrentArea();
7812 }
7813 }
7814
7815 // The FinishRestore call below can kill these, null them out so we don't
7816 // have invalid pointer lying around.
7817 newRootView = rootViewSibling = rootViewParent = nullptr;
7818 newVM = nullptr;
7819
7820 // If the IsUnderHiddenEmbedderElement() state has been changed, we need to
7821 // update it.
7822 if (oldPresShell && presShell &&
7823 presShell->IsUnderHiddenEmbedderElement() !=
7824 oldPresShell->IsUnderHiddenEmbedderElement()) {
7825 presShell->SetIsUnderHiddenEmbedderElement(
7826 oldPresShell->IsUnderHiddenEmbedderElement());
7827 }
7828
7829 // Simulate the completion of the load.
7830 nsDocShell::FinishRestore();
7831
7832 // Restart plugins, and paint the content.
7833 if (presShell) {
7834 presShell->Thaw();
7835 }
7836
7837 return privWin->FireDelayedDOMEvents(true);
7838}
7839
7840nsresult nsDocShell::CreateDocumentViewer(const nsACString& aContentType,
7841 nsIRequest* aRequest,
7842 nsIStreamListener** aContentHandler) {
7843 *aContentHandler = nullptr;
7844
7845 if (!mTreeOwner || mIsBeingDestroyed) {
7846 // If we don't have a tree owner, then we're in the process of being
7847 // destroyed. Rather than continue trying to load something, just give up.
7848 return NS_ERROR_DOCSHELL_DYING;
7849 }
7850
7851 if (!mBrowsingContext->AncestorsAreCurrent() ||
7852 mBrowsingContext->IsInBFCache()) {
7853 mBrowsingContext->RemoveRootFromBFCacheSync();
7854 return NS_ERROR_NOT_AVAILABLE;
7855 }
7856
7857 // Can we check the content type of the current content viewer
7858 // and reuse it without destroying it and re-creating it?
7859
7860 NS_ASSERTION(mLoadGroup, "Someone ignored return from Init()?")do { if (!(mLoadGroup)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "Someone ignored return from Init()?"
, "mLoadGroup", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 7860); MOZ_PretendNoReturn(); } } while (0)
;
7861
7862 // Instantiate the content viewer object
7863 nsCOMPtr<nsIDocumentViewer> viewer;
7864 nsresult rv = NewDocumentViewerObj(aContentType, aRequest, mLoadGroup,
7865 aContentHandler, getter_AddRefs(viewer));
7866
7867 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
7868 return rv;
7869 }
7870
7871 // Notify the current document that it is about to be unloaded!!
7872 //
7873 // It is important to fire the unload() notification *before* any state
7874 // is changed within the DocShell - otherwise, javascript will get the
7875 // wrong information :-(
7876 //
7877
7878 if (mSavingOldViewer) {
7879 // We determined that it was safe to cache the document presentation
7880 // at the time we initiated the new load. We need to check whether
7881 // it's still safe to do so, since there may have been DOM mutations
7882 // or new requests initiated.
7883 RefPtr<Document> doc = viewer->GetDocument();
7884 mSavingOldViewer = CanSavePresentation(
7885 mLoadType, aRequest, doc, /* aReportBFCacheComboTelemetry */ false);
7886 }
7887
7888 NS_ASSERTION(!mLoadingURI, "Re-entering unload?")do { if (!(!mLoadingURI)) { NS_DebugBreak(NS_DEBUG_ASSERTION,
"Re-entering unload?", "!mLoadingURI", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 7888); MOZ_PretendNoReturn(); } } while (0)
;
7889
7890 nsCOMPtr<nsIChannel> aOpenedChannel = do_QueryInterface(aRequest);
7891 if (aOpenedChannel) {
7892 aOpenedChannel->GetURI(getter_AddRefs(mLoadingURI));
7893 }
7894
7895 // Grab the current URI, we need to pass it to Embed, and OnNewURI will reset
7896 // it before we do call Embed.
7897 nsCOMPtr<nsIURI> previousURI = mCurrentURI;
7898
7899 FirePageHideNotification(!mSavingOldViewer);
7900 if (mIsBeingDestroyed) {
7901 // Force to stop the newly created orphaned viewer.
7902 viewer->Stop();
7903 return NS_ERROR_DOCSHELL_DYING;
7904 }
7905 mLoadingURI = nullptr;
7906
7907 // Set mFiredUnloadEvent = false so that the unload handler for the
7908 // *new* document will fire.
7909 mFiredUnloadEvent = false;
7910
7911 // we've created a new document so go ahead and call
7912 // OnNewURI(), but don't fire OnLocationChange()
7913 // notifications before we've called Embed(). See bug 284993.
7914 mURIResultedInDocument = true;
7915 bool errorOnLocationChangeNeeded = false;
7916 nsCOMPtr<nsIChannel> failedChannel = mFailedChannel;
7917 nsCOMPtr<nsIURI> failedURI;
7918
7919 if (mLoadType == LOAD_ERROR_PAGE) {
7920 // We need to set the SH entry and our current URI here and not
7921 // at the moment we load the page. We want the same behavior
7922 // of Stop() as for a normal page load. See bug 514232 for details.
7923
7924 // Revert mLoadType to load type to state the page load failed,
7925 // following function calls need it.
7926 mLoadType = mFailedLoadType;
7927
7928 Document* doc = viewer->GetDocument();
7929 if (doc) {
7930 doc->SetFailedChannel(failedChannel);
7931 }
7932
7933 nsCOMPtr<nsIPrincipal> triggeringPrincipal;
7934 if (failedChannel) {
7935 // Make sure we have a URI to set currentURI.
7936 NS_GetFinalChannelURI(failedChannel, getter_AddRefs(failedURI));
7937 } else {
7938 // if there is no failed channel we have to explicitly provide
7939 // a triggeringPrincipal for the history entry.
7940 triggeringPrincipal = nsContentUtils::GetSystemPrincipal();
7941 }
7942
7943 if (!failedURI) {
7944 failedURI = mFailedURI;
7945 }
7946 if (!failedURI) {
7947 // We need a URI object to store a session history entry, so make up a URI
7948 NS_NewURI(getter_AddRefs(failedURI), "about:blank");
7949 }
7950
7951 // When we don't have failedURI, something wrong will happen. See
7952 // bug 291876.
7953 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."
")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 7953
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "failedURI" ") (" "We don't have a URI for history APIs."
")"); do { MOZ_CrashSequence(__null, 7953); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7954
7955 mFailedChannel = nullptr;
7956 mFailedURI = nullptr;
7957
7958 // Create an shistory entry for the old load.
7959 if (failedURI) {
7960 errorOnLocationChangeNeeded =
7961 OnNewURI(failedURI, failedChannel, triggeringPrincipal, nullptr,
7962 nullptr, nullptr, false, false);
7963 }
7964
7965 // Be sure to have a correct mLSHE, it may have been cleared by
7966 // EndPageLoad. See bug 302115.
7967 ChildSHistory* shistory = GetSessionHistory();
7968 if (!mozilla::SessionHistoryInParent() && shistory && !mLSHE) {
7969 int32_t idx = shistory->LegacySHistory()->GetRequestedIndex();
7970 if (idx == -1) {
7971 idx = shistory->Index();
7972 }
7973 shistory->LegacySHistory()->GetEntryAtIndex(idx, getter_AddRefs(mLSHE));
7974 }
7975
7976 mLoadType = LOAD_ERROR_PAGE;
7977 }
7978
7979 nsCOMPtr<nsIURI> finalURI;
7980 // If this a redirect, use the final url (uri)
7981 // else use the original url
7982 //
7983 // Note that this should match what documents do (see Document::Reset).
7984 NS_GetFinalChannelURI(aOpenedChannel, getter_AddRefs(finalURI));
7985
7986 bool onLocationChangeNeeded = false;
7987 if (finalURI) {
7988 // Pass false for aCloneSHChildren, since we're loading a new page here.
7989 onLocationChangeNeeded = OnNewURI(finalURI, aOpenedChannel, nullptr,
7990 nullptr, nullptr, nullptr, true, false);
7991 }
7992
7993 // We inherit the classification flags from the parent document if the
7994 // document is about:blank and the principal matches.
7995 nsCOMPtr<nsIDocShellTreeItem> parentItem;
7996 GetInProcessSameTypeParent(getter_AddRefs(parentItem));
7997 if (parentItem && finalURI && NS_IsAboutBlank(finalURI)) {
7998 RefPtr<Document> doc = viewer->GetDocument();
7999 RefPtr<Document> parentDocument = parentItem->GetDocument();
8000 if (parentDocument && doc &&
8001 doc->NodePrincipal()->Equals(parentDocument->NodePrincipal())) {
8002 doc->SetClassificationFlags(parentDocument->GetClassificationFlags());
8003 }
8004 }
8005
8006 // let's try resetting the load group if we need to...
8007 nsCOMPtr<nsILoadGroup> currentLoadGroup;
8008 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, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 8010); return NS_ERROR_FAILURE; } } while (false)
8009 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, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 8010); return NS_ERROR_FAILURE; } } while (false)
8010 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, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 8010); return NS_ERROR_FAILURE; } } while (false)
;
8011
8012 if (currentLoadGroup != mLoadGroup) {
8013 nsLoadFlags loadFlags = 0;
8014
8015 // Cancel any URIs that are currently loading...
8016 // XXX: Need to do this eventually Stop();
8017 //
8018 // Retarget the document to this loadgroup...
8019 //
8020 /* First attach the channel to the right loadgroup
8021 * and then remove from the old loadgroup. This
8022 * puts the notifications in the right order and
8023 * we don't null-out mLSHE in OnStateChange() for
8024 * all redirected urls
8025 */
8026 aOpenedChannel->SetLoadGroup(mLoadGroup);
8027
8028 // Mark the channel as being a document URI...
8029 aOpenedChannel->GetLoadFlags(&loadFlags);
8030 loadFlags |= nsIChannel::LOAD_DOCUMENT_URI;
8031 nsCOMPtr<nsILoadInfo> loadInfo = aOpenedChannel->LoadInfo();
8032 if (SandboxFlagsImplyCookies(loadInfo->GetSandboxFlags())) {
8033 loadFlags |= nsIRequest::LOAD_DOCUMENT_NEEDS_COOKIE;
8034 }
8035
8036 aOpenedChannel->SetLoadFlags(loadFlags);
8037
8038 mLoadGroup->AddRequest(aRequest, nullptr);
8039 if (currentLoadGroup) {
8040 currentLoadGroup->RemoveRequest(aRequest, nullptr, NS_BINDING_RETARGETED);
8041 }
8042
8043 // Update the notification callbacks, so that progress and
8044 // status information are sent to the right docshell...
8045 aOpenedChannel->SetNotificationCallbacks(this);
8046 }
8047
8048 if (mLoadingEntry && mBrowsingContext->IsTop() &&
8049 !ShouldAddToSessionHistory(finalURI, aOpenedChannel)) {
8050 mLoadingEntry->mInfo.SetTransient();
8051 }
8052 NS_ENSURE_SUCCESS(Embed(viewer, nullptr, false, aOpenedChannel, previousURI),do { nsresult __rv = Embed(viewer, nullptr, false, 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, aOpenedChannel, previousURI)"
, "NS_ERROR_FAILURE", static_cast<uint32_t>(__rv), name
? " (" : "", name ? name : "", name ? ")" : ""); NS_DebugBreak
(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 8053); return NS_ERROR_FAILURE; } } while (false)
8053 NS_ERROR_FAILURE)do { nsresult __rv = Embed(viewer, nullptr, false, 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, aOpenedChannel, previousURI)"
, "NS_ERROR_FAILURE", static_cast<uint32_t>(__rv), name
? " (" : "", name ? name : "", name ? ")" : ""); NS_DebugBreak
(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 8053); return NS_ERROR_FAILURE; } } while (false)
;
8054
8055 if (!mBrowsingContext->GetHasLoadedNonInitialDocument()) {
8056 MOZ_ALWAYS_SUCCEEDS(mBrowsingContext->SetHasLoadedNonInitialDocument(true))do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(mBrowsingContext->SetHasLoadedNonInitialDocument(true))),
1)))), 1))) { } else { do { do { } while (false); MOZ_ReportCrash
("" "NS_SUCCEEDED(mBrowsingContext->SetHasLoadedNonInitialDocument(true))"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 8056); AnnotateMozCrashReason
("MOZ_CRASH(" "NS_SUCCEEDED(mBrowsingContext->SetHasLoadedNonInitialDocument(true))"
")"); do { MOZ_CrashSequence(__null, 8056); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
;
8057 }
8058
8059 mSavedRefreshURIList = nullptr;
8060 mSavingOldViewer = false;
8061 mEODForCurrentDocument = false;
8062
8063 // if this document is part of a multipart document,
8064 // the ID can be used to distinguish it from the other parts.
8065 nsCOMPtr<nsIMultiPartChannel> multiPartChannel(do_QueryInterface(aRequest));
8066 if (multiPartChannel) {
8067 if (PresShell* presShell = GetPresShell()) {
8068 if (Document* doc = presShell->GetDocument()) {
8069 uint32_t partID;
8070 multiPartChannel->GetPartID(&partID);
8071 doc->SetPartID(partID);
8072 }
8073 }
8074 }
8075
8076 if (errorOnLocationChangeNeeded) {
8077 FireOnLocationChange(this, failedChannel, failedURI,
8078 LOCATION_CHANGE_ERROR_PAGE);
8079 } else if (onLocationChangeNeeded) {
8080 uint32_t locationFlags =
8081 (mLoadType & LOAD_CMD_RELOAD) ? uint32_t(LOCATION_CHANGE_RELOAD) : 0;
8082 FireOnLocationChange(this, aRequest, mCurrentURI, locationFlags);
8083 }
8084
8085 return NS_OK;
8086}
8087
8088nsresult nsDocShell::NewDocumentViewerObj(const nsACString& aContentType,
8089 nsIRequest* aRequest,
8090 nsILoadGroup* aLoadGroup,
8091 nsIStreamListener** aContentHandler,
8092 nsIDocumentViewer** aViewer) {
8093 nsCOMPtr<nsIChannel> aOpenedChannel = do_QueryInterface(aRequest);
8094
8095 nsCOMPtr<nsIDocumentLoaderFactory> docLoaderFactory =
8096 nsContentUtils::FindInternalDocumentViewer(aContentType);
8097 if (!docLoaderFactory) {
8098 return NS_ERROR_FAILURE;
8099 }
8100
8101 // Now create an instance of the content viewer nsLayoutDLF makes the
8102 // determination if it should be a "view-source" instead of "view"
8103 nsresult rv = docLoaderFactory->CreateInstance(
8104 "view", aOpenedChannel, aLoadGroup, aContentType, this, nullptr,
8105 aContentHandler, aViewer);
8106 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, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 8106); return rv; } } while (false)
;
8107
8108 (*aViewer)->SetContainer(this);
8109 return NS_OK;
8110}
8111
8112nsresult nsDocShell::SetupNewViewer(nsIDocumentViewer* aNewViewer,
8113 WindowGlobalChild* aWindowActor) {
8114 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"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 8114); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!mIsBeingDestroyed" ")"); do { MOZ_CrashSequence
(__null, 8114); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
8115
8116 //
8117 // Copy content viewer state from previous or parent content viewer.
8118 //
8119 // The following logic is mirrored in nsHTMLDocument::StartDocumentLoad!
8120 //
8121 // Do NOT to maintain a reference to the old content viewer outside
8122 // of this "copying" block, or it will not be destroyed until the end of
8123 // this routine and all <SCRIPT>s and event handlers fail! (bug 20315)
8124 //
8125 // In this block of code, if we get an error result, we return it
8126 // but if we get a null pointer, that's perfectly legal for parent
8127 // and parentDocumentViewer.
8128 //
8129
8130 int32_t x = 0;
8131 int32_t y = 0;
8132 int32_t cx = 0;
8133 int32_t cy = 0;
8134
8135 // This will get the size from the current content viewer or from the
8136 // Init settings
8137 DoGetPositionAndSize(&x, &y, &cx, &cy);
8138
8139 nsCOMPtr<nsIDocShellTreeItem> parentAsItem;
8140 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, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 8141); return NS_ERROR_FAILURE; } } while (false)
8141 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, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 8141); return NS_ERROR_FAILURE; } } while (false)
;
8142 nsCOMPtr<nsIDocShell> parent(do_QueryInterface(parentAsItem));
8143
8144 const Encoding* reloadEncoding = nullptr;
8145 int32_t reloadEncodingSource = kCharsetUninitialized;
8146 // |newMUDV| also serves as a flag to set the data from the above vars
8147 nsCOMPtr<nsIDocumentViewer> newViewer;
8148
8149 if (mDocumentViewer || parent) {
8150 nsCOMPtr<nsIDocumentViewer> oldViewer;
8151 if (mDocumentViewer) {
8152 // Get any interesting state from old content viewer
8153 // XXX: it would be far better to just reuse the document viewer ,
8154 // since we know we're just displaying the same document as before
8155 oldViewer = mDocumentViewer;
8156
8157 // Tell the old content viewer to hibernate in session history when
8158 // it is destroyed.
8159
8160 if (mSavingOldViewer && NS_FAILED(CaptureState())((bool)(__builtin_expect(!!(NS_FAILED_impl(CaptureState())), 0
)))
) {
8161 if (mOSHE) {
8162 mOSHE->SyncPresentationState();
8163 }
8164 mSavingOldViewer = false;
8165 }
8166 } else {
8167 // No old content viewer, so get state from parent's content viewer
8168 parent->GetDocViewer(getter_AddRefs(oldViewer));
8169 }
8170
8171 if (oldViewer) {
8172 newViewer = aNewViewer;
8173 if (newViewer) {
8174 reloadEncoding =
8175 oldViewer->GetReloadEncodingAndSource(&reloadEncodingSource);
8176 }
8177 }
8178 }
8179
8180 nscolor bgcolor = NS_RGBA(0, 0, 0, 0)((nscolor)(((0) << 24) | ((0) << 16) | ((0) <<
8) | (0)))
;
8181 bool isUnderHiddenEmbedderElement = false;
8182 // Ensure that the content viewer is destroyed *after* the GC - bug 71515
8183 nsCOMPtr<nsIDocumentViewer> viewer = mDocumentViewer;
8184 if (viewer) {
8185 // Stop any activity that may be happening in the old document before
8186 // releasing it...
8187 viewer->Stop();
8188
8189 // Try to extract the canvas background color from the old
8190 // presentation shell, so we can use it for the next document.
8191 if (PresShell* presShell = viewer->GetPresShell()) {
8192 bgcolor = presShell->GetCanvasBackground();
8193 isUnderHiddenEmbedderElement = presShell->IsUnderHiddenEmbedderElement();
8194 }
8195
8196 viewer->Close(mSavingOldViewer ? mOSHE.get() : nullptr);
8197 aNewViewer->SetPreviousViewer(viewer);
8198 }
8199 if (mOSHE && (!mDocumentViewer || !mSavingOldViewer)) {
8200 // We don't plan to save a viewer in mOSHE; tell it to drop
8201 // any other state it's holding.
8202 mOSHE->SyncPresentationState();
8203 }
8204
8205 mDocumentViewer = nullptr;
8206
8207 // Now that we're about to switch documents, forget all of our children.
8208 // Note that we cached them as needed up in CaptureState above.
8209 DestroyChildren();
8210
8211 mDocumentViewer = aNewViewer;
8212
8213 nsCOMPtr<nsIWidget> widget;
8214 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, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 8214); return NS_ERROR_FAILURE; } } while (false)
;
8215
8216 LayoutDeviceIntRect bounds(x, y, cx, cy);
8217
8218 mDocumentViewer->SetNavigationTiming(mTiming);
8219
8220 if (NS_FAILED(mDocumentViewer->Init(widget, bounds, aWindowActor))((bool)(__builtin_expect(!!(NS_FAILED_impl(mDocumentViewer->
Init(widget, bounds, aWindowActor))), 0)))
) {
8221 nsCOMPtr<nsIDocumentViewer> viewer = mDocumentViewer;
8222 viewer->Close(nullptr);
8223 viewer->Destroy();
8224 mDocumentViewer = nullptr;
8225 SetCurrentURIInternal(nullptr);
8226 NS_WARNING("DocumentViewer Initialization failed")NS_DebugBreak(NS_DEBUG_WARNING, "DocumentViewer Initialization failed"
, nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 8226)
;
8227 return NS_ERROR_FAILURE;
8228 }
8229
8230 // If we have old state to copy, set the old state onto the new content
8231 // viewer
8232 if (newViewer) {
8233 newViewer->SetReloadEncodingAndSource(reloadEncoding, reloadEncodingSource);
8234 }
8235
8236 NS_ENSURE_TRUE(mDocumentViewer, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(mDocumentViewer)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "mDocumentViewer" ") failed"
, nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 8236); return NS_ERROR_FAILURE; } } while (false)
;
8237
8238 // Stuff the bgcolor from the old pres shell into the new
8239 // pres shell. This improves page load continuity.
8240 if (RefPtr<PresShell> presShell = mDocumentViewer->GetPresShell()) {
8241 presShell->SetCanvasBackground(bgcolor);
8242 presShell->ActivenessMaybeChanged();
8243 if (isUnderHiddenEmbedderElement) {
8244 presShell->SetIsUnderHiddenEmbedderElement(isUnderHiddenEmbedderElement);
8245 }
8246 }
8247
8248 // XXX: It looks like the LayoutState gets restored again in Embed()
8249 // right after the call to SetupNewViewer(...)
8250
8251 // We don't show the mDocumentViewer yet, since we want to draw the old page
8252 // until we have enough of the new page to show. Just return with the new
8253 // viewer still set to hidden.
8254
8255 return NS_OK;
8256}
8257
8258void nsDocShell::SetDocCurrentStateObj(nsISHEntry* aShEntry,
8259 SessionHistoryInfo* aInfo) {
8260 NS_ENSURE_TRUE_VOID(mDocumentViewer)do { if ((__builtin_expect(!!(!(mDocumentViewer)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "mDocumentViewer" ") failed"
, nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 8260); return; } } while (false)
;
8261
8262 RefPtr<Document> document = GetDocument();
8263 NS_ENSURE_TRUE_VOID(document)do { if ((__builtin_expect(!!(!(document)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "document" ") failed", nullptr
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 8263); return
; } } while (false)
;
8264
8265 nsCOMPtr<nsIStructuredCloneContainer> scContainer;
8266 if (mozilla::SessionHistoryInParent()) {
8267 // If aInfo is null, just set the document's state object to null.
8268 if (aInfo) {
8269 scContainer = aInfo->GetStateData();
8270 }
8271 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)
8272 ("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)
;
8273 } else {
8274 if (aShEntry) {
8275 scContainer = aShEntry->GetStateData();
8276
8277 // If aShEntry is null, just set the document's state object to null.
8278 }
8279 }
8280
8281 // It's OK for scContainer too be null here; that just means there's no
8282 // state data associated with this history entry.
8283 document->SetStateObject(scContainer);
8284}
8285
8286nsresult nsDocShell::CheckLoadingPermissions() {
8287 // This method checks whether the caller may load content into
8288 // this docshell. Even though we've done our best to hide windows
8289 // from code that doesn't have the right to access them, it's
8290 // still possible for an evil site to open a window and access
8291 // frames in the new window through window.frames[] (which is
8292 // allAccess for historic reasons), so we still need to do this
8293 // check on load.
8294 nsresult rv = NS_OK;
8295
8296 if (!IsSubframe()) {
8297 // We're not a frame. Permit all loads.
8298 return rv;
8299 }
8300
8301 // Note - The check for a current JSContext here isn't necessarily sensical.
8302 // It's just designed to preserve the old semantics during a mass-conversion
8303 // patch.
8304 if (!nsContentUtils::GetCurrentJSContext()) {
8305 return NS_OK;
8306 }
8307
8308 // Check if the caller is from the same origin as this docshell,
8309 // or any of its ancestors.
8310 nsIPrincipal* subjectPrincipal = nsContentUtils::SubjectPrincipal();
8311 for (RefPtr<BrowsingContext> bc = mBrowsingContext; bc;
8312 bc = bc->GetParent()) {
8313 // If the BrowsingContext is not in process, then it
8314 // is true by construction that its principal will not
8315 // subsume the current docshell principal.
8316 if (!bc->IsInProcess()) {
8317 continue;
8318 }
8319
8320 nsCOMPtr<nsIScriptGlobalObject> sgo =
8321 bc->GetDocShell()->GetScriptGlobalObject();
8322 nsCOMPtr<nsIScriptObjectPrincipal> sop(do_QueryInterface(sgo));
8323
8324 nsIPrincipal* p;
8325 if (!sop || !(p = sop->GetPrincipal())) {
8326 return NS_ERROR_UNEXPECTED;
8327 }
8328
8329 // file: URIs are considered the same domain for the purpose of frame
8330 // navigation by clicking a targeted link, regardless of script
8331 // accessibility (bug 1934807).
8332 if (subjectPrincipal->Subsumes(p) ||
8333 (subjectPrincipal->SchemeIs("file") && p->SchemeIs("file"))) {
8334 // Same origin, permit load
8335 return NS_OK;
8336 }
8337 }
8338
8339 return NS_ERROR_DOM_PROP_ACCESS_DENIED;
8340}
8341
8342//*****************************************************************************
8343// nsDocShell: Site Loading
8344//*****************************************************************************
8345
8346void nsDocShell::CopyFavicon(nsIURI* aOldURI, nsIURI* aNewURI,
8347 bool aInPrivateBrowsing) {
8348 if (XRE_IsContentProcess()) {
8349 dom::ContentChild* contentChild = dom::ContentChild::GetSingleton();
8350 if (contentChild) {
8351 contentChild->SendCopyFavicon(aOldURI, aNewURI, aInPrivateBrowsing);
8352 }
8353 return;
8354 }
8355
8356#ifdef MOZ_PLACES1
8357 auto* faviconService = nsFaviconService::GetFaviconService();
8358 if (faviconService) {
8359 faviconService->AsyncTryCopyFavicons(
8360 aOldURI, aNewURI,
8361 aInPrivateBrowsing ? nsIFaviconService::FAVICON_LOAD_PRIVATE
8362 : nsIFaviconService::FAVICON_LOAD_NON_PRIVATE);
8363 }
8364#endif
8365}
8366
8367class InternalLoadEvent : public Runnable {
8368 public:
8369 InternalLoadEvent(nsDocShell* aDocShell, nsDocShellLoadState* aLoadState)
8370 : mozilla::Runnable("InternalLoadEvent"),
8371 mDocShell(aDocShell),
8372 mLoadState(aLoadState) {
8373 // For events, both target and filename should be the version of "null" they
8374 // expect. By the time the event is fired, both window targeting and file
8375 // downloading have been handled, so we should never have an internal load
8376 // event that retargets or had a download.
8377 mLoadState->SetTarget(u""_ns);
8378 mLoadState->SetFileName(VoidString());
8379 }
8380
8381 NS_IMETHODvirtual nsresult
8382 Run() override {
8383#ifndef ANDROID
8384 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"
")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 8385
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mLoadState->TriggeringPrincipal()"
") (" "InternalLoadEvent: Should always have a principal here"
")"); do { MOZ_CrashSequence(__null, 8385); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
8385 "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"
")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 8385
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mLoadState->TriggeringPrincipal()"
") (" "InternalLoadEvent: Should always have a principal here"
")"); do { MOZ_CrashSequence(__null, 8385); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8386#endif
8387 return mDocShell->InternalLoad(mLoadState);
8388 }
8389
8390 private:
8391 RefPtr<nsDocShell> mDocShell;
8392 RefPtr<nsDocShellLoadState> mLoadState;
8393};
8394
8395/**
8396 * Returns true if we started an asynchronous load (i.e., from the network), but
8397 * the document we're loading there hasn't yet become this docshell's active
8398 * document.
8399 *
8400 * When JustStartedNetworkLoad is true, you should be careful about modifying
8401 * mLoadType and mLSHE. These are both set when the asynchronous load first
8402 * starts, and the load expects that, when it eventually runs InternalLoad,
8403 * mLoadType and mLSHE will have their original values.
8404 */
8405bool nsDocShell::JustStartedNetworkLoad() {
8406 return mDocumentRequest && mDocumentRequest != GetCurrentDocChannel();
8407}
8408
8409// The contentType will be INTERNAL_(I)FRAME if this docshell is for a
8410// non-toplevel browsing context in spec terms. (frame, iframe, <object>,
8411// <embed>, etc)
8412//
8413// This return value will be used when we call NS_CheckContentLoadPolicy, and
8414// later when we call DoURILoad.
8415nsContentPolicyType nsDocShell::DetermineContentType() {
8416 if (!IsSubframe()) {
8417 return nsIContentPolicy::TYPE_DOCUMENT;
8418 }
8419
8420 const auto& maybeEmbedderElementType =
8421 GetBrowsingContext()->GetEmbedderElementType();
8422 if (!maybeEmbedderElementType) {
8423 // If the EmbedderElementType hasn't been set yet, just assume we're
8424 // an iframe since that's more common.
8425 return nsIContentPolicy::TYPE_INTERNAL_IFRAME;
8426 }
8427
8428 return maybeEmbedderElementType->EqualsLiteral("iframe")
8429 ? nsIContentPolicy::TYPE_INTERNAL_IFRAME
8430 : nsIContentPolicy::TYPE_INTERNAL_FRAME;
8431}
8432
8433bool nsDocShell::NoopenerForceEnabled() {
8434 // If current's top-level browsing context's active document's
8435 // cross-origin-opener-policy is "same-origin" or "same-origin + COEP" then
8436 // if currentDoc's origin is not same origin with currentDoc's top-level
8437 // origin, noopener is force enabled, and name is cleared to "_blank".
8438 auto topPolicy = mBrowsingContext->Top()->GetOpenerPolicy();
8439 return (topPolicy == nsILoadInfo::OPENER_POLICY_SAME_ORIGIN ||
8440 topPolicy ==
8441 nsILoadInfo::
8442 OPENER_POLICY_SAME_ORIGIN_EMBEDDER_POLICY_REQUIRE_CORP) &&
8443 !mBrowsingContext->SameOriginWithTop();
8444}
8445
8446nsresult nsDocShell::PerformRetargeting(nsDocShellLoadState* aLoadState) {
8447 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!"
")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 8447
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState" ") ("
"need a load state!" ")"); do { MOZ_CrashSequence(__null, 8447
); __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
;
8448 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!"
")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 8448
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aLoadState->Target().IsEmpty()"
") (" "should have a target here!" ")"); do { MOZ_CrashSequence
(__null, 8448); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
8449 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" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 8450); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->TargetBrowsingContext().IsNull()"
") (" "should not have picked target yet" ")"); do { MOZ_CrashSequence
(__null, 8450); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
8450 "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" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 8450); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->TargetBrowsingContext().IsNull()"
") (" "should not have picked target yet" ")"); do { MOZ_CrashSequence
(__null, 8450); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
8451
8452 nsresult rv = NS_OK;
8453 RefPtr<BrowsingContext> targetContext;
8454
8455 // Only _self, _parent, and _top are supported in noopener case. But we
8456 // have to be careful to not apply that to the noreferrer case. See bug
8457 // 1358469.
8458 bool allowNamedTarget =
8459 !aLoadState->HasInternalLoadFlags(INTERNAL_LOAD_FLAGS_NO_OPENER) ||
8460 aLoadState->HasInternalLoadFlags(INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER);
8461 if (allowNamedTarget ||
8462 aLoadState->Target().LowerCaseEqualsLiteral("_self") ||
8463 aLoadState->Target().LowerCaseEqualsLiteral("_parent") ||
8464 aLoadState->Target().LowerCaseEqualsLiteral("_top")) {
8465 Document* document = GetDocument();
8466 NS_ENSURE_TRUE(document, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(document)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "document" ") failed", nullptr
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 8466); return
NS_ERROR_FAILURE; } } while (false)
;
8467 WindowGlobalChild* wgc = document->GetWindowGlobalChild();
8468 NS_ENSURE_TRUE(wgc, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(wgc)), 0))) { NS_DebugBreak(NS_DEBUG_WARNING
, "NS_ENSURE_TRUE(" "wgc" ") failed", nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 8468); return NS_ERROR_FAILURE; } } while (false)
;
8469 targetContext = wgc->FindBrowsingContextWithName(
8470 aLoadState->Target(), /* aUseEntryGlobalForAccessCheck */ false);
8471 }
8472
8473 if (!targetContext) {
8474 // If the targetContext doesn't exist, then this is a new docShell and we
8475 // should consider this a TYPE_DOCUMENT load
8476 //
8477 // For example, when target="_blank"
8478
8479 // If there's no targetContext, that means we are about to create a new
8480 // window. Perform a content policy check before creating the window. Please
8481 // note for all other docshell loads content policy checks are performed
8482 // within the contentSecurityManager when the channel is about to be
8483 // openend.
8484 nsISupports* requestingContext = nullptr;
8485 if (XRE_IsContentProcess()) {
8486 // In e10s the child process doesn't have access to the element that
8487 // contains the browsing context (because that element is in the chrome
8488 // process). So we just pass mScriptGlobal.
8489 requestingContext = ToSupports(mScriptGlobal);
8490 } else {
8491 // This is for loading non-e10s tabs and toplevel windows of various
8492 // sorts.
8493 // For the toplevel window cases, requestingElement will be null.
8494 nsCOMPtr<Element> requestingElement =
8495 mScriptGlobal->GetFrameElementInternal();
8496 requestingContext = requestingElement;
8497 }
8498
8499 // Ideally we should use the same loadinfo as within DoURILoad which
8500 // should match this one when both are applicable.
8501 nsCOMPtr<nsILoadInfo> secCheckLoadInfo =
8502 new LoadInfo(mScriptGlobal, aLoadState->URI(),
8503 aLoadState->TriggeringPrincipal(), requestingContext,
8504 nsILoadInfo::SEC_ONLY_FOR_EXPLICIT_CONTENTSEC_CHECK, 0);
8505
8506 // Since Content Policy checks are performed within docShell as well as
8507 // the ContentSecurityManager we need a reliable way to let certain
8508 // nsIContentPolicy consumers ignore duplicate calls.
8509 secCheckLoadInfo->SetSkipContentPolicyCheckForWebRequest(true);
8510
8511 int16_t shouldLoad = nsIContentPolicy::ACCEPT;
8512 rv = NS_CheckContentLoadPolicy(aLoadState->URI(), secCheckLoadInfo,
8513 &shouldLoad);
8514
8515 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) || NS_CP_REJECTED(shouldLoad)((shouldLoad) != nsIContentPolicy::ACCEPT)) {
8516 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
8517 if (shouldLoad == nsIContentPolicy::REJECT_TYPE) {
8518 return NS_ERROR_CONTENT_BLOCKED_SHOW_ALT;
8519 }
8520 if (shouldLoad == nsIContentPolicy::REJECT_POLICY) {
8521 return NS_ERROR_BLOCKED_BY_POLICY;
8522 }
8523 }
8524
8525 return NS_ERROR_CONTENT_BLOCKED;
8526 }
8527 }
8528
8529 //
8530 // Resolve the window target before going any further...
8531 // If the load has been targeted to another DocShell, then transfer the
8532 // load to it...
8533 //
8534
8535 // We've already done our owner-inheriting. Mask out that bit, so we
8536 // don't try inheriting an owner from the target window if we came up
8537 // with a null owner above.
8538 aLoadState->UnsetInternalLoadFlag(INTERNAL_LOAD_FLAGS_INHERIT_PRINCIPAL);
8539
8540 if (!targetContext) {
8541 // If the docshell's document is sandboxed, only open a new window
8542 // if the document's SANDBOXED_AUXILLARY_NAVIGATION flag is not set.
8543 // (i.e. if allow-popups is specified)
8544 NS_ENSURE_TRUE(mDocumentViewer, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(mDocumentViewer)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "mDocumentViewer" ") failed"
, nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 8544); return NS_ERROR_FAILURE; } } while (false)
;
8545 Document* doc = mDocumentViewer->GetDocument();
8546
8547 const bool isDocumentAuxSandboxed =
8548 doc && (doc->GetSandboxFlags() & SANDBOXED_AUXILIARY_NAVIGATION);
8549
8550 if (isDocumentAuxSandboxed) {
8551 return NS_ERROR_DOM_INVALID_ACCESS_ERR;
8552 }
8553
8554 nsCOMPtr<nsPIDOMWindowOuter> win = GetWindow();
8555 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, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 8555); return NS_ERROR_NOT_AVAILABLE; } } while (false)
;
8556
8557 RefPtr<BrowsingContext> newBC;
8558 nsAutoCString spec;
8559 aLoadState->URI()->GetSpec(spec);
8560
8561 // If we are a noopener load, we just hand the whole thing over to our
8562 // window.
8563 if (aLoadState->HasInternalLoadFlags(INTERNAL_LOAD_FLAGS_NO_OPENER) ||
8564 NoopenerForceEnabled()) {
8565 // Various asserts that we know to hold because NO_OPENER loads can only
8566 // happen for links.
8567 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()", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 8567); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aLoadState->LoadReplace()"
")"); do { MOZ_CrashSequence(__null, 8567); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8568 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()"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 8569); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aLoadState->PrincipalToInherit() == aLoadState->TriggeringPrincipal()"
")"); do { MOZ_CrashSequence(__null, 8569); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
8569 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()"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 8569); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aLoadState->PrincipalToInherit() == aLoadState->TriggeringPrincipal()"
")"); do { MOZ_CrashSequence(__null, 8569); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8570 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"
")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 8574
); 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 { MOZ_CrashSequence(__null, 8574); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
8571 ~(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"
")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 8574
); 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 { MOZ_CrashSequence(__null, 8574); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
8572 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"
")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 8574
); 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 { MOZ_CrashSequence(__null, 8574); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
8573 "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"
")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 8574
); 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 { MOZ_CrashSequence(__null, 8574); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
8574 "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"
")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 8574
); 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 { MOZ_CrashSequence(__null, 8574); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8575 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()", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 8576); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->IsFormSubmission()"
")"); do { MOZ_CrashSequence(__null, 8576); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
8576 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()", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 8576); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->IsFormSubmission()"
")"); do { MOZ_CrashSequence(__null, 8576); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
8577 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()", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 8577); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aLoadState->HeadersStream()"
")"); do { MOZ_CrashSequence(__null, 8577); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8578 // If OnLinkClickSync was invoked inside the onload handler, the load
8579 // type would be set to LOAD_NORMAL_REPLACE; otherwise it should be
8580 // LOAD_LINK.
8581 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"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 8582); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aLoadState->LoadType() == LOAD_LINK || aLoadState->LoadType() == LOAD_NORMAL_REPLACE"
")"); do { MOZ_CrashSequence(__null, 8582); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
8582 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"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 8582); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aLoadState->LoadType() == LOAD_LINK || aLoadState->LoadType() == LOAD_NORMAL_REPLACE"
")"); do { MOZ_CrashSequence(__null, 8582); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8583 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()"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 8583); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!aLoadState->LoadIsFromSessionHistory()"
")"); do { MOZ_CrashSequence(__null, 8583); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8584 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()"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 8584); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aLoadState->FirstParty()" ")"); do { MOZ_CrashSequence
(__null, 8584); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
; // Windowwatcher will assume this.
8585
8586 RefPtr<nsDocShellLoadState> loadState =
8587 new nsDocShellLoadState(aLoadState->URI());
8588
8589 // Set up our loadinfo so it will do the load as much like we would have
8590 // as possible.
8591 loadState->SetReferrerInfo(aLoadState->GetReferrerInfo());
8592 loadState->SetOriginalURI(aLoadState->OriginalURI());
8593
8594 Maybe<nsCOMPtr<nsIURI>> resultPrincipalURI;
8595 aLoadState->GetMaybeResultPrincipalURI(resultPrincipalURI);
8596
8597 loadState->SetMaybeResultPrincipalURI(resultPrincipalURI);
8598 loadState->SetKeepResultPrincipalURIIfSet(
8599 aLoadState->KeepResultPrincipalURIIfSet());
8600 // LoadReplace will always be false due to asserts above, skip setting
8601 // it.
8602 loadState->SetTriggeringPrincipal(aLoadState->TriggeringPrincipal());
8603 loadState->SetTriggeringSandboxFlags(
8604 aLoadState->TriggeringSandboxFlags());
8605 loadState->SetTriggeringWindowId(aLoadState->TriggeringWindowId());
8606 loadState->SetTriggeringStorageAccess(
8607 aLoadState->TriggeringStorageAccess());
8608 loadState->SetTriggeringClassificationFlags(
8609 aLoadState->TriggeringClassificationFlags());
8610 loadState->SetCsp(aLoadState->Csp());
8611 loadState->SetInheritPrincipal(aLoadState->HasInternalLoadFlags(
8612 INTERNAL_LOAD_FLAGS_INHERIT_PRINCIPAL));
8613 // Explicit principal because we do not want any guesses as to what the
8614 // principal to inherit is: it should be aTriggeringPrincipal.
8615 loadState->SetPrincipalIsExplicit(true);
8616 loadState->SetLoadType(aLoadState->LoadType());
8617 loadState->SetForceAllowDataURI(aLoadState->HasInternalLoadFlags(
8618 INTERNAL_LOAD_FLAGS_FORCE_ALLOW_DATA_URI));
8619
8620 loadState->SetHasValidUserGestureActivation(
8621 aLoadState->HasValidUserGestureActivation());
8622
8623 loadState->SetTextDirectiveUserActivation(
8624 aLoadState->GetTextDirectiveUserActivation());
8625
8626 // Propagate POST data to the new load.
8627 loadState->SetPostDataStream(aLoadState->PostDataStream());
8628 loadState->SetIsFormSubmission(aLoadState->IsFormSubmission());
8629
8630 rv = win->Open(spec,
8631 aLoadState->Target(), // window name
8632 u""_ns, // Features
8633 loadState,
8634 true, // aForceNoOpener
8635 getter_AddRefs(newBC));
8636 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", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 8636); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!newBC" ")"
); do { MOZ_CrashSequence(__null, 8636); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8637 return rv;
8638 }
8639
8640 rv = win->OpenNoNavigate(spec,
8641 aLoadState->Target(), // window name
8642 u""_ns, // Features
8643 getter_AddRefs(newBC));
8644
8645 // In some cases the Open call doesn't actually result in a new
8646 // window being opened. We can detect these cases by examining the
8647 // document in |newBC|, if any.
8648 nsCOMPtr<nsPIDOMWindowOuter> piNewWin =
8649 newBC ? newBC->GetDOMWindow() : nullptr;
8650 if (piNewWin) {
8651 RefPtr<Document> newDoc = piNewWin->GetExtantDoc();
8652 if (!newDoc || newDoc->IsInitialDocument()) {
8653 aLoadState->SetInternalLoadFlag(INTERNAL_LOAD_FLAGS_FIRST_LOAD);
8654 }
8655 }
8656
8657 if (newBC) {
8658 targetContext = newBC;
8659 }
8660 }
8661 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, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 8661); return rv; } } while (false)
;
8662 NS_ENSURE_TRUE(targetContext, rv)do { if ((__builtin_expect(!!(!(targetContext)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "targetContext" ") failed"
, nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 8662); return rv; } } while (false)
;
8663
8664 // If our target BrowsingContext is still pending initialization, ignore the
8665 // navigation request targeting it.
8666 if (NS_WARN_IF(targetContext->GetPendingInitialization())NS_warn_if_impl(targetContext->GetPendingInitialization(),
"targetContext->GetPendingInitialization()", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 8666)
) {
8667 return NS_OK;
8668 }
8669
8670 aLoadState->SetTargetBrowsingContext(targetContext);
8671 if (aLoadState->IsFormSubmission()) {
8672 aLoadState->SetLoadType(
8673 GetLoadTypeForFormSubmission(targetContext, aLoadState));
8674 }
8675
8676 //
8677 // Transfer the load to the target BrowsingContext... Clear the window target
8678 // name to the empty string to prevent recursive retargeting!
8679 //
8680 // No window target
8681 aLoadState->SetTarget(u""_ns);
8682 // No forced download
8683 aLoadState->SetFileName(VoidString());
8684 return targetContext->InternalLoad(aLoadState);
8685}
8686
8687static nsAutoCString RefMaybeNull(nsIURI* aURI) {
8688 nsAutoCString result;
8689 if (NS_FAILED(aURI->GetRef(result))((bool)(__builtin_expect(!!(NS_FAILED_impl(aURI->GetRef(result
))), 0)))
) {
8690 result.SetIsVoid(true);
8691 }
8692 return result;
8693}
8694
8695uint32_t nsDocShell::GetSameDocumentNavigationFlags(nsIURI* aNewURI) {
8696 uint32_t flags = LOCATION_CHANGE_SAME_DOCUMENT;
8697
8698 bool equal = false;
8699 if (mCurrentURI &&
8700 NS_SUCCEEDED(mCurrentURI->EqualsExceptRef(aNewURI, &equal))((bool)(__builtin_expect(!!(!NS_FAILED_impl(mCurrentURI->EqualsExceptRef
(aNewURI, &equal))), 1)))
&& equal &&
8701 RefMaybeNull(mCurrentURI) != RefMaybeNull(aNewURI)) {
8702 flags |= LOCATION_CHANGE_HASHCHANGE;
8703 }
8704
8705 return flags;
8706}
8707
8708struct SameDocumentNavigationState {
8709 nsAutoCString mCurrentHash;
8710 nsAutoCString mNewHash;
8711 nsTArray<TextDirective> mTextDirectives;
8712 bool mCurrentURIHasRef = false;
8713 bool mNewURIHasRef = false;
8714 bool mSameExceptHashes = false;
8715 bool mSecureUpgradeURI = false;
8716 bool mHistoryNavBetweenSameDoc = false;
8717};
8718
8719bool nsDocShell::IsSameDocumentNavigation(nsDocShellLoadState* aLoadState,
8720 SameDocumentNavigationState& aState) {
8721 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", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 8721); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState"
")"); do { MOZ_CrashSequence(__null, 8721); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8722 if (!(aLoadState->LoadType() == LOAD_NORMAL ||
8723 aLoadState->LoadType() == LOAD_STOP_CONTENT ||
8724 LOAD_TYPE_HAS_FLAGS(aLoadState->LoadType(),((aLoadState->LoadType()) & ((LOAD_FLAGS_REPLACE_HISTORY
) << 16))
8725 LOAD_FLAGS_REPLACE_HISTORY)((aLoadState->LoadType()) & ((LOAD_FLAGS_REPLACE_HISTORY
) << 16))
||
8726 aLoadState->LoadType() == LOAD_HISTORY ||
8727 aLoadState->LoadType() == LOAD_LINK)) {
8728 return false;
8729 }
8730
8731 nsCOMPtr<nsIURI> currentURI = mCurrentURI;
8732
8733 nsresult rvURINew = aLoadState->URI()->GetRef(aState.mNewHash);
8734 if (NS_SUCCEEDED(rvURINew)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rvURINew)), 1)))) {
8735 rvURINew = aLoadState->URI()->GetHasRef(&aState.mNewURIHasRef);
8736 }
8737
8738 // A Fragment Directive must be removed from the new hash in order to allow
8739 // fallback element id scroll.
8740 FragmentDirective::ParseAndRemoveFragmentDirectiveFromFragmentString(
8741 aState.mNewHash, &aState.mTextDirectives, aLoadState->URI());
8742
8743 if (currentURI && NS_SUCCEEDED(rvURINew)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rvURINew)), 1)))) {
8744 nsresult rvURIOld = currentURI->GetRef(aState.mCurrentHash);
8745 if (NS_SUCCEEDED(rvURIOld)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rvURIOld)), 1)))) {
8746 rvURIOld = currentURI->GetHasRef(&aState.mCurrentURIHasRef);
8747 }
8748 if (NS_SUCCEEDED(rvURIOld)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rvURIOld)), 1)))) {
8749 if (NS_FAILED(currentURI->EqualsExceptRef(aLoadState->URI(),((bool)(__builtin_expect(!!(NS_FAILED_impl(currentURI->EqualsExceptRef
(aLoadState->URI(), &aState.mSameExceptHashes))), 0)))
8750 &aState.mSameExceptHashes))((bool)(__builtin_expect(!!(NS_FAILED_impl(currentURI->EqualsExceptRef
(aLoadState->URI(), &aState.mSameExceptHashes))), 0)))
) {
8751 aState.mSameExceptHashes = false;
8752 }
8753 }
8754 }
8755
8756 if (!aState.mSameExceptHashes && currentURI && NS_SUCCEEDED(rvURINew)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rvURINew)), 1)))) {
8757 // Maybe aLoadState->URI() came from the exposable form of currentURI?
8758 nsCOMPtr<nsIURI> currentExposableURI =
8759 nsIOService::CreateExposableURI(currentURI);
8760 nsresult rvURIOld = currentExposableURI->GetRef(aState.mCurrentHash);
8761 if (NS_SUCCEEDED(rvURIOld)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rvURIOld)), 1)))) {
8762 rvURIOld = currentExposableURI->GetHasRef(&aState.mCurrentURIHasRef);
8763 }
8764 if (NS_SUCCEEDED(rvURIOld)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rvURIOld)), 1)))) {
8765 if (NS_FAILED(currentExposableURI->EqualsExceptRef(((bool)(__builtin_expect(!!(NS_FAILED_impl(currentExposableURI
->EqualsExceptRef( aLoadState->URI(), &aState.mSameExceptHashes
))), 0)))
8766 aLoadState->URI(), &aState.mSameExceptHashes))((bool)(__builtin_expect(!!(NS_FAILED_impl(currentExposableURI
->EqualsExceptRef( aLoadState->URI(), &aState.mSameExceptHashes
))), 0)))
) {
8767 aState.mSameExceptHashes = false;
8768 }
8769 // HTTPS-Only Mode upgrades schemes from http to https in Necko, hence we
8770 // have to perform a special check here to avoid an actual navigation. If
8771 // HTTPS-Only Mode is enabled and the two URIs are same-origin (modulo the
8772 // fact that the new URI is currently http), then set mSameExceptHashes to
8773 // true and only perform a fragment navigation.
8774 if (!aState.mSameExceptHashes) {
8775 if (nsCOMPtr<nsIChannel> docChannel = GetCurrentDocChannel()) {
8776 nsCOMPtr<nsILoadInfo> docLoadInfo = docChannel->LoadInfo();
8777 nsHTTPSOnlyUtils::UpgradeMode upgradeMode =
8778 nsHTTPSOnlyUtils::GetUpgradeMode(docLoadInfo);
8779 if (!docLoadInfo->GetLoadErrorPage() &&
8780 (upgradeMode == nsHTTPSOnlyUtils::HTTPS_ONLY_MODE ||
8781 upgradeMode == nsHTTPSOnlyUtils::HTTPS_FIRST_MODE) &&
8782 nsHTTPSOnlyUtils::IsHttpDowngrade(currentExposableURI,
8783 aLoadState->URI())) {
8784 uint32_t status = docLoadInfo->GetHttpsOnlyStatus();
8785 if ((status &
8786 (nsILoadInfo::HTTPS_ONLY_UPGRADED_LISTENER_REGISTERED |
8787 nsILoadInfo::HTTPS_ONLY_UPGRADED_HTTPS_FIRST)) &&
8788 !(status & nsILoadInfo::HTTPS_ONLY_EXEMPT)) {
8789 // At this point the requested URI is for sure a fragment
8790 // navigation via HTTP and HTTPS-Only mode or HTTPS-First is
8791 // enabled. Also it is not interfering the upgrade order of
8792 // https://searchfox.org/mozilla-central/source/netwerk/base/nsNetUtil.cpp#2948-2953.
8793 // Since we are on an HTTPS site the fragment
8794 // navigation should also be an HTTPS.
8795 // For that reason we should upgrade the URI to HTTPS.
8796 aState.mSecureUpgradeURI = true;
8797 aState.mSameExceptHashes = true;
8798 }
8799 }
8800 }
8801 }
8802 }
8803 }
8804
8805 if (mozilla::SessionHistoryInParent()) {
8806 if (mActiveEntry && aLoadState->LoadIsFromSessionHistory()) {
8807 aState.mHistoryNavBetweenSameDoc = mActiveEntry->SharesDocumentWith(
8808 aLoadState->GetLoadingSessionHistoryInfo()->mInfo);
8809 }
8810 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)
8811 ("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)
8812 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)
;
8813 } else {
8814 if (mOSHE && aLoadState->LoadIsFromSessionHistory()) {
8815 // We're doing a history load.
8816
8817 mOSHE->SharesDocumentWith(aLoadState->SHEntry(),
8818 &aState.mHistoryNavBetweenSameDoc);
8819 }
8820 }
8821
8822 // A same document navigation happens when we navigate between two SHEntries
8823 // for the same document. We do a same document navigation under two
8824 // circumstances. Either
8825 //
8826 // a) we're navigating between two different SHEntries which share a
8827 // document, or
8828 //
8829 // b) we're navigating to a new shentry whose URI differs from the
8830 // current URI only in its hash, the new hash is non-empty, and
8831 // we're not doing a POST.
8832 //
8833 // The restriction that the SHEntries in (a) must be different ensures
8834 // that history.go(0) and the like trigger full refreshes, rather than
8835 // same document navigations.
8836 if (!mozilla::SessionHistoryInParent()) {
8837 bool doSameDocumentNavigation =
8838 (aState.mHistoryNavBetweenSameDoc && mOSHE != aLoadState->SHEntry()) ||
8839 (!aLoadState->SHEntry() && !aLoadState->PostDataStream() &&
8840 aState.mSameExceptHashes && aState.mNewURIHasRef);
8841 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)
8842 ("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)
8843 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)
;
8844 return doSameDocumentNavigation;
8845 }
8846
8847 if (aState.mHistoryNavBetweenSameDoc &&
8848 !aLoadState->GetLoadingSessionHistoryInfo()->mLoadingCurrentEntry) {
8849 return true;
8850 }
8851
8852 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)
8853 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)
8854 ("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)
8855 "!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)
8856 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)
8857 !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)
8858 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)
8859 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)
;
8860 return !aLoadState->LoadIsFromSessionHistory() &&
8861 !aLoadState->PostDataStream() && aState.mSameExceptHashes &&
8862 aState.mNewURIHasRef;
8863}
8864
8865static bool IsSamePrincipalForDocumentURI(nsIPrincipal* aCurrentPrincipal,
8866 nsIURI* aCurrentURI,
8867 nsIURI* aNewURI) {
8868 if (!StaticPrefs::dom_security_setdocumenturi()) {
8869 return true;
8870 }
8871 nsCOMPtr<nsIURI> principalURI = aCurrentPrincipal->GetURI();
8872 if (aCurrentPrincipal->GetIsNullPrincipal()) {
8873 nsCOMPtr<nsIPrincipal> precursor =
8874 aCurrentPrincipal->GetPrecursorPrincipal();
8875 if (precursor) {
8876 principalURI = precursor->GetURI();
8877 }
8878 }
8879
8880 return !nsScriptSecurityManager::IsHttpOrHttpsAndCrossOrigin(principalURI,
8881 aNewURI) &&
8882 !nsScriptSecurityManager::IsHttpOrHttpsAndCrossOrigin(principalURI,
8883 aCurrentURI) &&
8884 !nsScriptSecurityManager::IsHttpOrHttpsAndCrossOrigin(aCurrentURI,
8885 aNewURI);
8886}
8887
8888nsresult nsDocShell::HandleSameDocumentNavigation(
8889 nsDocShellLoadState* aLoadState, SameDocumentNavigationState& aState,
8890 bool& aSameDocument) {
8891 aSameDocument = true;
8892#ifdef DEBUG1
8893 SameDocumentNavigationState state;
8894 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)"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 8894); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "IsSameDocumentNavigation(aLoadState, state)"
")"); do { MOZ_CrashSequence(__null, 8894); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8895#endif
8896
8897 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)
8898 ("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)
8899 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)
8900 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)
;
8901
8902 RefPtr<Document> doc = GetDocument();
8903 NS_ENSURE_TRUE(doc, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(doc)), 0))) { NS_DebugBreak(NS_DEBUG_WARNING
, "NS_ENSURE_TRUE(" "doc" ") failed", nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 8903); return NS_ERROR_FAILURE; } } while (false)
;
8904
8905 nsCOMPtr<nsIURI> currentURI = mCurrentURI;
8906
8907 // We need to upgrade the new URI from http: to https:
8908 nsCOMPtr<nsIURI> newURI = aLoadState->URI();
8909 if (aState.mSecureUpgradeURI) {
8910 MOZ_TRY(NS_GetSecureUpgradedURI(aLoadState->URI(), getter_AddRefs(newURI)))__extension__({ auto mozTryVarTempResult = ::mozilla::ToResult
(NS_GetSecureUpgradedURI(aLoadState->URI(), getter_AddRefs
(newURI))); if ((__builtin_expect(!!(mozTryVarTempResult.isErr
()), 0))) { return mozTryVarTempResult.propagateErr(); } mozTryVarTempResult
.unwrap(); })
;
8911 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)
8912 ("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)
;
8913 }
8914
8915 // check if documentPrincipal, mCurrentURI, and aLoadState->URI() are same
8916 // origin skip handling otherwise
8917 if (!IsSamePrincipalForDocumentURI(doc->NodePrincipal(), mCurrentURI,
8918 newURI)) {
8919 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)
8920 ("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)
8921 "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)
8922 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)
;
8923 return NS_OK;
8924 }
8925
8926 if (nsCOMPtr<nsPIDOMWindowInner> window = doc->GetInnerWindow()) {
8927 // https://html.spec.whatwg.org/#navigate-fragid
8928 // Step 1
8929 if (RefPtr<Navigation> navigation = window->Navigation()) {
8930 // Step 2
8931 RefPtr<nsIStructuredCloneContainer> destinationNavigationAPIState =
8932 mActiveEntry ? mActiveEntry->GetNavigationState() : nullptr;
8933 // Step 3
8934 if (aLoadState->GetNavigationAPIState()) {
8935 destinationNavigationAPIState = aLoadState->GetNavigationAPIState();
8936 }
8937
8938 AutoJSAPI jsapi;
8939 if (jsapi.Init(window)) {
8940 RefPtr<Element> sourceElement = aLoadState->GetSourceElement();
8941 // Step 4
8942 bool shouldContinue = navigation->FirePushReplaceReloadNavigateEvent(
8943 jsapi.cx(), aLoadState->GetNavigationType(), newURI,
8944 /* aIsSameDocument */ true, /* aIsSync */ true,
8945 Some(aLoadState->UserNavigationInvolvement()), sourceElement,
8946 /* aFormDataEntryList */ nullptr,
8947 /* aNavigationAPIState */ destinationNavigationAPIState,
8948 /* aClassicHistoryAPIState */ nullptr);
8949
8950 // Step 5
8951 if (!shouldContinue) {
8952 return NS_OK;
8953 }
8954 }
8955 }
8956 }
8957
8958 doc->DoNotifyPossibleTitleChange();
8959
8960 // Store the pending uninvoked directives if it is a same document
8961 // navigation. We need to set it here, in case the navigation happens before
8962 // the document has actually finished loading.
8963 doc->FragmentDirective()->SetTextDirectives(
8964 std::move(aState.mTextDirectives));
8965
8966#ifdef DEBUG1
8967 if (aState.mSameExceptHashes) {
8968 bool sameExceptHashes = false;
8969 currentURI->EqualsExceptRef(newURI, &sameExceptHashes);
8970 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"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 8970); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "sameExceptHashes" ")"); do { MOZ_CrashSequence
(__null, 8970); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
8971 }
8972#endif
8973 const nsCOMPtr<nsILoadInfo> loadInfo =
8974 doc->GetChannel() ? doc->GetChannel()->LoadInfo() : nullptr;
8975 if (loadInfo) {
8976 loadInfo->SetIsSameDocumentNavigation(true);
8977 }
8978 // Save the position of the scrollers.
8979 nsPoint scrollPos = GetCurScrollPos();
8980
8981 // Reset mLoadType to its original value once we exit this block, because this
8982 // same document navigation might have started after a normal, network load,
8983 // and we don't want to clobber its load type. See bug 737307.
8984 Maybe<AutoRestore<uint32_t>> loadTypeResetter;
8985 if (StaticPrefs::
8986 docshell_shistory_sameDocumentNavigationOverridesLoadType() &&
8987 !doc->NodePrincipal()->IsURIInPrefList(
8988 "docshell.shistory.sameDocumentNavigationOverridesLoadType."
8989 "forceDisable")) {
8990 loadTypeResetter.emplace(mLoadType);
8991 }
8992 if (JustStartedNetworkLoad() && !loadTypeResetter.isSome()) {
8993 loadTypeResetter.emplace(mLoadType);
8994 }
8995
8996 // If a non-same-document-navigation (i.e., a network load) is pending, make
8997 // this a replacement load, so that we don't add a SHEntry here and the
8998 // network load goes into the SHEntry it expects to.
8999 if (JustStartedNetworkLoad() && (aLoadState->LoadType() & LOAD_CMD_NORMAL)) {
9000 mLoadType = LOAD_NORMAL_REPLACE;
9001 } else {
9002 mLoadType = aLoadState->LoadType();
9003 }
9004
9005 mURIResultedInDocument = true;
9006
9007 nsCOMPtr<nsISHEntry> oldLSHE = mLSHE;
9008
9009 // we need to assign aLoadState->SHEntry() to mLSHE right here, so that on
9010 // History loads, SetCurrentURI() called from OnNewURI() will send proper
9011 // onLocationChange() notifications to the browser to update back/forward
9012 // buttons.
9013 SetHistoryEntryAndUpdateBC(Some<nsISHEntry*>(aLoadState->SHEntry()),
9014 Nothing());
9015 UniquePtr<mozilla::dom::LoadingSessionHistoryInfo> oldLoadingEntry;
9016 mLoadingEntry.swap(oldLoadingEntry);
9017 if (aLoadState->GetLoadingSessionHistoryInfo()) {
9018 mLoadingEntry = MakeUnique<LoadingSessionHistoryInfo>(
9019 *aLoadState->GetLoadingSessionHistoryInfo());
9020 mNeedToReportActiveAfterLoadingBecomesActive = false;
9021 }
9022
9023 // Set the doc's URI according to the new history entry's URI.
9024 doc->SetDocumentURI(newURI);
9025
9026 /* This is a anchor traversal within the same page.
9027 * call OnNewURI() so that, this traversal will be
9028 * recorded in session and global history.
9029 */
9030 nsCOMPtr<nsIPrincipal> newURITriggeringPrincipal, newURIPrincipalToInherit,
9031 newURIPartitionedPrincipalToInherit;
9032 nsCOMPtr<nsIContentSecurityPolicy> newCsp;
9033 if (mozilla::SessionHistoryInParent() ? !!mActiveEntry : !!mOSHE) {
9034 if (mozilla::SessionHistoryInParent()) {
9035 newURITriggeringPrincipal = mActiveEntry->GetTriggeringPrincipal();
9036 newURIPrincipalToInherit = mActiveEntry->GetPrincipalToInherit();
9037 newURIPartitionedPrincipalToInherit =
9038 mActiveEntry->GetPartitionedPrincipalToInherit();
9039 newCsp = mActiveEntry->GetCsp();
9040 } else {
9041 newURITriggeringPrincipal = mOSHE->GetTriggeringPrincipal();
9042 newURIPrincipalToInherit = mOSHE->GetPrincipalToInherit();
9043 newURIPartitionedPrincipalToInherit =
9044 mOSHE->GetPartitionedPrincipalToInherit();
9045 newCsp = mOSHE->GetCsp();
9046 }
9047 } else {
9048 newURITriggeringPrincipal = aLoadState->TriggeringPrincipal();
9049 newURIPrincipalToInherit = doc->NodePrincipal();
9050 newURIPartitionedPrincipalToInherit = doc->PartitionedPrincipal();
9051 newCsp = doc->GetCsp();
9052 }
9053
9054 uint32_t locationChangeFlags = GetSameDocumentNavigationFlags(newURI);
9055
9056 // Pass true for aCloneSHChildren, since we're not
9057 // changing documents here, so all of our subframes are
9058 // still relevant to the new session history entry.
9059 //
9060 // It also makes OnNewURI(...) set LOCATION_CHANGE_SAME_DOCUMENT
9061 // flag on firing onLocationChange(...).
9062 // Anyway, aCloneSHChildren param is simply reflecting
9063 // doSameDocumentNavigation in this scope.
9064 //
9065 // Note: we'll actually fire onLocationChange later, in order to preserve
9066 // ordering of HistoryCommit() in the parent vs onLocationChange (bug
9067 // 1668126)
9068 bool locationChangeNeeded = OnNewURI(
9069 newURI, nullptr, newURITriggeringPrincipal, newURIPrincipalToInherit,
9070 newURIPartitionedPrincipalToInherit, newCsp, true, true);
9071
9072 nsCOMPtr<nsIInputStream> postData;
9073 nsCOMPtr<nsIReferrerInfo> referrerInfo;
9074 uint32_t cacheKey = 0;
9075
9076 bool scrollRestorationIsManual = false;
9077 if (!mozilla::SessionHistoryInParent()) {
9078 if (mOSHE) {
9079 /* save current position of scroller(s) (bug 59774) */
9080 mOSHE->SetScrollPosition(scrollPos.x, scrollPos.y);
9081 scrollRestorationIsManual = mOSHE->GetScrollRestorationIsManual();
9082 // Get the postdata, page ident and referrer info from the current page,
9083 // if the new load is being done via normal means. Note that "normal
9084 // means" can be checked for just by checking for LOAD_CMD_NORMAL, given
9085 // the loadType and allowScroll check above -- it filters out some
9086 // LOAD_CMD_NORMAL cases that we wouldn't want here.
9087 if (aLoadState->LoadType() & LOAD_CMD_NORMAL) {
9088 postData = mOSHE->GetPostData();
9089 cacheKey = mOSHE->GetCacheKey();
9090 referrerInfo = mOSHE->GetReferrerInfo();
9091 }
9092
9093 // Link our new SHEntry to the old SHEntry's back/forward
9094 // cache data, since the two SHEntries correspond to the
9095 // same document.
9096 if (mLSHE) {
9097 if (!aLoadState->LoadIsFromSessionHistory()) {
9098 // If we're not doing a history load, scroll restoration
9099 // should be inherited from the previous session history entry.
9100 SetScrollRestorationIsManualOnHistoryEntry(mLSHE,
9101 scrollRestorationIsManual);
9102 }
9103 mLSHE->AdoptBFCacheEntry(mOSHE);
9104 }
9105 }
9106 } else {
9107 if (mActiveEntry) {
9108 mActiveEntry->SetScrollPosition(scrollPos.x, scrollPos.y);
9109 if (mBrowsingContext) {
9110 CollectWireframe();
9111 if (XRE_IsParentProcess()) {
9112 SessionHistoryEntry* entry =
9113 mBrowsingContext->Canonical()->GetActiveSessionHistoryEntry();
9114 if (entry) {
9115 entry->SetScrollPosition(scrollPos.x, scrollPos.y);
9116 }
9117 } else {
9118 mozilla::Unused << ContentChild::GetSingleton()
9119 ->SendSessionHistoryEntryScrollPosition(
9120 mBrowsingContext, scrollPos.x,
9121 scrollPos.y);
9122 }
9123 }
9124 }
9125 if (mLoadingEntry) {
9126 if (!mLoadingEntry->mLoadIsFromSessionHistory) {
9127 // If we're not doing a history load, scroll restoration
9128 // should be inherited from the previous session history entry.
9129 // XXX This needs most probably tweaks once fragment navigation is
9130 // fixed to work with session-history-in-parent.
9131 SetScrollRestorationIsManualOnHistoryEntry(nullptr,
9132 scrollRestorationIsManual);
9133 }
9134 }
9135 }
9136
9137 // If we're doing a history load, use its scroll restoration state.
9138 if (aLoadState->LoadIsFromSessionHistory()) {
9139 if (mozilla::SessionHistoryInParent()) {
9140 scrollRestorationIsManual = aLoadState->GetLoadingSessionHistoryInfo()
9141 ->mInfo.GetScrollRestorationIsManual();
9142 } else {
9143 scrollRestorationIsManual =
9144 aLoadState->SHEntry()->GetScrollRestorationIsManual();
9145 }
9146 }
9147
9148 /* Assign mLSHE to mOSHE. This will either be a new entry created
9149 * by OnNewURI() for normal loads or aLoadState->SHEntry() for history
9150 * loads.
9151 */
9152 if (!mozilla::SessionHistoryInParent()) {
9153 if (mLSHE) {
9154 SetHistoryEntryAndUpdateBC(Nothing(), Some<nsISHEntry*>(mLSHE));
9155 // Save the postData obtained from the previous page
9156 // in to the session history entry created for the
9157 // anchor page, so that any history load of the anchor
9158 // page will restore the appropriate postData.
9159 if (postData) {
9160 mOSHE->SetPostData(postData);
9161 }
9162
9163 // Make sure we won't just repost without hitting the
9164 // cache first
9165 if (cacheKey != 0) {
9166 mOSHE->SetCacheKey(cacheKey);
9167 }
9168
9169 // As the document has not changed, the referrer info hasn't changed too,
9170 // so we can just copy it over.
9171 if (referrerInfo) {
9172 mOSHE->SetReferrerInfo(referrerInfo);
9173 }
9174 }
9175
9176 /* Set the title for the SH entry for this target url so that
9177 * SH menus in go/back/forward buttons won't be empty for this.
9178 * Note, this happens on mOSHE (and mActiveEntry in the future) because of
9179 * the code above.
9180 * Note, when session history lives in the parent process, this does not
9181 * update the title there.
9182 */
9183 SetTitleOnHistoryEntry(false);
9184 } else {
9185 if (aLoadState->LoadIsFromSessionHistory()) {
9186 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)
9187 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)
9188 ("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)
9189 "%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)
9190 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)
;
9191
9192 nsCOMPtr<nsILayoutHistoryState> currentLayoutHistoryState;
9193 if (mActiveEntry) {
9194 currentLayoutHistoryState = mActiveEntry->GetLayoutHistoryState();
9195 }
9196
9197 UniquePtr<SessionHistoryInfo> previousActiveEntry(mActiveEntry.release());
9198 mActiveEntry = MakeUnique<SessionHistoryInfo>(mLoadingEntry->mInfo);
9199 if (currentLayoutHistoryState) {
9200 // Restore the existing nsILayoutHistoryState object, since it is
9201 // possibly being used by the layout. When doing a new load, the
9202 // shared state is copied from the existing active entry, so this
9203 // special case is needed only with the history loads.
9204 mActiveEntry->SetLayoutHistoryState(currentLayoutHistoryState);
9205 }
9206
9207 if (cacheKey != 0) {
9208 mActiveEntry->SetCacheKey(cacheKey);
9209 }
9210
9211 mActiveEntry->SetPartitionedPrincipalToInherit(
9212 doc->PartitionedPrincipal());
9213 // We're passing in mCurrentURI, which could be null. SessionHistoryCommit
9214 // does require a non-null uri if this is for a refresh load of the same
9215 // URI, but in that case mCurrentURI won't be null here.
9216 mBrowsingContext->SessionHistoryCommit(
9217 *mLoadingEntry, mLoadType, mCurrentURI, previousActiveEntry.get(),
9218 true,
9219 /* No expiration update on the same document loads*/
9220 false, cacheKey, doc->PartitionedPrincipal());
9221 // FIXME Need to set postdata.
9222
9223 // Set the title for the SH entry for this target url so that
9224 // SH menus in go/back/forward buttons won't be empty for this.
9225 // Note, when session history lives in the parent process, this does not
9226 // update the title there.
9227 SetTitleOnHistoryEntry(false);
9228 } else {
9229 Maybe<bool> scrollRestorationIsManual;
9230 if (mActiveEntry) {
9231 scrollRestorationIsManual.emplace(
9232 mActiveEntry->GetScrollRestorationIsManual());
9233
9234 // Get the postdata, page ident and referrer info from the current page,
9235 // if the new load is being done via normal means. Note that "normal
9236 // means" can be checked for just by checking for LOAD_CMD_NORMAL, given
9237 // the loadType and allowScroll check above -- it filters out some
9238 // LOAD_CMD_NORMAL cases that we wouldn't want here.
9239 if (aLoadState->LoadType() & LOAD_CMD_NORMAL) {
9240 postData = mActiveEntry->GetPostData();
9241 cacheKey = mActiveEntry->GetCacheKey();
9242 referrerInfo = mActiveEntry->GetReferrerInfo();
9243 }
9244 }
9245
9246 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)
9247 ("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)
9248 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)
;
9249 UniquePtr<SessionHistoryInfo> previousActiveEntry(mActiveEntry.release());
9250 if (previousActiveEntry) {
9251 mActiveEntry =
9252 MakeUnique<SessionHistoryInfo>(*previousActiveEntry, newURI);
9253 } else {
9254 mActiveEntry = MakeUnique<SessionHistoryInfo>(
9255 newURI, newURITriggeringPrincipal, newURIPrincipalToInherit,
9256 newURIPartitionedPrincipalToInherit, newCsp, mContentTypeHint);
9257 }
9258
9259 // Save the postData obtained from the previous page in to the session
9260 // history entry created for the anchor page, so that any history load of
9261 // the anchor page will restore the appropriate postData.
9262 if (postData) {
9263 mActiveEntry->SetPostData(postData);
9264 }
9265
9266 // Make sure we won't just repost without hitting the
9267 // cache first
9268 if (cacheKey != 0) {
9269 mActiveEntry->SetCacheKey(cacheKey);
9270 }
9271
9272 // As the document has not changed, the referrer info hasn't changed too,
9273 // so we can just copy it over.
9274 if (referrerInfo) {
9275 mActiveEntry->SetReferrerInfo(referrerInfo);
9276 }
9277
9278 // Set the title for the SH entry for this target url so that
9279 // SH menus in go/back/forward buttons won't be empty for this.
9280 mActiveEntry->SetTitle(mTitle);
9281
9282 mActiveEntry->SetPartitionedPrincipalToInherit(
9283 doc->PartitionedPrincipal());
9284
9285 if (scrollRestorationIsManual.isSome()) {
9286 mActiveEntry->SetScrollRestorationIsManual(
9287 scrollRestorationIsManual.value());
9288 }
9289
9290 if (LOAD_TYPE_HAS_FLAGS(mLoadType, LOAD_FLAGS_REPLACE_HISTORY)((mLoadType) & ((LOAD_FLAGS_REPLACE_HISTORY) << 16)
)
) {
9291 mBrowsingContext->ReplaceActiveSessionHistoryEntry(mActiveEntry.get());
9292 } else {
9293 mBrowsingContext->IncrementHistoryEntryCountForBrowsingContext();
9294 // FIXME We should probably just compute mChildOffset in the parent
9295 // instead of passing it over IPC here.
9296 mBrowsingContext->SetActiveSessionHistoryEntry(
9297 Some(scrollPos), mActiveEntry.get(), previousActiveEntry.get(),
9298 mLoadType, cacheKey);
9299 // FIXME Do we need to update mPreviousEntryIndex and mLoadedEntryIndex?
9300 }
9301 }
9302 }
9303
9304 if (locationChangeNeeded) {
9305 FireOnLocationChange(this, nullptr, newURI, locationChangeFlags);
9306 }
9307
9308 /* Restore the original LSHE if we were loading something
9309 * while same document navigation was initiated.
9310 */
9311 SetHistoryEntryAndUpdateBC(Some<nsISHEntry*>(oldLSHE), Nothing());
9312 mLoadingEntry.swap(oldLoadingEntry);
9313
9314 /* Set the title for the Global History entry for this anchor url.
9315 */
9316 UpdateGlobalHistoryTitle(newURI);
9317
9318 SetDocCurrentStateObj(mOSHE, mActiveEntry.get());
9319
9320 // Inform the favicon service that the favicon for oldURI also
9321 // applies to newURI.
9322 CopyFavicon(currentURI, newURI, UsePrivateBrowsing());
9323
9324 RefPtr<nsGlobalWindowOuter> scriptGlobal = mScriptGlobal;
9325 nsCOMPtr<nsPIDOMWindowInner> win =
9326 scriptGlobal ? scriptGlobal->GetCurrentInnerWindow() : nullptr;
9327
9328 // The check for uninvoked directives must come before ScrollToAnchor() is
9329 // called.
9330 const bool hasTextDirectives =
9331 doc->FragmentDirective()->HasUninvokedDirectives();
9332
9333 // ScrollToAnchor doesn't necessarily cause us to scroll the window;
9334 // the function decides whether a scroll is appropriate based on the
9335 // arguments it receives. But even if we don't end up scrolling,
9336 // ScrollToAnchor performs other important tasks, such as informing
9337 // the presShell that we have a new hash. See bug 680257.
9338 nsresult rv = ScrollToAnchor(aState.mCurrentURIHasRef, aState.mNewURIHasRef,
9339 aState.mNewHash, aLoadState->LoadType());
9340 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, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 9340); return rv; } } while (false)
;
9341
9342 /* restore previous position of scroller(s), if we're moving
9343 * back in history (bug 59774)
9344 */
9345 nscoord bx = 0;
9346 nscoord by = 0;
9347 bool needsScrollPosUpdate = false;
9348 if ((mozilla::SessionHistoryInParent() ? !!mActiveEntry : !!mOSHE) &&
9349 (aLoadState->LoadType() == LOAD_HISTORY ||
9350 aLoadState->LoadType() == LOAD_RELOAD_NORMAL) &&
9351 !scrollRestorationIsManual) {
9352 needsScrollPosUpdate = true;
9353 if (mozilla::SessionHistoryInParent()) {
9354 mActiveEntry->GetScrollPosition(&bx, &by);
9355 } else {
9356 mOSHE->GetScrollPosition(&bx, &by);
9357 }
9358 }
9359
9360 // Dispatch the popstate and hashchange events, as appropriate.
9361 //
9362 // The event dispatch below can cause us to re-enter script and
9363 // destroy the docshell, nulling out mScriptGlobal. Hold a stack
9364 // reference to avoid null derefs. See bug 914521.
9365 if (win) {
9366 if (RefPtr navigation = win->Navigation()) {
9367 MOZ_LOG(gNavigationLog, LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = gNavigationLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "nsDocShell %p triggering a navigation event from "
"HandleSameDocumentNavigation", this); } } while (0)
9368 ("nsDocShell %p triggering a navigation event from "do { const ::mozilla::LogModule* moz_real_module = gNavigationLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "nsDocShell %p triggering a navigation event from "
"HandleSameDocumentNavigation", this); } } while (0)
9369 "HandleSameDocumentNavigation",do { const ::mozilla::LogModule* moz_real_module = gNavigationLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "nsDocShell %p triggering a navigation event from "
"HandleSameDocumentNavigation", this); } } while (0)
9370 this))do { const ::mozilla::LogModule* moz_real_module = gNavigationLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "nsDocShell %p triggering a navigation event from "
"HandleSameDocumentNavigation", this); } } while (0)
;
9371 // Corresponds to step 6.4.2 from the Updating the document algorithm:
9372 // https://html.spec.whatwg.org/multipage/browsing-the-web.html#updating-the-document
9373 navigation->UpdateEntriesForSameDocumentNavigation(
9374 mActiveEntry.get(),
9375 LOAD_TYPE_HAS_FLAGS(mLoadType, LOAD_FLAGS_REPLACE_HISTORY)((mLoadType) & ((LOAD_FLAGS_REPLACE_HISTORY) << 16)
)
9376 ? NavigationType::Replace
9377 : aLoadState->LoadIsFromSessionHistory() ? NavigationType::Traverse
9378 : NavigationType::Push);
9379 }
9380
9381 // Fire a hashchange event URIs differ, and only in their hashes.
9382 // If the fragment contains a directive, compare hasRef.
9383 bool doHashchange = aState.mSameExceptHashes &&
9384 (!aState.mCurrentHash.Equals(aState.mNewHash) ||
9385 (hasTextDirectives &&
9386 aState.mCurrentURIHasRef != aState.mNewURIHasRef));
9387
9388 if (aState.mHistoryNavBetweenSameDoc || doHashchange) {
9389 win->DispatchSyncPopState();
9390 }
9391
9392 if (needsScrollPosUpdate && win->HasActiveDocument()) {
9393 SetCurScrollPosEx(bx, by);
9394 }
9395
9396 if (doHashchange) {
9397 // Note that currentURI hasn't changed because it's on the
9398 // stack, so we can just use it directly as the old URI.
9399 win->DispatchAsyncHashchange(currentURI, newURI);
9400 }
9401 }
9402
9403 return NS_OK;
9404}
9405
9406static bool NavigationShouldTakeFocus(nsDocShell* aDocShell,
9407 nsDocShellLoadState* aLoadState) {
9408 if (!aLoadState->AllowFocusMove()) {
9409 return false;
9410 }
9411 if (!aLoadState->HasValidUserGestureActivation()) {
9412 return false;
9413 }
9414 const auto& sourceBC = aLoadState->SourceBrowsingContext();
9415 if (!sourceBC || !sourceBC->IsActive()) {
9416 // If the navigation didn't come from a foreground tab, then we don't steal
9417 // focus.
9418 return false;
9419 }
9420 auto* bc = aDocShell->GetBrowsingContext();
9421 if (sourceBC.get() == bc) {
9422 // If it comes from the same tab / frame, don't steal focus either.
9423 return false;
9424 }
9425 auto* fm = nsFocusManager::GetFocusManager();
9426 if (fm && bc->IsActive() && fm->IsInActiveWindow(bc)) {
9427 // If we're already on the foreground tab of the foreground window, then we
9428 // don't need to do this. This helps to e.g. not steal focus from the
9429 // browser chrome unnecessarily.
9430 return false;
9431 }
9432 if (auto* doc = aDocShell->GetExtantDocument()) {
9433 if (doc->IsInitialDocument()) {
9434 // If we're the initial load for the browsing context, the browser
9435 // chrome determines what to focus. This is important because the
9436 // browser chrome may want to e.g focus the url-bar
9437 return false;
9438 }
9439 }
9440 // Take loadDivertedInBackground into account so the behavior would be the
9441 // same as how the tab first opened.
9442 return !Preferences::GetBool("browser.tabs.loadDivertedInBackground", false);
9443}
9444
9445uint32_t nsDocShell::GetLoadTypeForFormSubmission(
9446 BrowsingContext* aTargetBC, nsDocShellLoadState* aLoadState) {
9447 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()", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 9447); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->IsFormSubmission()"
")"); do { MOZ_CrashSequence(__null, 9447); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9448
9449 // https://html.spec.whatwg.org/#form-submission-algorithm
9450 // 22. Let historyHandling be "push".
9451 // 23. If form document equals targetNavigable's active document, and
9452 // form document has not yet completely loaded, then set
9453 // historyHandling to "replace".
9454 return GetBrowsingContext() == aTargetBC && !mEODForCurrentDocument
9455 ? LOAD_NORMAL_REPLACE
9456 : LOAD_LINK;
9457}
9458
9459// InternalLoad performs several of the steps from
9460// https://html.spec.whatwg.org/#navigate.
9461nsresult nsDocShell::InternalLoad(nsDocShellLoadState* aLoadState,
9462 Maybe<uint32_t> aCacheKey) {
9463 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!"
")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 9463
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState" ") ("
"need a load state!" ")"); do { MOZ_CrashSequence(__null, 9463
); __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
;
9464 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"
")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 9465
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->TriggeringPrincipal()"
") (" "need a valid TriggeringPrincipal" ")"); do { MOZ_CrashSequence
(__null, 9465); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
9465 "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"
")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 9465
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->TriggeringPrincipal()"
") (" "need a valid TriggeringPrincipal" ")"); do { MOZ_CrashSequence
(__null, 9465); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
9466
9467 if (!aLoadState->TriggeringPrincipal()) {
9468 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"
")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 9468
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") (" "InternalLoad needs a valid triggeringPrincipal"
")"); do { MOZ_CrashSequence(__null, 9468); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9469 return NS_ERROR_FAILURE;
9470 }
9471 if (NS_WARN_IF(mBrowsingContext->GetPendingInitialization())NS_warn_if_impl(mBrowsingContext->GetPendingInitialization
(), "mBrowsingContext->GetPendingInitialization()", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 9471)
) {
9472 return NS_ERROR_NOT_AVAILABLE;
9473 }
9474
9475 const bool shouldTakeFocus = NavigationShouldTakeFocus(this, aLoadState);
9476
9477 mOriginalUriString.Truncate();
9478
9479 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)
9480 ("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)
9481 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)
;
9482
9483 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
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 9483); return
NS_ERROR_INVALID_ARG; } } while (false)
;
9484
9485 // Cancel loads coming from Docshells that are being destroyed.
9486 if (mIsBeingDestroyed) {
9487 return NS_ERROR_NOT_AVAILABLE;
9488 }
9489
9490 nsresult rv = EnsureScriptEnvironment();
9491 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
9492 return rv;
9493 }
9494
9495 // If we have a target to move to, do that now.
9496 if (!aLoadState->Target().IsEmpty()) {
9497 return PerformRetargeting(aLoadState);
9498 }
9499
9500 // This is the non-retargeting load path, we've already set the right loadtype
9501 // for form submissions in nsDocShell::OnLinkClickSync.
9502 if (aLoadState->TargetBrowsingContext().IsNull()) {
9503 aLoadState->SetTargetBrowsingContext(GetBrowsingContext());
9504 }
9505
9506 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" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 9508); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "aLoadState->TargetBrowsingContext() == GetBrowsingContext()"
") (" "Load must be targeting this BrowsingContext" ")"); do
{ MOZ_CrashSequence(__null, 9508); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
9507 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" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 9508); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "aLoadState->TargetBrowsingContext() == GetBrowsingContext()"
") (" "Load must be targeting this BrowsingContext" ")"); do
{ MOZ_CrashSequence(__null, 9508); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
9508 "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" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 9508); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "aLoadState->TargetBrowsingContext() == GetBrowsingContext()"
") (" "Load must be targeting this BrowsingContext" ")"); do
{ MOZ_CrashSequence(__null, 9508); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
9509
9510 MOZ_TRY(CheckDisallowedJavascriptLoad(aLoadState))__extension__({ auto mozTryVarTempResult = ::mozilla::ToResult
(CheckDisallowedJavascriptLoad(aLoadState)); if ((__builtin_expect
(!!(mozTryVarTempResult.isErr()), 0))) { return mozTryVarTempResult
.propagateErr(); } mozTryVarTempResult.unwrap(); })
;
9511
9512 // If we don't have a target, we're loading into ourselves, and our load
9513 // delegate may want to intercept that load.
9514 SameDocumentNavigationState sameDocumentNavigationState;
9515 bool sameDocument =
9516 IsSameDocumentNavigation(aLoadState, sameDocumentNavigationState) &&
9517 !aLoadState->GetPendingRedirectedChannel();
9518
9519 // Note: We do this check both here and in BrowsingContext::
9520 // LoadURI/InternalLoad, since document-specific sandbox flags are only
9521 // available in the process triggering the load, and we don't want the target
9522 // process to have to trust the triggering process to do the appropriate
9523 // checks for the BrowsingContext's sandbox flags.
9524 MOZ_TRY(mBrowsingContext->CheckSandboxFlags(aLoadState))__extension__({ auto mozTryVarTempResult = ::mozilla::ToResult
(mBrowsingContext->CheckSandboxFlags(aLoadState)); if ((__builtin_expect
(!!(mozTryVarTempResult.isErr()), 0))) { return mozTryVarTempResult
.propagateErr(); } mozTryVarTempResult.unwrap(); })
;
9525
9526 NS_ENSURE_STATE(!HasUnloadedParent())do { if ((__builtin_expect(!!(!(!HasUnloadedParent())), 0))) {
NS_DebugBreak(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "!HasUnloadedParent()"
") failed", nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 9526); return NS_ERROR_UNEXPECTED; } } while (false)
;
9527
9528 rv = CheckLoadingPermissions();
9529 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
9530 return rv;
9531 }
9532
9533 if (mFiredUnloadEvent) {
9534 if (IsOKToLoadURI(aLoadState->URI())) {
9535 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!"
")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 9536
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->Target().IsEmpty()"
") (" "Shouldn't have a window target here!" ")"); do { MOZ_CrashSequence
(__null, 9536); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
9536 "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!"
")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 9536
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->Target().IsEmpty()"
") (" "Shouldn't have a window target here!" ")"); do { MOZ_CrashSequence
(__null, 9536); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
9537
9538 // If this is a replace load, make whatever load triggered
9539 // the unload event also a replace load, so we don't
9540 // create extra history entries.
9541 if (LOAD_TYPE_HAS_FLAGS(aLoadState->LoadType(),((aLoadState->LoadType()) & ((LOAD_FLAGS_REPLACE_HISTORY
) << 16))
9542 LOAD_FLAGS_REPLACE_HISTORY)((aLoadState->LoadType()) & ((LOAD_FLAGS_REPLACE_HISTORY
) << 16))
) {
9543 mLoadType = LOAD_NORMAL_REPLACE;
9544 }
9545
9546 // Do this asynchronously
9547 nsCOMPtr<nsIRunnable> ev = new InternalLoadEvent(this, aLoadState);
9548 return Dispatch(ev.forget());
9549 }
9550
9551 // Just ignore this load attempt
9552 return NS_OK;
9553 }
9554
9555 // If we are loading a URI that should inherit a security context (basically
9556 // javascript: at this point), and the caller has said that principal
9557 // inheritance is allowed, there are a few possible cases:
9558 //
9559 // 1) We are provided with the principal to inherit. In that case, we just use
9560 // it.
9561 //
9562 // 2) The load is coming from some other application. In this case we don't
9563 // want to inherit from whatever document we have loaded now, since the
9564 // load is unrelated to it.
9565 //
9566 // 3) It's a load from our application, but does not provide an explicit
9567 // principal to inherit. In that case, we want to inherit the principal of
9568 // our current document, or of our parent document (if any) if we don't
9569 // have a current document.
9570 {
9571 bool inherits;
9572
9573 if (!aLoadState->HasLoadFlags(LOAD_FLAGS_FROM_EXTERNAL) &&
9574 !aLoadState->PrincipalToInherit() &&
9575 (aLoadState->HasInternalLoadFlags(
9576 INTERNAL_LOAD_FLAGS_INHERIT_PRINCIPAL)) &&
9577 NS_SUCCEEDED(nsContentUtils::URIInheritsSecurityContext(((bool)(__builtin_expect(!!(!NS_FAILED_impl(nsContentUtils::URIInheritsSecurityContext
( aLoadState->URI(), &inherits))), 1)))
9578 aLoadState->URI(), &inherits))((bool)(__builtin_expect(!!(!NS_FAILED_impl(nsContentUtils::URIInheritsSecurityContext
( aLoadState->URI(), &inherits))), 1)))
&&
9579 inherits) {
9580 aLoadState->SetPrincipalToInherit(GetInheritedPrincipal(true));
9581 }
9582 // If principalToInherit is still null (e.g. if some of the conditions of
9583 // were not satisfied), then no inheritance of any sort will happen: the
9584 // load will just get a principal based on the URI being loaded.
9585 }
9586
9587 // If this docshell is owned by a frameloader, make sure to cancel
9588 // possible frameloader initialization before loading a new page.
9589 nsCOMPtr<nsIDocShellTreeItem> parent = GetInProcessParentDocshell();
9590 if (parent) {
9591 RefPtr<Document> doc = parent->GetDocument();
9592 if (doc) {
9593 doc->TryCancelFrameLoaderInitialization(this);
9594 }
9595 }
9596
9597 // Before going any further vet loads initiated by external programs.
9598 if (aLoadState->HasLoadFlags(LOAD_FLAGS_FROM_EXTERNAL)) {
9599 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"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 9599); AnnotateMozCrashReason
("MOZ_DIAGNOSTIC_ASSERT" "(" "aLoadState->LoadType() == LOAD_NORMAL"
")"); do { MOZ_CrashSequence(__null, 9599); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9600
9601 // Disallow external chrome: loads targetted at content windows
9602 if (aLoadState->URI()->SchemeIs("chrome")) {
9603 NS_WARNING("blocked external chrome: url -- use '--chrome' option")NS_DebugBreak(NS_DEBUG_WARNING, "blocked external chrome: url -- use '--chrome' option"
, nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 9603)
;
9604 return NS_ERROR_FAILURE;
9605 }
9606
9607 // clear the decks to prevent context bleed-through (bug 298255)
9608 rv = CreateAboutBlankDocumentViewer(nullptr, nullptr, nullptr, nullptr,
9609 /* aIsInitialDocument */ false);
9610 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
9611 return NS_ERROR_FAILURE;
9612 }
9613 }
9614
9615 mAllowKeywordFixup = aLoadState->HasInternalLoadFlags(
9616 INTERNAL_LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP);
9617 mURIResultedInDocument = false; // reset the clock...
9618
9619 // If container is an iframe element and will lazy load element steps given
9620 // container returns true, then stop intersection-observing a lazy loading
9621 // element container and set container's lazy load resumption steps to null.
9622 if (IsSubframe()) {
9623 if (auto* iframe = HTMLIFrameElement::FromNodeOrNull(
9624 mBrowsingContext->GetEmbedderElement())) {
9625 // Per spec, reload doesn't cancel lazy loading iframes.
9626 if (!(aLoadState->LoadType() & LOAD_RELOAD_NORMAL)) {
9627 iframe->CancelLazyLoading(true /* aClearLazyLoadState */);
9628 }
9629 }
9630 }
9631
9632 // See if this is actually a load between two history entries for the same
9633 // document. If the process fails, or if we successfully navigate within the
9634 // same document, return.
9635 if (sameDocument) {
9636 nsresult rv = HandleSameDocumentNavigation(
9637 aLoadState, sameDocumentNavigationState, sameDocument);
9638 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, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 9638); return rv; } } while (false)
;
9639 if (shouldTakeFocus) {
9640 mBrowsingContext->Focus(CallerType::System, IgnoreErrors());
9641 }
9642 if (sameDocument) {
9643 return rv;
9644 }
9645 }
9646
9647 // mDocumentViewer->PermitUnload can destroy |this| docShell, which
9648 // causes the next call of CanSavePresentation to crash.
9649 // Hold onto |this| until we return, to prevent a crash from happening.
9650 // (bug#331040)
9651 nsCOMPtr<nsIDocShell> kungFuDeathGrip(this);
9652
9653 // Don't init timing for javascript:, since it generally doesn't
9654 // actually start a load or anything. If it does, we'll init
9655 // timing then, from OnStateChange.
9656
9657 // XXXbz mTiming should know what channel it's for, so we don't
9658 // need this hackery.
9659 const bool isJavaScript = aLoadState->URI()->SchemeIs("javascript");
9660 const bool isExternalProtocol =
9661 nsContentUtils::IsExternalProtocol(aLoadState->URI());
9662 const bool isDownload = !aLoadState->FileName().IsVoid();
9663 const bool toBeReset = !isJavaScript && MaybeInitTiming();
9664
9665 // FIXME(emilio): Should this be done by javascript: uris? What about external
9666 // protocols?
9667 if (mTiming && !isDownload) {
9668 mTiming->NotifyBeforeUnload();
9669 }
9670
9671 // The following steps are from https://html.spec.whatwg.org/#navigate
9672 // Step 19, and here we actually also perform step 2 from
9673 // #navigate-to-a-javascript:-url (step 20) where the ongoing navigation is
9674 // set to null.
9675 SetOngoingNavigation(isJavaScript ? Nothing()
9676 : Some(OngoingNavigation::NavigationID));
9677
9678 // Step 21
9679 if (RefPtr<Document> document = GetDocument();
9680 document &&
9681 aLoadState->UserNavigationInvolvement() !=
9682 UserNavigationInvolvement::BrowserUI &&
9683 !document->IsInitialDocument() &&
9684 !NS_IsAboutBlankAllowQueryAndFragment(document->GetDocumentURI()) &&
9685 NS_IsFetchScheme(aLoadState->URI()) &&
9686 document->NodePrincipal()->Subsumes(aLoadState->TriggeringPrincipal())) {
9687 if (nsCOMPtr<nsPIDOMWindowInner> window = document->GetInnerWindow()) {
9688 // Step 21.1
9689 if (RefPtr<Navigation> navigation = window->Navigation()) {
9690 AutoJSAPI jsapi;
9691 if (jsapi.Init(window)) {
9692 RefPtr<Element> sourceElement = aLoadState->GetSourceElement();
9693
9694 // Step 21.2
9695 RefPtr<FormData> formData = aLoadState->GetFormDataEntryList();
9696
9697 // Step 21.3
9698 RefPtr<nsIStructuredCloneContainer> navigationAPIStateForFiring =
9699 aLoadState->GetNavigationAPIState();
9700 if (!navigationAPIStateForFiring) {
9701 navigationAPIStateForFiring = nullptr;
9702 }
9703
9704 nsCOMPtr<nsIURI> destinationURL = aLoadState->URI();
9705 // Step 21.4
9706 bool shouldContinue = navigation->FirePushReplaceReloadNavigateEvent(
9707 jsapi.cx(), aLoadState->GetNavigationType(), destinationURL,
9708 /* aIsSameDocument */ false, /* aIsSync */ false,
9709 Some(aLoadState->UserNavigationInvolvement()), sourceElement,
9710 formData.forget(), navigationAPIStateForFiring,
9711 /* aClassicHistoryAPIState */ nullptr);
9712
9713 // Step 21.5
9714 if (!shouldContinue) {
9715 return NS_OK;
9716 }
9717 }
9718 }
9719 }
9720 }
9721
9722 // Check if the page doesn't want to be unloaded. The javascript:
9723 // protocol handler deals with this for javascript: URLs.
9724 // NOTE(emilio): As of this writing, other browsers fire beforeunload for
9725 // external protocols, so keep doing that even though they don't return data
9726 // and thus we won't really unload this...
9727 if (!isJavaScript && !isDownload &&
9728 !aLoadState->NotifiedBeforeUnloadListeners() && mDocumentViewer) {
9729 // Check if request is exempted from HTTPSOnlyMode and if https-first is
9730 // enabled, if so it means:
9731 // * https-first failed to upgrade request to https
9732 // * we already asked for permission to unload and the user accepted
9733 // otherwise we wouldn't be here.
9734 const bool isPrivateWin = GetOriginAttributes().IsPrivateBrowsing();
9735 const uint32_t loadType = aLoadState->LoadType();
9736
9737 // Check if request is a reload.
9738 const bool isHistoryOrReload =
9739 loadType == LOAD_RELOAD_NORMAL ||
9740 loadType == LOAD_RELOAD_BYPASS_CACHE ||
9741 loadType == LOAD_RELOAD_BYPASS_PROXY ||
9742 loadType == LOAD_RELOAD_BYPASS_PROXY_AND_CACHE ||
9743 loadType == LOAD_HISTORY;
9744
9745 // If it isn't a reload, the request already failed to be upgraded and
9746 // https-first is enabled then don't ask the user again for permission to
9747 // unload and just unload.
9748 bool okToUnload;
9749 if (!isHistoryOrReload && aLoadState->IsExemptFromHTTPSFirstMode() &&
9750 nsHTTPSOnlyUtils::GetUpgradeMode(isPrivateWin) ==
9751 nsHTTPSOnlyUtils::HTTPS_FIRST_MODE) {
9752 rv = mDocumentViewer->PermitUnload(
9753 nsIDocumentViewer::PermitUnloadAction::eDontPromptAndUnload,
9754 &okToUnload);
9755 } else {
9756 rv = mDocumentViewer->PermitUnload(&okToUnload);
9757 }
9758
9759 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && !okToUnload) {
9760 // The user chose not to unload the page, interrupt the
9761 // load.
9762 MaybeResetInitTiming(toBeReset);
9763 return NS_OK;
9764 }
9765 }
9766
9767 if (mTiming && !isDownload) {
9768 mTiming->NotifyUnloadAccepted(mCurrentURI);
9769 }
9770
9771 // In e10s, in the parent process, we refuse to load anything other than
9772 // "safe" resources that we ship or trust enough to give "special" URLs.
9773 // Similar check will be performed by the ParentProcessDocumentChannel if in
9774 // use.
9775 if (XRE_IsE10sParentProcess() &&
9776 !DocumentChannel::CanUseDocumentChannel(aLoadState->URI()) &&
9777 !CanLoadInParentProcess(aLoadState->URI())) {
9778 return NS_ERROR_FAILURE;
9779 }
9780
9781 // Whenever a top-level browsing context is navigated, the user agent MUST
9782 // lock the orientation of the document to the document's default
9783 // orientation. We don't explicitly check for a top-level browsing context
9784 // here because orientation is only set on top-level browsing contexts.
9785 if (mBrowsingContext->GetOrientationLock() != hal::ScreenOrientation::None) {
9786 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()", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 9786); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mBrowsingContext->IsTop()"
")"); do { MOZ_CrashSequence(__null, 9786); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9787 MOZ_ALWAYS_SUCCEEDS(do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(mBrowsingContext->SetOrientationLock(hal::ScreenOrientation
::None))), 1)))), 1))) { } else { do { do { } while (false); MOZ_ReportCrash
("" "NS_SUCCEEDED(mBrowsingContext->SetOrientationLock(hal::ScreenOrientation::None))"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 9788); AnnotateMozCrashReason
("MOZ_CRASH(" "NS_SUCCEEDED(mBrowsingContext->SetOrientationLock(hal::ScreenOrientation::None))"
")"); do { MOZ_CrashSequence(__null, 9788); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
9788 mBrowsingContext->SetOrientationLock(hal::ScreenOrientation::None))do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(mBrowsingContext->SetOrientationLock(hal::ScreenOrientation
::None))), 1)))), 1))) { } else { do { do { } while (false); MOZ_ReportCrash
("" "NS_SUCCEEDED(mBrowsingContext->SetOrientationLock(hal::ScreenOrientation::None))"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 9788); AnnotateMozCrashReason
("MOZ_CRASH(" "NS_SUCCEEDED(mBrowsingContext->SetOrientationLock(hal::ScreenOrientation::None))"
")"); do { MOZ_CrashSequence(__null, 9788); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
;
9789 if (mBrowsingContext->IsActive()) {
9790 ScreenOrientation::UpdateActiveOrientationLock(
9791 hal::ScreenOrientation::None);
9792 }
9793 }
9794
9795 // Check for saving the presentation here, before calling Stop().
9796 // This is necessary so that we can catch any pending requests.
9797 // Since the new request has not been created yet, we pass null for the
9798 // new request parameter.
9799 // Also pass nullptr for the document, since it doesn't affect the return
9800 // value for our purposes here.
9801 const bool savePresentation =
9802 CanSavePresentation(aLoadState->LoadType(), nullptr, nullptr,
9803 /* aReportBFCacheComboTelemetry */ true);
9804
9805 // nsDocShell::CanSavePresentation is for non-SHIP version only. Do a
9806 // separate check for SHIP so that we know if there are ongoing requests
9807 // before calling Stop() below.
9808 if (mozilla::SessionHistoryInParent()) {
9809 Document* document = GetDocument();
9810 uint32_t flags = 0;
9811 if (document && !document->CanSavePresentation(nullptr, flags, true)) {
9812 // This forces some flags into the WindowGlobalParent's mBFCacheStatus,
9813 // which we'll then use in CanonicalBrowsingContext::AllowedInBFCache,
9814 // and in particular we'll store BFCacheStatus::REQUEST if needed.
9815 // Also, we want to report all the flags to the parent process here (and
9816 // not just BFCacheStatus::NOT_ALLOWED), so that it can update the
9817 // telemetry data correctly.
9818 document->DisallowBFCaching(flags);
9819 }
9820 }
9821
9822 // Don't stop current network activity for javascript: URL's since they might
9823 // not result in any data, and thus nothing should be stopped in those cases.
9824 // In the case where they do result in data, the javascript: URL channel takes
9825 // care of stopping current network activity. Similarly, downloads don't
9826 // unload this document...
9827 if (!isJavaScript && !isDownload && !isExternalProtocol) {
9828 // Stop any current network activity.
9829 // Also stop content if this is a zombie doc. otherwise
9830 // the onload will be delayed by other loads initiated in the
9831 // background by the first document that
9832 // didn't fully load before the next load was initiated.
9833 // If not a zombie, don't stop content until data
9834 // starts arriving from the new URI...
9835 if ((mDocumentViewer && mDocumentViewer->GetPreviousViewer()) ||
9836 LOAD_TYPE_HAS_FLAGS(aLoadState->LoadType(), LOAD_FLAGS_STOP_CONTENT)((aLoadState->LoadType()) & ((LOAD_FLAGS_STOP_CONTENT)
<< 16))
) {
9837 rv = Stop(nsIWebNavigation::STOP_ALL);
9838 } else {
9839 rv = Stop(nsIWebNavigation::STOP_NETWORK);
9840 }
9841
9842 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
9843 return rv;
9844 }
9845 }
9846
9847 mLoadType = aLoadState->LoadType();
9848
9849 // aLoadState->SHEntry() should be assigned to mLSHE, only after Stop() has
9850 // been called. But when loading an error page, do not clear the
9851 // mLSHE for the real page.
9852 if (mLoadType != LOAD_ERROR_PAGE) {
9853 SetHistoryEntryAndUpdateBC(Some<nsISHEntry*>(aLoadState->SHEntry()),
9854 Nothing());
9855 if (aLoadState->LoadIsFromSessionHistory() &&
9856 !mozilla::SessionHistoryInParent()) {
9857 // We're making history navigation or a reload. Make sure our history ID
9858 // points to the same ID as SHEntry's docshell ID.
9859 nsID historyID = {};
9860 aLoadState->SHEntry()->GetDocshellID(historyID);
9861
9862 Unused << mBrowsingContext->SetHistoryID(historyID);
9863 }
9864 }
9865
9866 mSavingOldViewer = savePresentation;
9867
9868 // If we have a saved content viewer in history, restore and show it now.
9869 if (aLoadState->LoadIsFromSessionHistory() &&
9870 (mLoadType & LOAD_CMD_HISTORY)) {
9871 // https://html.spec.whatwg.org/#history-traversal:
9872 // To traverse the history
9873 // "If entry has a different Document object than the current entry, then
9874 // run the following substeps: Remove any tasks queued by the history
9875 // traversal task source..."
9876 // Same document object case was handled already above with
9877 // HandleSameDocumentNavigation call.
9878 RefPtr<ChildSHistory> shistory = GetRootSessionHistory();
9879 if (shistory) {
9880 shistory->RemovePendingHistoryNavigations();
9881 }
9882 if (!mozilla::SessionHistoryInParent()) {
9883 // It's possible that the previous viewer of mDocumentViewer is the
9884 // viewer that will end up in aLoadState->SHEntry() when it gets closed.
9885 // If that's the case, we need to go ahead and force it into its shentry
9886 // so we can restore it.
9887 if (mDocumentViewer) {
9888 nsCOMPtr<nsIDocumentViewer> prevViewer =
9889 mDocumentViewer->GetPreviousViewer();
9890 if (prevViewer) {
9891#ifdef DEBUG1
9892 nsCOMPtr<nsIDocumentViewer> prevPrevViewer =
9893 prevViewer->GetPreviousViewer();
9894 NS_ASSERTION(!prevPrevViewer, "Should never have viewer chain here")do { if (!(!prevPrevViewer)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "Should never have viewer chain here", "!prevPrevViewer", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 9894); MOZ_PretendNoReturn(); } } while (0)
;
9895#endif
9896 nsCOMPtr<nsISHEntry> viewerEntry;
9897 prevViewer->GetHistoryEntry(getter_AddRefs(viewerEntry));
9898 if (viewerEntry == aLoadState->SHEntry()) {
9899 // Make sure this viewer ends up in the right place
9900 mDocumentViewer->SetPreviousViewer(nullptr);
9901 prevViewer->Destroy();
9902 }
9903 }
9904 }
9905 nsCOMPtr<nsISHEntry> oldEntry = mOSHE;
9906 bool restoring;
9907 rv = RestorePresentation(aLoadState->SHEntry(), &restoring);
9908 if (restoring) {
9909 glean::bfcache::page_restored
9910 .EnumGet(glean::bfcache::PageRestoredLabel::eTrue)
9911 .Add();
9912 return rv;
9913 }
9914 glean::bfcache::page_restored
9915 .EnumGet(glean::bfcache::PageRestoredLabel::eFalse)
9916 .Add();
9917
9918 // We failed to restore the presentation, so clean up.
9919 // Both the old and new history entries could potentially be in
9920 // an inconsistent state.
9921 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
9922 if (oldEntry) {
9923 oldEntry->SyncPresentationState();
9924 }
9925
9926 aLoadState->SHEntry()->SyncPresentationState();
9927 }
9928 }
9929 }
9930
9931 bool isTopLevelDoc = mBrowsingContext->IsTopContent();
9932
9933 OriginAttributes attrs = GetOriginAttributes();
9934 attrs.SetFirstPartyDomain(isTopLevelDoc, aLoadState->URI());
9935
9936 PredictorLearn(aLoadState->URI(), nullptr,
9937 nsINetworkPredictor::LEARN_LOAD_TOPLEVEL, attrs);
9938 PredictorPredict(aLoadState->URI(), nullptr,
9939 nsINetworkPredictor::PREDICT_LOAD, attrs, nullptr);
9940
9941 nsCOMPtr<nsIRequest> req;
9942 rv = DoURILoad(aLoadState, aCacheKey, getter_AddRefs(req));
9943
9944 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
9945 if (shouldTakeFocus) {
9946 mBrowsingContext->Focus(CallerType::System, IgnoreErrors());
9947 }
9948 }
9949
9950 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
9951 nsCOMPtr<nsIChannel> chan(do_QueryInterface(req));
9952 UnblockEmbedderLoadEventForFailure();
9953 nsCOMPtr<nsIURI> uri = aLoadState->URI();
9954 if (DisplayLoadError(rv, uri, nullptr, chan) &&
9955 // FIXME: At this point code was using internal load flags, but checking
9956 // non-internal load flags?
9957 aLoadState->HasLoadFlags(LOAD_FLAGS_ERROR_LOAD_CHANGES_RV)) {
9958 return NS_ERROR_LOAD_SHOWED_ERRORPAGE;
9959 }
9960
9961 // We won't report any error if this is an unknown protocol error. The
9962 // reason behind this is that it will allow enumeration of external
9963 // protocols if we report an error for each unknown protocol.
9964 if (NS_ERROR_UNKNOWN_PROTOCOL == rv) {
9965 return NS_OK;
9966 }
9967 }
9968
9969 return rv;
9970}
9971
9972/* static */
9973bool nsDocShell::CanLoadInParentProcess(nsIURI* aURI) {
9974 nsCOMPtr<nsIURI> uri = aURI;
9975 // In e10s, in the parent process, we refuse to load anything other than
9976 // "safe" resources that we ship or trust enough to give "special" URLs.
9977 bool canLoadInParent = false;
9978 if (NS_SUCCEEDED(NS_URIChainHasFlags(((bool)(__builtin_expect(!!(!NS_FAILED_impl(NS_URIChainHasFlags
( uri, nsIProtocolHandler::URI_IS_UI_RESOURCE, &canLoadInParent
))), 1)))
9979 uri, nsIProtocolHandler::URI_IS_UI_RESOURCE, &canLoadInParent))((bool)(__builtin_expect(!!(!NS_FAILED_impl(NS_URIChainHasFlags
( uri, nsIProtocolHandler::URI_IS_UI_RESOURCE, &canLoadInParent
))), 1)))
&&
9980 canLoadInParent) {
9981 // We allow UI resources.
9982 return true;
9983 }
9984 // For about: and extension-based URIs, which don't get
9985 // URI_IS_UI_RESOURCE, first remove layers of view-source:, if present.
9986 while (uri && uri->SchemeIs("view-source")) {
9987 nsCOMPtr<nsINestedURI> nested = do_QueryInterface(uri);
9988 if (nested) {
9989 nested->GetInnerURI(getter_AddRefs(uri));
9990 } else {
9991 break;
9992 }
9993 }
9994 // Allow about: URIs, and allow moz-extension ones if we're running
9995 // extension content in the parent process.
9996 if (!uri || uri->SchemeIs("about") ||
9997 (!StaticPrefs::extensions_webextensions_remote() &&
9998 uri->SchemeIs("moz-extension"))) {
9999 return true;
10000 }
10001#ifdef MOZ_THUNDERBIRD
10002 if (uri->SchemeIs("imap") || uri->SchemeIs("mailbox") ||
10003 uri->SchemeIs("news") || uri->SchemeIs("nntp") ||
10004 uri->SchemeIs("snews") || uri->SchemeIs("x-moz-ews")) {
10005 return true;
10006 }
10007#endif
10008 nsAutoCString scheme;
10009 uri->GetScheme(scheme);
10010 // Allow ext+foo URIs (extension-registered custom protocols). See
10011 // https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/protocol_handlers
10012 if (StringBeginsWith(scheme, "ext+"_ns) &&
10013 !StaticPrefs::extensions_webextensions_remote()) {
10014 return true;
10015 }
10016 // Final exception for some legacy automated tests:
10017 if (xpc::IsInAutomation() &&
10018 StaticPrefs::security_allow_unsafe_parent_loads()) {
10019 return true;
10020 }
10021 return false;
10022}
10023
10024nsIPrincipal* nsDocShell::GetInheritedPrincipal(
10025 bool aConsiderCurrentDocument, bool aConsiderPartitionedPrincipal) {
10026 RefPtr<Document> document;
10027 bool inheritedFromCurrent = false;
10028
10029 if (aConsiderCurrentDocument && mDocumentViewer) {
10030 document = mDocumentViewer->GetDocument();
10031 inheritedFromCurrent = true;
10032 }
10033
10034 if (!document) {
10035 nsCOMPtr<nsIDocShellTreeItem> parentItem;
10036 GetInProcessSameTypeParent(getter_AddRefs(parentItem));
10037 if (parentItem) {
10038 document = parentItem->GetDocument();
10039 }
10040 }
10041
10042 if (!document) {
10043 if (!aConsiderCurrentDocument) {
10044 return nullptr;
10045 }
10046
10047 // Make sure we end up with _something_ as the principal no matter
10048 // what.If this fails, we'll just get a null docViewer and bail.
10049 EnsureDocumentViewer();
10050 if (!mDocumentViewer) {
10051 return nullptr;
10052 }
10053 document = mDocumentViewer->GetDocument();
10054 }
10055
10056 //-- Get the document's principal
10057 if (document) {
10058 nsIPrincipal* docPrincipal = aConsiderPartitionedPrincipal
10059 ? document->PartitionedPrincipal()
10060 : document->NodePrincipal();
10061
10062 // Don't allow loads in typeContent docShells to inherit the system
10063 // principal from existing documents.
10064 if (inheritedFromCurrent && mItemType == typeContent &&
10065 docPrincipal->IsSystemPrincipal()) {
10066 return nullptr;
10067 }
10068
10069 return docPrincipal;
10070 }
10071
10072 return nullptr;
10073}
10074
10075/* static */ nsresult nsDocShell::CreateRealChannelForDocument(
10076 nsIChannel** aChannel, nsIURI* aURI, nsILoadInfo* aLoadInfo,
10077 nsIInterfaceRequestor* aCallbacks, nsLoadFlags aLoadFlags,
10078 const nsAString& aSrcdoc, nsIURI* aBaseURI) {
10079 nsCOMPtr<nsIChannel> channel;
10080 if (aSrcdoc.IsVoid()) {
10081 MOZ_TRY(NS_NewChannelInternal(getter_AddRefs(channel), aURI, aLoadInfo,__extension__({ auto mozTryVarTempResult = ::mozilla::ToResult
(NS_NewChannelInternal(getter_AddRefs(channel), aURI, aLoadInfo
, nullptr, nullptr, aCallbacks, aLoadFlags)); if ((__builtin_expect
(!!(mozTryVarTempResult.isErr()), 0))) { return mozTryVarTempResult
.propagateErr(); } mozTryVarTempResult.unwrap(); })
10082 nullptr, // PerformanceStorage__extension__({ auto mozTryVarTempResult = ::mozilla::ToResult
(NS_NewChannelInternal(getter_AddRefs(channel), aURI, aLoadInfo
, nullptr, nullptr, aCallbacks, aLoadFlags)); if ((__builtin_expect
(!!(mozTryVarTempResult.isErr()), 0))) { return mozTryVarTempResult
.propagateErr(); } mozTryVarTempResult.unwrap(); })
10083 nullptr, // loadGroup__extension__({ auto mozTryVarTempResult = ::mozilla::ToResult
(NS_NewChannelInternal(getter_AddRefs(channel), aURI, aLoadInfo
, nullptr, nullptr, aCallbacks, aLoadFlags)); if ((__builtin_expect
(!!(mozTryVarTempResult.isErr()), 0))) { return mozTryVarTempResult
.propagateErr(); } mozTryVarTempResult.unwrap(); })
10084 aCallbacks, aLoadFlags))__extension__({ auto mozTryVarTempResult = ::mozilla::ToResult
(NS_NewChannelInternal(getter_AddRefs(channel), aURI, aLoadInfo
, nullptr, nullptr, aCallbacks, aLoadFlags)); if ((__builtin_expect
(!!(mozTryVarTempResult.isErr()), 0))) { return mozTryVarTempResult
.propagateErr(); } mozTryVarTempResult.unwrap(); })
;
10085
10086 if (aBaseURI) {
10087 nsCOMPtr<nsIViewSourceChannel> vsc = do_QueryInterface(channel);
10088 if (vsc) {
10089 MOZ_ALWAYS_SUCCEEDS(vsc->SetBaseURI(aBaseURI))do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(vsc->SetBaseURI(aBaseURI))), 1)))), 1))) { } else { do { do
{ } while (false); MOZ_ReportCrash("" "NS_SUCCEEDED(vsc->SetBaseURI(aBaseURI))"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 10089);
AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED(vsc->SetBaseURI(aBaseURI))"
")"); do { MOZ_CrashSequence(__null, 10089); __attribute__((
nomerge)) ::abort(); } while (false); } while (false); } } while
(false)
;
10090 }
10091 }
10092 } else if (aURI->SchemeIs("view-source")) {
10093 // Instantiate view source handler protocol, if it doesn't exist already.
10094 nsCOMPtr<nsIIOService> io(do_GetIOService());
10095 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", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 10095); AnnotateMozCrashReason("MOZ_ASSERT" "(" "io" ")"); do
{ MOZ_CrashSequence(__null, 10095); __attribute__((nomerge))
::abort(); } while (false); } } while (false)
;
10096 nsCOMPtr<nsIProtocolHandler> handler;
10097 nsresult rv =
10098 io->GetProtocolHandler("view-source", getter_AddRefs(handler));
10099 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
10100 return rv;
10101 }
10102
10103 nsViewSourceHandler* vsh = nsViewSourceHandler::GetInstance();
10104 if (!vsh) {
10105 return NS_ERROR_FAILURE;
10106 }
10107
10108 MOZ_TRY(vsh->NewSrcdocChannel(aURI, aBaseURI, aSrcdoc, aLoadInfo,__extension__({ auto mozTryVarTempResult = ::mozilla::ToResult
(vsh->NewSrcdocChannel(aURI, aBaseURI, aSrcdoc, aLoadInfo,
getter_AddRefs(channel))); if ((__builtin_expect(!!(mozTryVarTempResult
.isErr()), 0))) { return mozTryVarTempResult.propagateErr(); }
mozTryVarTempResult.unwrap(); })
10109 getter_AddRefs(channel)))__extension__({ auto mozTryVarTempResult = ::mozilla::ToResult
(vsh->NewSrcdocChannel(aURI, aBaseURI, aSrcdoc, aLoadInfo,
getter_AddRefs(channel))); if ((__builtin_expect(!!(mozTryVarTempResult
.isErr()), 0))) { return mozTryVarTempResult.propagateErr(); }
mozTryVarTempResult.unwrap(); })
;
10110 } else {
10111 MOZ_TRY(NS_NewInputStreamChannelInternal(getter_AddRefs(channel), aURI,__extension__({ auto mozTryVarTempResult = ::mozilla::ToResult
(NS_NewInputStreamChannelInternal(getter_AddRefs(channel), aURI
, aSrcdoc, "text/html"_ns, aLoadInfo, true)); if ((__builtin_expect
(!!(mozTryVarTempResult.isErr()), 0))) { return mozTryVarTempResult
.propagateErr(); } mozTryVarTempResult.unwrap(); })
10112 aSrcdoc, "text/html"_ns, aLoadInfo,__extension__({ auto mozTryVarTempResult = ::mozilla::ToResult
(NS_NewInputStreamChannelInternal(getter_AddRefs(channel), aURI
, aSrcdoc, "text/html"_ns, aLoadInfo, true)); if ((__builtin_expect
(!!(mozTryVarTempResult.isErr()), 0))) { return mozTryVarTempResult
.propagateErr(); } mozTryVarTempResult.unwrap(); })
10113 true))__extension__({ auto mozTryVarTempResult = ::mozilla::ToResult
(NS_NewInputStreamChannelInternal(getter_AddRefs(channel), aURI
, aSrcdoc, "text/html"_ns, aLoadInfo, true)); if ((__builtin_expect
(!!(mozTryVarTempResult.isErr()), 0))) { return mozTryVarTempResult
.propagateErr(); } mozTryVarTempResult.unwrap(); })
;
10114 nsCOMPtr<nsIInputStreamChannel> isc = do_QueryInterface(channel);
10115 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", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 10115); AnnotateMozCrashReason("MOZ_ASSERT" "(" "isc" ")");
do { MOZ_CrashSequence(__null, 10115); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
10116 isc->SetBaseURI(aBaseURI);
10117 }
10118
10119 if (aLoadFlags != nsIRequest::LOAD_NORMAL) {
10120 nsresult rv = channel->SetLoadFlags(aLoadFlags);
10121 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, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 10121); return rv; } } while (false)
;
10122 }
10123
10124 channel.forget(aChannel);
10125 return NS_OK;
10126}
10127
10128/* static */ bool nsDocShell::CreateAndConfigureRealChannelForLoadState(
10129 BrowsingContext* aBrowsingContext, nsDocShellLoadState* aLoadState,
10130 LoadInfo* aLoadInfo, nsIInterfaceRequestor* aCallbacks,
10131 nsDocShell* aDocShell, const OriginAttributes& aOriginAttributes,
10132 nsLoadFlags aLoadFlags, uint32_t aCacheKey, nsresult& aRv,
10133 nsIChannel** aChannel) {
10134 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", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 10134); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadInfo"
")"); do { MOZ_CrashSequence(__null, 10134); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10135
10136 nsString srcdoc = VoidString();
10137 bool isSrcdoc =
10138 aLoadState->HasInternalLoadFlags(INTERNAL_LOAD_FLAGS_IS_SRCDOC);
10139 if (isSrcdoc) {
10140 srcdoc = aLoadState->SrcdocData();
10141 }
10142
10143 aLoadInfo->SetTriggeringRemoteType(
10144 aLoadState->GetEffectiveTriggeringRemoteType());
10145
10146 if (aLoadState->PrincipalToInherit()) {
10147 aLoadInfo->SetPrincipalToInherit(aLoadState->PrincipalToInherit());
10148 }
10149 aLoadInfo->SetLoadTriggeredFromExternal(
10150 aLoadState->HasLoadFlags(LOAD_FLAGS_FROM_EXTERNAL));
10151 aLoadInfo->SetForceAllowDataURI(aLoadState->HasInternalLoadFlags(
10152 INTERNAL_LOAD_FLAGS_FORCE_ALLOW_DATA_URI));
10153 aLoadInfo->SetOriginalFrameSrcLoad(
10154 aLoadState->HasInternalLoadFlags(INTERNAL_LOAD_FLAGS_ORIGINAL_FRAME_SRC));
10155 aLoadInfo->SetIsNewWindowTarget(
10156 aLoadState->HasInternalLoadFlags(INTERNAL_LOAD_FLAGS_FIRST_LOAD));
10157
10158 bool inheritAttrs = false;
10159 if (aLoadState->PrincipalToInherit()) {
10160 inheritAttrs = nsContentUtils::ChannelShouldInheritPrincipal(
10161 aLoadState->PrincipalToInherit(), aLoadState->URI(),
10162 true, // aInheritForAboutBlank
10163 isSrcdoc);
10164 }
10165
10166 // Strip the target query parameters before creating the channel.
10167 aLoadState->MaybeStripTrackerQueryStrings(aBrowsingContext);
10168
10169 OriginAttributes attrs;
10170
10171 // Inherit origin attributes from PrincipalToInherit if inheritAttrs is
10172 // true. Otherwise we just use the origin attributes from docshell.
10173 if (inheritAttrs) {
10174 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."
")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 10175
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->PrincipalToInherit()"
") (" "We should have PrincipalToInherit here." ")"); do { MOZ_CrashSequence
(__null, 10175); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
10175 "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."
")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 10175
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->PrincipalToInherit()"
") (" "We should have PrincipalToInherit here." ")"); do { MOZ_CrashSequence
(__null, 10175); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
10176 attrs = aLoadState->PrincipalToInherit()->OriginAttributesRef();
10177 // If firstPartyIsolation is not enabled, then PrincipalToInherit should
10178 // have the same origin attributes with docshell.
10179 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"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 10180);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "attrs == aOriginAttributes"
")"); do { MOZ_CrashSequence(__null, 10180); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false); } } while
(false)
10180 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"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 10180);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "attrs == aOriginAttributes"
")"); do { MOZ_CrashSequence(__null, 10180); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false); } } while
(false)
;
10181 } else {
10182 attrs = aOriginAttributes;
10183 attrs.SetFirstPartyDomain(IsTopLevelDoc(aBrowsingContext, aLoadInfo),
10184 aLoadState->URI());
10185 }
10186
10187 aRv = aLoadInfo->SetOriginAttributes(attrs);
10188 if (NS_WARN_IF(NS_FAILED(aRv))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(aRv
)), 0))), "NS_FAILED(aRv)", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 10188)
) {
10189 return false;
10190 }
10191
10192 if (aLoadState->GetIsFromProcessingFrameAttributes()) {
10193 aLoadInfo->SetIsFromProcessingFrameAttributes();
10194 }
10195
10196 // Propagate the IsFormSubmission flag to the loadInfo.
10197 if (aLoadState->IsFormSubmission()) {
10198 aLoadInfo->SetIsFormSubmission(true);
10199 }
10200
10201 aLoadInfo->SetUnstrippedURI(aLoadState->GetUnstrippedURI());
10202
10203 nsCOMPtr<nsIChannel> channel;
10204 aRv = CreateRealChannelForDocument(getter_AddRefs(channel), aLoadState->URI(),
10205 aLoadInfo, aCallbacks, aLoadFlags, srcdoc,
10206 aLoadState->BaseURI());
10207 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, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 10207); return false; } } while (false)
;
10208
10209 if (!channel) {
10210 return false;
10211 }
10212
10213 // If the HTTPS-Only mode is enabled, every insecure request gets upgraded to
10214 // HTTPS by default. This behavior can be disabled through the loadinfo flag
10215 // HTTPS_ONLY_EXEMPT.
10216 nsHTTPSOnlyUtils::TestSitePermissionAndPotentiallyAddExemption(channel);
10217
10218 // hack
10219 nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(channel));
10220 nsCOMPtr<nsIHttpChannelInternal> httpChannelInternal(
10221 do_QueryInterface(channel));
10222 nsCOMPtr<nsIURI> referrer;
10223 nsIReferrerInfo* referrerInfo = aLoadState->GetReferrerInfo();
10224 if (referrerInfo) {
10225 referrerInfo->GetOriginalReferrer(getter_AddRefs(referrer));
10226 }
10227 if (httpChannelInternal) {
10228 if (aLoadState->HasInternalLoadFlags(
10229 INTERNAL_LOAD_FLAGS_FORCE_ALLOW_COOKIES)) {
10230 aRv = httpChannelInternal->SetThirdPartyFlags(
10231 nsIHttpChannelInternal::THIRD_PARTY_FORCE_ALLOW);
10232 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)))", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 10232); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(aRv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 10232); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10233 }
10234 if (aLoadState->FirstParty()) {
10235 aRv = httpChannelInternal->SetDocumentURI(aLoadState->URI());
10236 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)))", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 10236); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(aRv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 10236); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10237 } else {
10238 aRv = httpChannelInternal->SetDocumentURI(referrer);
10239 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)))", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 10239); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(aRv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 10239); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10240 }
10241 aRv = httpChannelInternal->SetRedirectMode(
10242 nsIHttpChannelInternal::REDIRECT_MODE_MANUAL);
10243 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)))", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 10243); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(aRv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 10243); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10244 }
10245
10246 if (httpChannel) {
10247 if (aLoadState->HeadersStream()) {
10248 aRv = AddHeadersToChannel(aLoadState->HeadersStream(), httpChannel);
10249 }
10250 // Set the referrer explicitly
10251 // Referrer is currenly only set for link clicks here.
10252 if (referrerInfo) {
10253 aRv = httpChannel->SetReferrerInfo(referrerInfo);
10254 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)))", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 10254); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(aRv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 10254); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10255 }
10256
10257 // Mark the http channel as UrgentStart for top level document loading in
10258 // active tab.
10259 if (IsUrgentStart(aBrowsingContext, aLoadInfo, aLoadState->LoadType())) {
10260 nsCOMPtr<nsIClassOfService> cos(do_QueryInterface(channel));
10261 if (cos) {
10262 cos->AddClassFlags(nsIClassOfService::UrgentStart);
10263 if (StaticPrefs::dom_document_priority_incremental()) {
10264 cos->SetIncremental(true);
10265 }
10266 }
10267 }
10268 }
10269
10270 channel->SetOriginalURI(aLoadState->OriginalURI() ? aLoadState->OriginalURI()
10271 : aLoadState->URI());
10272
10273 const nsACString& typeHint = aLoadState->TypeHint();
10274 if (!typeHint.IsVoid()) {
10275 channel->SetContentType(typeHint);
10276 }
10277
10278 const nsAString& fileName = aLoadState->FileName();
10279 if (!fileName.IsVoid()) {
10280 aRv = channel->SetContentDisposition(nsIChannel::DISPOSITION_ATTACHMENT);
10281 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, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 10281); return false; } } while (false)
;
10282 if (!fileName.IsEmpty()) {
10283 aRv = channel->SetContentDispositionFilename(fileName);
10284 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, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 10284); return false; } } while (false)
;
10285 }
10286 }
10287
10288 if (nsCOMPtr<nsIWritablePropertyBag2> props = do_QueryInterface(channel)) {
10289 nsCOMPtr<nsIURI> referrer;
10290 nsIReferrerInfo* referrerInfo = aLoadState->GetReferrerInfo();
10291 if (referrerInfo) {
10292 referrerInfo->GetOriginalReferrer(getter_AddRefs(referrer));
10293 }
10294 // save true referrer for those who need it (e.g. xpinstall whitelisting)
10295 // Currently only http and ftp channels support this.
10296 props->SetPropertyAsInterface(u"docshell.internalReferrer"_ns, referrer);
10297 }
10298
10299 nsCOMPtr<nsICacheInfoChannel> cacheChannel(do_QueryInterface(channel));
10300 auto loadType = aLoadState->LoadType();
10301
10302 if (loadType == LOAD_RELOAD_NORMAL &&
10303 StaticPrefs::
10304 browser_soft_reload_only_force_validate_top_level_document()) {
10305 nsCOMPtr<nsICacheInfoChannel> cachingChannel = do_QueryInterface(channel);
10306 if (cachingChannel) {
10307 cachingChannel->SetForceValidateCacheContent(true);
10308 }
10309 }
10310
10311 // figure out if we need to set the post data stream on the channel...
10312 if (aLoadState->PostDataStream()) {
10313 if (nsCOMPtr<nsIFormPOSTActionChannel> postChannel =
10314 do_QueryInterface(channel)) {
10315 // XXX it's a bit of a hack to rewind the postdata stream here but
10316 // it has to be done in case the post data is being reused multiple
10317 // times.
10318 nsCOMPtr<nsISeekableStream> postDataSeekable =
10319 do_QueryInterface(aLoadState->PostDataStream());
10320 if (postDataSeekable) {
10321 aRv = postDataSeekable->Seek(nsISeekableStream::NS_SEEK_SET, 0);
10322 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, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 10322); return false; } } while (false)
;
10323 }
10324
10325 // we really need to have a content type associated with this stream!!
10326 postChannel->SetUploadStream(aLoadState->PostDataStream(), ""_ns, -1);
10327
10328 // Ownership of the stream has transferred to the channel, clear our
10329 // reference.
10330 aLoadState->SetPostDataStream(nullptr);
10331 }
10332
10333 /* If there is a valid postdata *and* it is a History Load,
10334 * set up the cache key on the channel, to retrieve the
10335 * data *only* from the cache. If it is a normal reload, the
10336 * cache is free to go to the server for updated postdata.
10337 */
10338 if (cacheChannel && aCacheKey != 0) {
10339 if (loadType == LOAD_HISTORY || loadType == LOAD_RELOAD_CHARSET_CHANGE) {
10340 cacheChannel->SetCacheKey(aCacheKey);
10341 uint32_t loadFlags;
10342 if (NS_SUCCEEDED(channel->GetLoadFlags(&loadFlags))((bool)(__builtin_expect(!!(!NS_FAILED_impl(channel->GetLoadFlags
(&loadFlags))), 1)))
) {
10343 channel->SetLoadFlags(loadFlags |
10344 nsICachingChannel::LOAD_ONLY_FROM_CACHE);
10345 }
10346 } else if (loadType == LOAD_RELOAD_NORMAL) {
10347 cacheChannel->SetCacheKey(aCacheKey);
10348 }
10349 }
10350 } else {
10351 /* If there is no postdata, set the cache key on the channel, and
10352 * do not set the LOAD_ONLY_FROM_CACHE flag, so that the channel
10353 * will be free to get it from net if it is not found in cache.
10354 * New cache may use it creatively on CGI pages with GET
10355 * method and even on those that say "no-cache"
10356 */
10357 if (loadType == LOAD_HISTORY || loadType == LOAD_RELOAD_NORMAL ||
10358 loadType == LOAD_RELOAD_CHARSET_CHANGE ||
10359 loadType == LOAD_RELOAD_CHARSET_CHANGE_BYPASS_CACHE ||
10360 loadType == LOAD_RELOAD_CHARSET_CHANGE_BYPASS_PROXY_AND_CACHE) {
10361 if (cacheChannel && aCacheKey != 0) {
10362 cacheChannel->SetCacheKey(aCacheKey);
10363 }
10364 }
10365 }
10366
10367 if (nsCOMPtr<nsIScriptChannel> scriptChannel = do_QueryInterface(channel)) {
10368 // Allow execution against our context if the principals match
10369 scriptChannel->SetExecutionPolicy(nsIScriptChannel::EXECUTE_NORMAL);
10370 }
10371
10372 if (nsCOMPtr<nsITimedChannel> timedChannel = do_QueryInterface(channel)) {
10373 nsString initiatorType;
10374 switch (aLoadInfo->InternalContentPolicyType()) {
10375 case nsIContentPolicy::TYPE_INTERNAL_EMBED:
10376 initiatorType = u"embed"_ns;
10377 break;
10378 case nsIContentPolicy::TYPE_INTERNAL_OBJECT:
10379 initiatorType = u"object"_ns;
10380 break;
10381 default: {
10382 const auto& embedderElementType =
10383 aBrowsingContext->GetEmbedderElementType();
10384 if (embedderElementType) {
10385 initiatorType = *embedderElementType;
10386 }
10387 break;
10388 }
10389 }
10390
10391 if (!initiatorType.IsEmpty()) {
10392 timedChannel->SetInitiatorType(initiatorType);
10393 }
10394 }
10395
10396 nsCOMPtr<nsIURI> rpURI;
10397 aLoadInfo->GetResultPrincipalURI(getter_AddRefs(rpURI));
10398 Maybe<nsCOMPtr<nsIURI>> originalResultPrincipalURI;
10399 aLoadState->GetMaybeResultPrincipalURI(originalResultPrincipalURI);
10400 if (originalResultPrincipalURI &&
10401 (!aLoadState->KeepResultPrincipalURIIfSet() || !rpURI)) {
10402 // Unconditionally override, we want the replay to be equal to what has
10403 // been captured.
10404 aLoadInfo->SetResultPrincipalURI(originalResultPrincipalURI.ref());
10405 }
10406
10407 if (aLoadState->OriginalURI() && aLoadState->LoadReplace()) {
10408 // The LOAD_REPLACE flag and its handling here will be removed as part
10409 // of bug 1319110. For now preserve its restoration here to not break
10410 // any code expecting it being set specially on redirected channels.
10411 // If the flag has originally been set to change result of
10412 // NS_GetFinalChannelURI it won't have any effect and also won't cause
10413 // any harm.
10414 uint32_t loadFlags;
10415 aRv = channel->GetLoadFlags(&loadFlags);
10416 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, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 10416); return false; } } while (false)
;
10417 channel->SetLoadFlags(loadFlags | nsIChannel::LOAD_REPLACE);
10418 }
10419
10420 nsCOMPtr<nsIContentSecurityPolicy> csp = aLoadState->Csp();
10421 if (csp) {
10422 // Navigational requests that are same origin need to be upgraded in case
10423 // upgrade-insecure-requests is present. Please note that for document
10424 // navigations that bit is re-computed in case we encounter a server
10425 // side redirect so the navigation is not same-origin anymore.
10426 bool upgradeInsecureRequests = false;
10427 csp->GetUpgradeInsecureRequests(&upgradeInsecureRequests);
10428 if (upgradeInsecureRequests) {
10429 // only upgrade if the navigation is same origin
10430 nsCOMPtr<nsIPrincipal> resultPrincipal;
10431 aRv = nsContentUtils::GetSecurityManager()->GetChannelResultPrincipal(
10432 channel, getter_AddRefs(resultPrincipal));
10433 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, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 10433); return false; } } while (false)
;
10434 if (nsContentSecurityUtils::IsConsideredSameOriginForUIR(
10435 aLoadState->TriggeringPrincipal(), resultPrincipal)) {
10436 aLoadInfo->SetUpgradeInsecureRequests(true);
10437 }
10438 }
10439
10440 // For document loads we store the CSP that potentially needs to
10441 // be inherited by the new document, e.g. in case we are loading
10442 // an opaque origin like a data: URI. The actual inheritance
10443 // check happens within Document::InitCSP().
10444 // Please create an actual copy of the CSP (do not share the same
10445 // reference) otherwise a Meta CSP of an opaque origin will
10446 // incorrectly be propagated to the embedding document.
10447 RefPtr<nsCSPContext> cspToInherit = new nsCSPContext();
10448 cspToInherit->InitFromOther(static_cast<nsCSPContext*>(csp.get()));
10449 aLoadInfo->SetCSPToInherit(cspToInherit);
10450 }
10451
10452 channel.forget(aChannel);
10453 return true;
10454}
10455
10456bool nsDocShell::IsAboutBlankLoadOntoInitialAboutBlank(
10457 nsIURI* aURI, bool aInheritPrincipal, nsIPrincipal* aPrincipalToInherit) {
10458 return NS_IsAboutBlankAllowQueryAndFragment(aURI) && aInheritPrincipal &&
10459 (aPrincipalToInherit == GetInheritedPrincipal(false)) &&
10460 (!mDocumentViewer || !mDocumentViewer->GetDocument() ||
10461 mDocumentViewer->GetDocument()->IsInitialDocument());
10462}
10463
10464nsresult nsDocShell::DoURILoad(nsDocShellLoadState* aLoadState,
10465 Maybe<uint32_t> aCacheKey,
10466 nsIRequest** aRequest) {
10467 // Double-check that we're still around to load this URI.
10468 if (mIsBeingDestroyed) {
10469 // Return NS_OK despite not doing anything to avoid throwing exceptions
10470 // from nsLocation::SetHref if the unload handler of the existing page
10471 // tears us down.
10472 return NS_OK;
10473 }
10474
10475 nsCOMPtr<nsIURILoader> uriLoader = components::URILoader::Service();
10476 if (NS_WARN_IF(!uriLoader)NS_warn_if_impl(!uriLoader, "!uriLoader", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 10476)
) {
10477 return NS_ERROR_UNEXPECTED;
10478 }
10479
10480 // Persist and sync layout history state before we load a new uri, as this
10481 // might be our last chance to do so, in the content process.
10482 PersistLayoutHistoryState();
10483 SynchronizeLayoutHistoryState();
10484
10485 nsresult rv;
10486 nsContentPolicyType contentPolicyType = DetermineContentType();
10487
10488 if (IsSubframe()) {
10489 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"
")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 10491
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "contentPolicyType == nsIContentPolicy::TYPE_INTERNAL_IFRAME || contentPolicyType == nsIContentPolicy::TYPE_INTERNAL_FRAME"
") (" "DoURILoad thinks this is a frame and InternalLoad does not"
")"); do { MOZ_CrashSequence(__null, 10491); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
10490 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"
")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 10491
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "contentPolicyType == nsIContentPolicy::TYPE_INTERNAL_IFRAME || contentPolicyType == nsIContentPolicy::TYPE_INTERNAL_FRAME"
") (" "DoURILoad thinks this is a frame and InternalLoad does not"
")"); do { MOZ_CrashSequence(__null, 10491); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
10491 "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"
")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 10491
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "contentPolicyType == nsIContentPolicy::TYPE_INTERNAL_IFRAME || contentPolicyType == nsIContentPolicy::TYPE_INTERNAL_FRAME"
") (" "DoURILoad thinks this is a frame and InternalLoad does not"
")"); do { MOZ_CrashSequence(__null, 10491); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10492 if (StaticPrefs::dom_block_external_protocol_in_iframes()) {
10493 // Only allow URLs able to return data in iframes.
10494 if (nsContentUtils::IsExternalProtocol(aLoadState->URI())) {
10495 // The context to check user-interaction with for the purposes of
10496 // popup-blocking.
10497 //
10498 // We generally want to check the context that initiated the navigation.
10499 WindowContext* sourceWindowContext = [&] {
10500 const MaybeDiscardedBrowsingContext& sourceBC =
10501 aLoadState->SourceBrowsingContext();
10502 if (!sourceBC.IsNullOrDiscarded()) {
10503 if (WindowContext* wc = sourceBC.get()->GetCurrentWindowContext()) {
10504 return wc;
10505 }
10506 }
10507 return mBrowsingContext->GetParentWindowContext();
10508 }();
10509
10510 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"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 10510);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "sourceWindowContext"
")"); do { MOZ_CrashSequence(__null, 10510); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10511 // FIXME: We can't check user-interaction against an OOP window. This is
10512 // the next best thing we can really do. The load state keeps whether
10513 // the navigation had a user interaction in process
10514 // (aLoadState->HasValidUserGestureActivation()), but we can't really
10515 // consume it, which we want to prevent popup-spamming from the same
10516 // click event.
10517 WindowContext* context =
10518 sourceWindowContext->IsInProcess()
10519 ? sourceWindowContext
10520 : mBrowsingContext->GetCurrentWindowContext();
10521 const bool popupBlocked = [&] {
10522 const bool active = mBrowsingContext->IsActive();
10523
10524 // For same-origin-with-top windows, we grant a single free popup
10525 // without user activation, see bug 1680721.
10526 //
10527 // We consume the flag now even if there's no user activation.
10528 const bool hasFreePass = [&] {
10529 if (!active ||
10530 !(context->IsInProcess() && context->SameOriginWithTop())) {
10531 return false;
10532 }
10533 nsGlobalWindowInner* win =
10534 context->TopWindowContext()->GetInnerWindow();
10535 return win && win->TryOpenExternalProtocolIframe();
10536 }();
10537
10538 if (context->IsInProcess() &&
10539 context->ConsumeTransientUserGestureActivation()) {
10540 // If the user has interacted with the page, consume it.
10541 return false;
10542 }
10543
10544 // TODO(emilio): Can we remove this check? It seems like what prompted
10545 // this code (bug 1514547) should be covered by transient user
10546 // activation, see bug 1514547.
10547 if (active &&
10548 PopupBlocker::ConsumeTimerTokenForExternalProtocolIframe()) {
10549 return false;
10550 }
10551
10552 if (sourceWindowContext->CanShowPopup()) {
10553 return false;
10554 }
10555
10556 if (hasFreePass) {
10557 return false;
10558 }
10559
10560 return true;
10561 }();
10562
10563 // No error must be returned when iframes are blocked.
10564 if (popupBlocked) {
10565 nsAutoString message;
10566 nsresult rv = nsContentUtils::GetLocalizedString(
10567 nsContentUtils::eDOM_PROPERTIES,
10568 "ExternalProtocolFrameBlockedNoUserActivation", message);
10569 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
10570 nsContentUtils::ReportToConsoleByWindowID(
10571 message, nsIScriptError::warningFlag, "DOM"_ns,
10572 context->InnerWindowId());
10573 }
10574 return NS_OK;
10575 }
10576 }
10577 }
10578
10579 // Only allow view-source scheme in top-level docshells. view-source is
10580 // the only scheme to which this applies at the moment due to potential
10581 // timing attacks to read data from cross-origin iframes. If this widens
10582 // we should add a protocol flag for whether the scheme is allowed in
10583 // frames and use something like nsNetUtil::NS_URIChainHasFlags.
10584 nsCOMPtr<nsIURI> tempURI = aLoadState->URI();
10585 nsCOMPtr<nsINestedURI> nestedURI = do_QueryInterface(tempURI);
10586 while (nestedURI) {
10587 // view-source should always be an nsINestedURI, loop and check the
10588 // scheme on this and all inner URIs that are also nested URIs.
10589 if (tempURI->SchemeIs("view-source")) {
10590 return NS_ERROR_UNKNOWN_PROTOCOL;
10591 }
10592 nestedURI->GetInnerURI(getter_AddRefs(tempURI));
10593 nestedURI = do_QueryInterface(tempURI);
10594 }
10595 } else {
10596 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"
")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 10597
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "contentPolicyType == nsIContentPolicy::TYPE_DOCUMENT"
") (" "DoURILoad thinks this is a document and InternalLoad does not"
")"); do { MOZ_CrashSequence(__null, 10597); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
10597 "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"
")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 10597
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "contentPolicyType == nsIContentPolicy::TYPE_DOCUMENT"
") (" "DoURILoad thinks this is a document and InternalLoad does not"
")"); do { MOZ_CrashSequence(__null, 10597); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10598 }
10599
10600 // We want to inherit aLoadState->PrincipalToInherit() when:
10601 // 1. ChannelShouldInheritPrincipal returns true.
10602 // 2. aLoadState->URI() is not data: URI, or data: URI is not
10603 // configured as unique opaque origin.
10604 bool inheritPrincipal = false;
10605
10606 nsCOMPtr<nsIURI> uri = aLoadState->URI();
10607 if (aLoadState->PrincipalToInherit()) {
10608 bool isSrcdoc =
10609 aLoadState->HasInternalLoadFlags(INTERNAL_LOAD_FLAGS_IS_SRCDOC);
10610 bool inheritAttrs = nsContentUtils::ChannelShouldInheritPrincipal(
10611 aLoadState->PrincipalToInherit(), uri,
10612 true, // aInheritForAboutBlank
10613 isSrcdoc);
10614
10615 inheritPrincipal = inheritAttrs && !uri->SchemeIs("data");
10616 }
10617
10618 // See https://bugzilla.mozilla.org/show_bug.cgi?id=1736570
10619 const bool isAboutBlankLoadOntoInitialAboutBlank =
10620 IsAboutBlankLoadOntoInitialAboutBlank(uri, inheritPrincipal,
10621 aLoadState->PrincipalToInherit());
10622
10623 // FIXME We still have a ton of codepaths that don't pass through
10624 // DocumentLoadListener, so probably need to create session history info
10625 // in more places.
10626 if (aLoadState->GetLoadingSessionHistoryInfo()) {
10627 SetLoadingSessionHistoryInfo(*aLoadState->GetLoadingSessionHistoryInfo());
10628 } else if (isAboutBlankLoadOntoInitialAboutBlank &&
10629 mozilla::SessionHistoryInParent()) {
10630 // Materialize LoadingSessionHistoryInfo here, because DocumentChannel
10631 // loads have it, and later history behavior depends on it existing.
10632 UniquePtr<SessionHistoryInfo> entry = MakeUnique<SessionHistoryInfo>(
10633 uri, aLoadState->TriggeringPrincipal(),
10634 aLoadState->PrincipalToInherit(),
10635 aLoadState->PartitionedPrincipalToInherit(), aLoadState->Csp(),
10636 mContentTypeHint);
10637 mozilla::dom::LoadingSessionHistoryInfo info(*entry);
10638 SetLoadingSessionHistoryInfo(info, true);
10639 }
10640
10641 // open a channel for the url
10642
10643 // If we have a pending channel, use the channel we've already created here.
10644 // We don't need to set up load flags for our channel, as it has already been
10645 // created.
10646
10647 if (nsCOMPtr<nsIChannel> channel =
10648 aLoadState->GetPendingRedirectedChannel()) {
10649 // If we have a request outparameter, shove our channel into it.
10650 if (aRequest) {
10651 nsCOMPtr<nsIRequest> outRequest = channel;
10652 outRequest.forget(aRequest);
10653 }
10654
10655 return OpenRedirectedChannel(aLoadState);
10656 }
10657
10658 // There are two cases we care about:
10659 // * Top-level load: In this case, loadingNode is null, but loadingWindow
10660 // is our mScriptGlobal. We pass null for loadingPrincipal in this case.
10661 // * Subframe load: loadingWindow is null, but loadingNode is the frame
10662 // element for the load. loadingPrincipal is the NodePrincipal of the
10663 // frame element.
10664 nsCOMPtr<nsINode> loadingNode;
10665 nsCOMPtr<nsPIDOMWindowOuter> loadingWindow;
10666 nsCOMPtr<nsIPrincipal> loadingPrincipal;
10667 nsCOMPtr<nsISupports> topLevelLoadingContext;
10668
10669 if (contentPolicyType == nsIContentPolicy::TYPE_DOCUMENT) {
10670 loadingNode = nullptr;
10671 loadingPrincipal = nullptr;
10672 loadingWindow = mScriptGlobal;
10673 if (XRE_IsContentProcess()) {
10674 // In e10s the child process doesn't have access to the element that
10675 // contains the browsing context (because that element is in the chrome
10676 // process).
10677 nsCOMPtr<nsIBrowserChild> browserChild = GetBrowserChild();
10678 topLevelLoadingContext = ToSupports(browserChild);
10679 } else {
10680 // This is for loading non-e10s tabs and toplevel windows of various
10681 // sorts.
10682 // For the toplevel window cases, requestingElement will be null.
10683 nsCOMPtr<Element> requestingElement =
10684 loadingWindow->GetFrameElementInternal();
10685 topLevelLoadingContext = requestingElement;
10686 }
10687 } else {
10688 loadingWindow = nullptr;
10689 loadingNode = mScriptGlobal->GetFrameElementInternal();
10690 if (loadingNode) {
10691 // If we have a loading node, then use that as our loadingPrincipal.
10692 loadingPrincipal = loadingNode->NodePrincipal();
10693#ifdef DEBUG1
10694 // Get the docshell type for requestingElement.
10695 RefPtr<Document> requestingDoc = loadingNode->OwnerDoc();
10696 nsCOMPtr<nsIDocShell> elementDocShell = requestingDoc->GetDocShell();
10697 // requestingElement docshell type = current docshell type.
10698 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"
")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 10700
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mItemType == elementDocShell->ItemType()"
") (" "subframes should have the same docshell type as their parent"
")"); do { MOZ_CrashSequence(__null, 10700); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
10699 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"
")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 10700
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mItemType == elementDocShell->ItemType()"
") (" "subframes should have the same docshell type as their parent"
")"); do { MOZ_CrashSequence(__null, 10700); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
10700 "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"
")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 10700
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mItemType == elementDocShell->ItemType()"
") (" "subframes should have the same docshell type as their parent"
")"); do { MOZ_CrashSequence(__null, 10700); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10701#endif
10702 } else {
10703 if (mIsBeingDestroyed) {
10704 // If this isn't a top-level load and mScriptGlobal's frame element is
10705 // null, then the element got removed from the DOM while we were trying
10706 // to load this resource. This docshell is scheduled for destruction
10707 // already, so bail out here.
10708 return NS_OK;
10709 }
10710 // If we are not being destroyed and we do not have access to the loading
10711 // node, then we are a remote subframe. Set the loading principal
10712 // to be a null principal and then set it correctly in the parent.
10713 loadingPrincipal = NullPrincipal::Create(GetOriginAttributes(), nullptr);
10714 }
10715 }
10716
10717 if (!aLoadState->TriggeringPrincipal()) {
10718 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"
")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 10718
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") (" "DoURILoad needs a valid triggeringPrincipal"
")"); do { MOZ_CrashSequence(__null, 10718); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10719 return NS_ERROR_FAILURE;
10720 }
10721
10722 uint32_t sandboxFlags = mBrowsingContext->GetSandboxFlags();
10723 nsSecurityFlags securityFlags =
10724 nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_SEC_CONTEXT_IS_NULL;
10725
10726 if (mLoadType == LOAD_ERROR_PAGE) {
10727 securityFlags |= nsILoadInfo::SEC_LOAD_ERROR_PAGE;
10728 }
10729
10730 if (inheritPrincipal) {
10731 securityFlags |= nsILoadInfo::SEC_FORCE_INHERIT_PRINCIPAL;
10732 }
10733
10734 // Must never have a parent for TYPE_DOCUMENT loads
10735 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()"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 10736);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mBrowsingContext->GetParent()"
")"); do { MOZ_CrashSequence(__null, 10736); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false); } } while
(false)
10736 !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()"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 10736);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mBrowsingContext->GetParent()"
")"); do { MOZ_CrashSequence(__null, 10736); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false); } } while
(false)
;
10737 // Subdocuments must have a parent
10738 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()", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 10739); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mBrowsingContext->GetParent()"
")"); do { MOZ_CrashSequence(__null, 10739); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false); } } while
(false)
10739 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()", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 10739); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mBrowsingContext->GetParent()"
")"); do { MOZ_CrashSequence(__null, 10739); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false); } } while
(false)
;
10740 mBrowsingContext->SetTriggeringAndInheritPrincipals(
10741 aLoadState->TriggeringPrincipal(), aLoadState->PrincipalToInherit(),
10742 aLoadState->GetLoadIdentifier());
10743 RefPtr<LoadInfo> loadInfo;
10744 if (contentPolicyType == nsIContentPolicy::TYPE_DOCUMENT) {
10745 loadInfo =
10746 new LoadInfo(loadingWindow, uri, aLoadState->TriggeringPrincipal(),
10747 topLevelLoadingContext, securityFlags, sandboxFlags);
10748 } else {
10749 loadInfo = MOZ_TRY(LoadInfo::Create(__extension__({ auto mozTryVarTempResult = ::mozilla::ToResult
(LoadInfo::Create( loadingPrincipal, aLoadState->TriggeringPrincipal
(), loadingNode, securityFlags, contentPolicyType, Maybe<mozilla
::dom::ClientInfo>(), Maybe<mozilla::dom::ServiceWorkerDescriptor
>(), sandboxFlags)); if ((__builtin_expect(!!(mozTryVarTempResult
.isErr()), 0))) { return mozTryVarTempResult.propagateErr(); }
mozTryVarTempResult.unwrap(); })
10750 loadingPrincipal, aLoadState->TriggeringPrincipal(), loadingNode,__extension__({ auto mozTryVarTempResult = ::mozilla::ToResult
(LoadInfo::Create( loadingPrincipal, aLoadState->TriggeringPrincipal
(), loadingNode, securityFlags, contentPolicyType, Maybe<mozilla
::dom::ClientInfo>(), Maybe<mozilla::dom::ServiceWorkerDescriptor
>(), sandboxFlags)); if ((__builtin_expect(!!(mozTryVarTempResult
.isErr()), 0))) { return mozTryVarTempResult.propagateErr(); }
mozTryVarTempResult.unwrap(); })
10751 securityFlags, contentPolicyType, Maybe<mozilla::dom::ClientInfo>(),__extension__({ auto mozTryVarTempResult = ::mozilla::ToResult
(LoadInfo::Create( loadingPrincipal, aLoadState->TriggeringPrincipal
(), loadingNode, securityFlags, contentPolicyType, Maybe<mozilla
::dom::ClientInfo>(), Maybe<mozilla::dom::ServiceWorkerDescriptor
>(), sandboxFlags)); if ((__builtin_expect(!!(mozTryVarTempResult
.isErr()), 0))) { return mozTryVarTempResult.propagateErr(); }
mozTryVarTempResult.unwrap(); })
10752 Maybe<mozilla::dom::ServiceWorkerDescriptor>(), sandboxFlags))__extension__({ auto mozTryVarTempResult = ::mozilla::ToResult
(LoadInfo::Create( loadingPrincipal, aLoadState->TriggeringPrincipal
(), loadingNode, securityFlags, contentPolicyType, Maybe<mozilla
::dom::ClientInfo>(), Maybe<mozilla::dom::ServiceWorkerDescriptor
>(), sandboxFlags)); if ((__builtin_expect(!!(mozTryVarTempResult
.isErr()), 0))) { return mozTryVarTempResult.propagateErr(); }
mozTryVarTempResult.unwrap(); })
;
10753 }
10754 RefPtr<WindowContext> context = mBrowsingContext->GetCurrentWindowContext();
10755
10756 if (isAboutBlankLoadOntoInitialAboutBlank) {
10757 // Match the DocumentChannel case where the default for third-partiness
10758 // differs from the default in LoadInfo construction here.
10759 // toolkit/components/antitracking/test/browser/browser_aboutblank.js
10760 // fails without this.
10761 BrowsingContext* top = mBrowsingContext->Top();
10762 if (top == mBrowsingContext) {
10763 // If we're at the top, this must be a window.open()ed
10764 // window, and we can't be third-party relative to ourselves.
10765 loadInfo->SetIsThirdPartyContextToTopWindow(false);
10766 } else {
10767 if (Document* topDoc = top->GetDocument()) {
10768 bool thirdParty = false;
10769 mozilla::Unused << topDoc->GetPrincipal()->IsThirdPartyPrincipal(
10770 aLoadState->PrincipalToInherit(), &thirdParty);
10771 loadInfo->SetIsThirdPartyContextToTopWindow(thirdParty);
10772 } else {
10773 // If top is in a different process, we have to be third-party relative
10774 // to it.
10775 loadInfo->SetIsThirdPartyContextToTopWindow(true);
10776 }
10777 }
10778 }
10779
10780 if (mLoadType != LOAD_ERROR_PAGE && context && context->IsInProcess()) {
10781 if (context->HasValidTransientUserGestureActivation()) {
10782 aLoadState->SetHasValidUserGestureActivation(true);
10783 aLoadState->SetTextDirectiveUserActivation(true);
10784 }
10785 if (!aLoadState->TriggeringWindowId()) {
10786 aLoadState->SetTriggeringWindowId(context->Id());
10787 }
10788 if (!aLoadState->TriggeringStorageAccess()) {
10789 Document* contextDoc = context->GetExtantDoc();
10790 if (contextDoc) {
10791 aLoadState->SetTriggeringStorageAccess(
10792 contextDoc->UsingStorageAccess());
10793 }
10794 }
10795 }
10796
10797 // in case this docshell load was triggered by a valid transient user gesture,
10798 // or also the load originates from external, then we pass that information on
10799 // to the loadinfo, which allows e.g. setting Sec-Fetch-User request headers.
10800 if (aLoadState->HasValidUserGestureActivation() ||
10801 aLoadState->HasLoadFlags(LOAD_FLAGS_FROM_EXTERNAL)) {
10802 loadInfo->SetHasValidUserGestureActivation(true);
10803 aLoadState->SetTextDirectiveUserActivation(true);
10804 }
10805
10806 loadInfo->SetTextDirectiveUserActivation(
10807 aLoadState->GetTextDirectiveUserActivation());
10808
10809 loadInfo->SetTriggeringWindowId(aLoadState->TriggeringWindowId());
10810 loadInfo->SetTriggeringStorageAccess(aLoadState->TriggeringStorageAccess());
10811 loadInfo->SetTriggeringSandboxFlags(aLoadState->TriggeringSandboxFlags());
10812 net::ClassificationFlags flags = aLoadState->TriggeringClassificationFlags();
10813 loadInfo->SetTriggeringFirstPartyClassificationFlags(flags.firstPartyFlags);
10814 loadInfo->SetTriggeringThirdPartyClassificationFlags(flags.thirdPartyFlags);
10815 loadInfo->SetIsMetaRefresh(aLoadState->IsMetaRefresh());
10816
10817 uint32_t cacheKey = 0;
10818 if (aCacheKey) {
10819 cacheKey = *aCacheKey;
10820 } else if (mozilla::SessionHistoryInParent()) {
10821 if (mLoadingEntry) {
10822 cacheKey = mLoadingEntry->mInfo.GetCacheKey();
10823 } else if (mActiveEntry) { // for reload cases
10824 cacheKey = mActiveEntry->GetCacheKey();
10825 }
10826 } else {
10827 if (mLSHE) {
10828 cacheKey = mLSHE->GetCacheKey();
10829 } else if (mOSHE) { // for reload cases
10830 cacheKey = mOSHE->GetCacheKey();
10831 }
10832 }
10833
10834 bool uriModified;
10835 if (mLSHE || mLoadingEntry) {
10836 if (mLoadingEntry) {
10837 uriModified = mLoadingEntry->mInfo.GetURIWasModified();
10838 } else {
10839 uriModified = mLSHE->GetURIWasModified();
10840 }
10841 } else {
10842 uriModified = false;
10843 }
10844
10845 bool isEmbeddingBlockedError = false;
10846 if (mFailedChannel) {
10847 nsresult status;
10848 mFailedChannel->GetStatus(&status);
10849 isEmbeddingBlockedError = status == NS_ERROR_XFO_VIOLATION ||
10850 status == NS_ERROR_CSP_FRAME_ANCESTOR_VIOLATION;
10851 }
10852
10853 nsLoadFlags loadFlags = aLoadState->CalculateChannelLoadFlags(
10854 mBrowsingContext, uriModified, Some(isEmbeddingBlockedError));
10855
10856 nsCOMPtr<nsIChannel> channel;
10857 if (DocumentChannel::CanUseDocumentChannel(uri) &&
10858 !isAboutBlankLoadOntoInitialAboutBlank) {
10859 channel = DocumentChannel::CreateForDocument(
10860 aLoadState, loadInfo, loadFlags, this, cacheKey, uriModified,
10861 isEmbeddingBlockedError);
10862 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", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 10862); AnnotateMozCrashReason("MOZ_ASSERT" "(" "channel" ")"
); do { MOZ_CrashSequence(__null, 10862); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
10863
10864 // Disable keyword fixup when using DocumentChannel, since
10865 // DocumentLoadListener will handle this for us (in the parent process).
10866 mAllowKeywordFixup = false;
10867 } else if (!CreateAndConfigureRealChannelForLoadState(
10868 mBrowsingContext, aLoadState, loadInfo, this, this,
10869 GetOriginAttributes(), loadFlags, cacheKey, rv,
10870 getter_AddRefs(channel))) {
10871 return rv;
10872 }
10873
10874 // Make sure to give the caller a channel if we managed to create one
10875 // This is important for correct error page/session history interaction
10876 if (aRequest) {
10877 NS_ADDREF(*aRequest = channel)(*aRequest = channel)->AddRef();
10878 }
10879
10880 const nsACString& typeHint = aLoadState->TypeHint();
10881 if (!typeHint.IsVoid()) {
10882 mContentTypeHint = typeHint;
10883 } else {
10884 mContentTypeHint.Truncate();
10885 }
10886
10887 // Load attributes depend on load type...
10888 if (mLoadType == LOAD_RELOAD_CHARSET_CHANGE) {
10889 // Use SetAllowStaleCacheContent (not LOAD_FROM_CACHE flag) since we
10890 // only want to force cache load for this channel, not the whole
10891 // loadGroup.
10892 nsCOMPtr<nsICacheInfoChannel> cachingChannel = do_QueryInterface(channel);
10893 if (cachingChannel) {
10894 cachingChannel->SetAllowStaleCacheContent(true);
10895 }
10896 }
10897
10898 uint32_t openFlags =
10899 nsDocShell::ComputeURILoaderFlags(mBrowsingContext, mLoadType);
10900 return OpenInitializedChannel(channel, uriLoader, openFlags);
10901}
10902
10903static nsresult AppendSegmentToString(nsIInputStream* aIn, void* aClosure,
10904 const char* aFromRawSegment,
10905 uint32_t aToOffset, uint32_t aCount,
10906 uint32_t* aWriteCount) {
10907 // aFromSegment now contains aCount bytes of data.
10908
10909 nsAutoCString* buf = static_cast<nsAutoCString*>(aClosure);
10910 buf->Append(aFromRawSegment, aCount);
10911
10912 // Indicate that we have consumed all of aFromSegment
10913 *aWriteCount = aCount;
10914 return NS_OK;
10915}
10916
10917/* static */ nsresult nsDocShell::AddHeadersToChannel(
10918 nsIInputStream* aHeadersData, nsIChannel* aGenericChannel) {
10919 nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(aGenericChannel);
10920 NS_ENSURE_STATE(httpChannel)do { if ((__builtin_expect(!!(!(httpChannel)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "httpChannel" ") failed"
, nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 10920); return NS_ERROR_UNEXPECTED; } } while (false)
;
10921
10922 uint32_t numRead;
10923 nsAutoCString headersString;
10924 nsresult rv = aHeadersData->ReadSegments(
10925 AppendSegmentToString, &headersString, UINT32_MAX(4294967295U), &numRead);
10926 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, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 10926); return rv; } } while (false)
;
10927
10928 // used during the manipulation of the String from the InputStream
10929 nsAutoCString headerName;
10930 nsAutoCString headerValue;
10931 int32_t crlf;
10932 int32_t colon;
10933
10934 //
10935 // Iterate over the headersString: for each "\r\n" delimited chunk,
10936 // add the value as a header to the nsIHttpChannel
10937 //
10938
10939 static const char kWhitespace[] = "\b\t\r\n ";
10940 while (true) {
10941 crlf = headersString.Find("\r\n");
10942 if (crlf == kNotFound) {
10943 return NS_OK;
10944 }
10945
10946 const nsACString& oneHeader = StringHead(headersString, crlf);
10947
10948 colon = oneHeader.FindChar(':');
10949 if (colon == kNotFound) {
10950 return NS_ERROR_UNEXPECTED;
10951 }
10952
10953 headerName = StringHead(oneHeader, colon);
10954 headerValue = Substring(oneHeader, colon + 1);
10955
10956 headerName.Trim(kWhitespace);
10957 headerValue.Trim(kWhitespace);
10958
10959 headersString.Cut(0, crlf + 2);
10960
10961 //
10962 // FINALLY: we can set the header!
10963 //
10964
10965 rv = httpChannel->SetRequestHeader(headerName, headerValue, true);
10966 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, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 10966); return rv; } } while (false)
;
10967 }
10968
10969 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" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 10969); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "oops" ")"); do { MOZ_CrashSequence
(__null, 10969); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
10970 return NS_ERROR_UNEXPECTED;
10971}
10972
10973/* static */ uint32_t nsDocShell::ComputeURILoaderFlags(
10974 BrowsingContext* aBrowsingContext, uint32_t aLoadType,
10975 bool aIsDocumentLoad) {
10976 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"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 10976);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "aBrowsingContext" ")"
); do { MOZ_CrashSequence(__null, 10976); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
10977
10978 uint32_t openFlags = 0;
10979 if (aLoadType == LOAD_LINK) {
10980 openFlags |= nsIURILoader::IS_CONTENT_PREFERRED;
10981 }
10982 if (!aBrowsingContext->GetAllowContentRetargeting()) {
10983 openFlags |= nsIURILoader::DONT_RETARGET;
10984 }
10985
10986 if (!aIsDocumentLoad) {
10987 openFlags |= nsIURILoader::IS_OBJECT_EMBED;
10988
10989 // Unless the pref is set, object/embed loads always specify DONT_RETARGET.
10990 // See bug 1868001 for details.
10991 if (!StaticPrefs::dom_navigation_object_embed_allow_retargeting()) {
10992 openFlags |= nsIURILoader::DONT_RETARGET;
10993 }
10994 }
10995
10996 return openFlags;
10997}
10998
10999nsresult nsDocShell::OpenInitializedChannel(nsIChannel* aChannel,
11000 nsIURILoader* aURILoader,
11001 uint32_t aOpenFlags) {
11002 nsresult rv = NS_OK;
11003
11004 // If anything fails here, make sure to clear our initial ClientSource.
11005 auto cleanupInitialClient =
11006 MakeScopeExit([&] { mInitialClientSource.reset(); });
11007
11008 nsCOMPtr<nsPIDOMWindowOuter> win = GetWindow();
11009 NS_ENSURE_TRUE(win, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(win)), 0))) { NS_DebugBreak(NS_DEBUG_WARNING
, "NS_ENSURE_TRUE(" "win" ") failed", nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 11009); return NS_ERROR_FAILURE; } } while (false)
;
11010
11011 MaybeCreateInitialClientSource();
11012
11013 // Let the client channel helper know if we are using DocumentChannel,
11014 // since redirects get handled in the parent process in that case.
11015 RefPtr<net::DocumentChannel> docChannel = do_QueryObject(aChannel);
11016 if (docChannel && XRE_IsContentProcess()) {
11017 // Tell the content process nsDocumentOpenInfo to not try to do
11018 // any sort of targeting.
11019 aOpenFlags |= nsIURILoader::DONT_RETARGET;
11020 }
11021
11022 // Since we are loading a document we need to make sure the proper reserved
11023 // and initial client data is stored on the nsILoadInfo. The
11024 // ClientChannelHelper does this and ensures that it is propagated properly
11025 // on redirects. We pass no reserved client here so that the helper will
11026 // create the reserved ClientSource if necessary.
11027 Maybe<ClientInfo> noReservedClient;
11028 if (docChannel) {
11029 // When using DocumentChannel, all redirect handling is done in the parent,
11030 // so we just need the child variant to watch for the internal redirect
11031 // to the final channel.
11032 rv = AddClientChannelHelperInChild(aChannel,
11033 GetMainThreadSerialEventTarget());
11034 docChannel->SetInitialClientInfo(GetInitialClientInfo());
11035 } else {
11036 rv = AddClientChannelHelper(aChannel, std::move(noReservedClient),
11037 GetInitialClientInfo(),
11038 GetMainThreadSerialEventTarget());
11039 }
11040 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, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 11040); return rv; } } while (false)
;
11041
11042 rv = aURILoader->OpenURI(aChannel, aOpenFlags, this);
11043 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, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 11043); return rv; } } while (false)
;
11044
11045 // We're about to load a new page and it may take time before necko
11046 // gives back any data, so main thread might have a chance to process a
11047 // collector slice
11048 nsJSContext::MaybeRunNextCollectorSlice(this, JS::GCReason::DOCSHELL);
11049
11050 // Success. Keep the initial ClientSource if it exists.
11051 cleanupInitialClient.release();
11052
11053 return NS_OK;
11054}
11055
11056nsresult nsDocShell::OpenRedirectedChannel(nsDocShellLoadState* aLoadState) {
11057 nsCOMPtr<nsIChannel> channel = aLoadState->GetPendingRedirectedChannel();
11058 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", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 11058); AnnotateMozCrashReason("MOZ_ASSERT" "(" "channel" ")"
); do { MOZ_CrashSequence(__null, 11058); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
11059
11060 // If anything fails here, make sure to clear our initial ClientSource.
11061 auto cleanupInitialClient =
11062 MakeScopeExit([&] { mInitialClientSource.reset(); });
11063
11064 nsCOMPtr<nsPIDOMWindowOuter> win = GetWindow();
11065 NS_ENSURE_TRUE(win, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(win)), 0))) { NS_DebugBreak(NS_DEBUG_WARNING
, "NS_ENSURE_TRUE(" "win" ") failed", nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 11065); return NS_ERROR_FAILURE; } } while (false)
;
11066
11067 MaybeCreateInitialClientSource();
11068
11069 nsCOMPtr<nsILoadInfo> loadInfo = channel->LoadInfo();
11070
11071 LoadInfo* li = static_cast<LoadInfo*>(loadInfo.get());
11072 if (loadInfo->GetExternalContentPolicyType() ==
11073 ExtContentPolicy::TYPE_DOCUMENT) {
11074 li->UpdateBrowsingContextID(mBrowsingContext->Id());
11075 } else if (loadInfo->GetExternalContentPolicyType() ==
11076 ExtContentPolicy::TYPE_SUBDOCUMENT) {
11077 li->UpdateFrameBrowsingContextID(mBrowsingContext->Id());
11078 }
11079
11080 // If we did a process switch, then we should have an existing allocated
11081 // ClientInfo, so we just need to allocate a corresponding ClientSource.
11082 CreateReservedSourceIfNeeded(channel, GetMainThreadSerialEventTarget());
11083
11084 uint32_t documentOpenInfoFlags = nsIURILoader::DONT_RETARGET;
11085 if (loadInfo->GetExternalContentPolicyType() ==
11086 ExtContentPolicy::TYPE_OBJECT) {
11087 documentOpenInfoFlags |= nsIURILoader::IS_OBJECT_EMBED;
11088 }
11089
11090 RefPtr<nsDocumentOpenInfo> loader =
11091 new nsDocumentOpenInfo(this, documentOpenInfoFlags, nullptr);
11092 channel->SetLoadGroup(mLoadGroup);
11093
11094 MOZ_ALWAYS_SUCCEEDS(loader->Prepare())do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(loader->Prepare())), 1)))), 1))) { } else { do { do { } while
(false); MOZ_ReportCrash("" "NS_SUCCEEDED(loader->Prepare())"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 11094);
AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED(loader->Prepare())"
")"); do { MOZ_CrashSequence(__null, 11094); __attribute__((
nomerge)) ::abort(); } while (false); } while (false); } } while
(false)
;
11095
11096 nsresult rv = NS_OK;
11097 if (XRE_IsParentProcess()) {
11098 // If we're in the parent, the we don't have an nsIChildChannel, just
11099 // the original channel, which is already open in this process.
11100
11101 // DocumentLoadListener expects to get an nsIParentChannel, so
11102 // we create a wrapper around the channel and nsIStreamListener
11103 // that forwards functionality as needed, and then we register
11104 // it under the provided identifier.
11105 RefPtr<ParentChannelWrapper> wrapper =
11106 new ParentChannelWrapper(channel, loader);
11107 wrapper->Register(aLoadState->GetPendingRedirectChannelRegistrarId());
11108
11109 mLoadGroup->AddRequest(channel, nullptr);
11110 } else if (nsCOMPtr<nsIChildChannel> childChannel =
11111 do_QueryInterface(channel)) {
11112 // Our channel was redirected from another process, so doesn't need to
11113 // be opened again. However, it does need its listener hooked up
11114 // correctly.
11115 rv = childChannel->CompleteRedirectSetup(loader);
11116 } else {
11117 // It's possible for the redirected channel to not implement
11118 // nsIChildChannel and be entirely local (like srcdoc). In that case we
11119 // can just open the local instance and it will work.
11120 rv = channel->AsyncOpen(loader);
11121 }
11122 if (rv == NS_ERROR_NO_CONTENT) {
11123 return NS_OK;
11124 }
11125 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, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 11125); return rv; } } while (false)
;
11126
11127 // Success. Keep the initial ClientSource if it exists.
11128 cleanupInitialClient.release();
11129 return NS_OK;
11130}
11131
11132// https://html.spec.whatwg.org/#scrolling-to-a-fragment
11133nsresult nsDocShell::ScrollToAnchor(bool aCurHasRef, bool aNewHasRef,
11134 nsACString& aNewHash, uint32_t aLoadType) {
11135 if (!mCurrentURI) {
11136 return NS_OK;
11137 }
11138
11139 RefPtr<PresShell> presShell = GetPresShell();
11140 if (!presShell) {
11141 // If we failed to get the shell, or if there is no shell,
11142 // nothing left to do here.
11143 return NS_OK;
11144 }
11145
11146 ScrollContainerFrame* rootScroll = presShell->GetRootScrollContainerFrame();
11147 if (rootScroll) {
11148 rootScroll->ClearDidHistoryRestore();
11149 }
11150
11151 // If it's a load from history, we don't have any anchor jumping to do.
11152 // Scrollbar position will be restored by the caller based on positions stored
11153 // in session history.
11154 bool scroll = aLoadType != LOAD_HISTORY && aLoadType != LOAD_RELOAD_NORMAL;
11155 // If the load contains text directives, try to apply them. This may fail if
11156 // the load is a same-document load that was initiated before the document was
11157 // fully loaded and the target is not yet included in the DOM tree.
11158 // For this case, the `uninvokedTextDirectives` are not cleared, so that
11159 // `Document::ScrollToRef()` can re-apply the text directive.
11160 // `Document::ScrollToRef()` is (presumably) the second "async" call mentioned
11161 // in sec. 7.4.2.3.3 in the HTML spec, "Fragment navigations":
11162 // https://html.spec.whatwg.org/#scroll-to-fragid:~:text=This%20algorithm%20will%20be%20called%20twice
11163
11164 const RefPtr fragmentDirective = GetDocument()->FragmentDirective();
11165 const nsTArray<RefPtr<nsRange>> textDirectiveRanges =
11166 fragmentDirective->FindTextFragmentsInDocument();
11167 fragmentDirective->HighlightTextDirectives(textDirectiveRanges);
11168 const bool scrollToTextDirective =
11169 !textDirectiveRanges.IsEmpty() &&
11170 fragmentDirective->IsTextDirectiveAllowedToBeScrolledTo();
11171 const RefPtr<nsRange> textDirectiveToScroll =
11172 scrollToTextDirective ? textDirectiveRanges[0] : nullptr;
11173
11174 // If we have no new anchor, we do not want to scroll, unless there is a
11175 // current anchor and we are doing a history load. So return if we have no
11176 // new anchor, and there is no current anchor or the load is not a history
11177 // load.
11178 if ((!aCurHasRef || aLoadType != LOAD_HISTORY) && !aNewHasRef &&
11179 !scrollToTextDirective) {
11180 return NS_OK;
11181 }
11182
11183 // Both the new and current URIs refer to the same page. We can now
11184 // browse to the hash stored in the new URI.
11185
11186 if (aNewHash.IsEmpty() && !scrollToTextDirective) {
11187 // 2. If fragment is the empty string, then return the special value top of
11188 // the document.
11189 //
11190 // Tell the shell it's at an anchor without scrolling.
11191 presShell->GoToAnchor(u""_ns, nullptr, false);
11192
11193 if (scroll) {
11194 // Scroll to the top of the page. Ignore the return value; failure to
11195 // scroll here (e.g. if there is no root scrollframe) is not grounds for
11196 // canceling the load!
11197 SetCurScrollPosEx(0, 0);
11198 }
11199
11200 return NS_OK;
11201 }
11202
11203 // 3. Let potentialIndicatedElement be the result of finding a potential
11204 // indicated element given document and fragment.
11205 NS_ConvertUTF8toUTF16 uStr(aNewHash);
11206
11207 MOZ_ASSERT(!uStr.IsEmpty() || scrollToTextDirective)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!uStr.IsEmpty() || scrollToTextDirective)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(!uStr.IsEmpty() || scrollToTextDirective))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("!uStr.IsEmpty() || scrollToTextDirective"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 11207);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "!uStr.IsEmpty() || scrollToTextDirective"
")"); do { MOZ_CrashSequence(__null, 11207); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11208
11209 auto rv = presShell->GoToAnchor(uStr, textDirectiveToScroll, scroll,
11210 ScrollFlags::ScrollSmoothAuto);
11211
11212 // 4. If potentialIndicatedElement is not null, then return
11213 // potentialIndicatedElement.
11214 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
11215 return NS_OK;
11216 }
11217
11218 // 5. Let fragmentBytes be the result of percent-decoding fragment.
11219 nsAutoCString fragmentBytes;
11220 const bool unescaped = NS_UnescapeURL(aNewHash.Data(), aNewHash.Length(),
11221 /* aFlags = */ 0, fragmentBytes);
11222
11223 if (!unescaped) {
11224 // Another attempt is only necessary if characters were unescaped.
11225 return NS_OK;
11226 }
11227
11228 if (fragmentBytes.IsEmpty()) {
11229 // When aNewHash contains "%00", the unescaped string may be empty, and
11230 // GoToAnchor asserts if we ask it to scroll to an empty ref.
11231 presShell->GoToAnchor(u""_ns, nullptr, false);
11232 return NS_OK;
11233 }
11234
11235 // 6. Let decodedFragment be the result of running UTF-8 decode without BOM on
11236 // fragmentBytes.
11237 nsAutoString decodedFragment;
11238 rv = UTF_8_ENCODING->DecodeWithoutBOMHandling(fragmentBytes, decodedFragment);
11239 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, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 11239); return rv; } } while (false)
;
11240
11241 // 7. Set potentialIndicatedElement to the result of finding a potential
11242 // indicated element given document and decodedFragment.
11243 //
11244 // Ignore the return value of GoToAnchor, since it will return an error if
11245 // there is no such anchor in the document, which is actually a success
11246 // condition for us (we want to update the session history with the new URI no
11247 // matter whether we actually scrolled somewhere).
11248 presShell->GoToAnchor(decodedFragment, nullptr, scroll,
11249 ScrollFlags::ScrollSmoothAuto);
11250
11251 return NS_OK;
11252}
11253
11254bool nsDocShell::OnNewURI(nsIURI* aURI, nsIChannel* aChannel,
11255 nsIPrincipal* aTriggeringPrincipal,
11256 nsIPrincipal* aPrincipalToInherit,
11257 nsIPrincipal* aPartitionedPrincipalToInherit,
11258 nsIContentSecurityPolicy* aCsp,
11259 bool aAddToGlobalHistory, bool aCloneSHChildren) {
11260 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" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 11260); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aURI" ") ("
"uri is null" ")"); do { MOZ_CrashSequence(__null, 11260); __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
;
11261 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"
")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 11261
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aChannel || !aTriggeringPrincipal"
") (" "Shouldn't have both set" ")"); do { MOZ_CrashSequence
(__null, 11261); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
11262
11263 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)"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 11264);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aPrincipalToInherit || (aPrincipalToInherit && aTriggeringPrincipal)"
")"); do { MOZ_CrashSequence(__null, 11264); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
11264 (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)"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 11264);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aPrincipalToInherit || (aPrincipalToInherit && aTriggeringPrincipal)"
")"); do { MOZ_CrashSequence(__null, 11264); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11265
11266#if defined(DEBUG1)
11267 if (MOZ_LOG_TEST(gDocShellLog, LogLevel::Debug)(__builtin_expect(!!(mozilla::detail::log_test(gDocShellLog, LogLevel
::Debug)), 0))
) {
11268 nsAutoCString chanName;
11269 if (aChannel) {
11270 aChannel->GetName(chanName);
11271 } else {
11272 chanName.AssignLiteral("<no channel>");
11273 }
11274
11275 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)
11276 ("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)
11277 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)
;
11278 }
11279#endif
11280
11281 bool equalUri = false;
11282
11283 // Get the post data and the HTTP response code from the channel.
11284 uint32_t responseStatus = 0;
11285 nsCOMPtr<nsIInputStream> inputStream;
11286 if (aChannel) {
11287 nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(aChannel));
11288
11289 // Check if the HTTPChannel is hiding under a multiPartChannel
11290 if (!httpChannel) {
11291 GetHttpChannel(aChannel, getter_AddRefs(httpChannel));
11292 }
11293
11294 if (httpChannel) {
11295 nsCOMPtr<nsIUploadChannel> uploadChannel(do_QueryInterface(httpChannel));
11296 if (uploadChannel) {
11297 uploadChannel->GetUploadStream(getter_AddRefs(inputStream));
11298 }
11299
11300 // If the response status indicates an error, unlink this session
11301 // history entry from any entries sharing its document.
11302 nsresult rv = httpChannel->GetResponseStatus(&responseStatus);
11303 if (mLSHE && NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && responseStatus >= 400) {
11304 mLSHE->AbandonBFCacheEntry();
11305 // FIXME Do the same for mLoadingEntry
11306 }
11307 }
11308 }
11309
11310 // Determine if this type of load should update history.
11311 bool updateGHistory = ShouldUpdateGlobalHistory(mLoadType);
11312
11313 // We don't update session history on reload unless we're loading
11314 // an iframe in shift-reload case.
11315 bool updateSHistory = mBrowsingContext->ShouldUpdateSessionHistory(mLoadType);
11316
11317 // Create SH Entry (mLSHE) only if there is a SessionHistory object in the
11318 // root browsing context.
11319 // FIXME If session history in the parent is enabled then we only do this if
11320 // the session history object is in process, otherwise we can't really
11321 // use the mLSHE anyway. Once session history is only stored in the
11322 // parent then this code will probably be removed anyway.
11323 RefPtr<ChildSHistory> rootSH = GetRootSessionHistory();
11324 if (!rootSH) {
11325 updateSHistory = false;
11326 updateGHistory = false; // XXX Why global history too?
11327 }
11328
11329 // Check if the url to be loaded is the same as the one already loaded.
11330 if (mCurrentURI) {
11331 aURI->Equals(mCurrentURI, &equalUri);
11332 }
11333
11334#ifdef DEBUG1
11335 bool shAvailable = (rootSH != nullptr);
11336
11337 // XXX This log message is almost useless because |updateSHistory|
11338 // and |updateGHistory| are not correct at this point.
11339
11340 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)
11341 (" 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)
11342 " 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)
11343 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)
;
11344#endif
11345
11346 /* If the url to be loaded is the same as the one already there,
11347 * and the original loadType is LOAD_NORMAL, LOAD_LINK, or
11348 * LOAD_STOP_CONTENT, set loadType to LOAD_NORMAL_REPLACE so that
11349 * AddToSessionHistory() won't mess with the current SHEntry and
11350 * if this page has any frame children, it also will be handled
11351 * properly. see bug 83684
11352 *
11353 * NB: If mOSHE is null but we have a current URI, then it probably
11354 * means that we must be at the transient about:blank content viewer;
11355 * we should let the normal load continue, since there's nothing to
11356 * replace. Sometimes this happens after a session restore (eg process
11357 * switch) and mCurrentURI is not about:blank; we assume we can let the load
11358 * continue (Bug 1301399).
11359 *
11360 * XXX Hopefully changing the loadType at this time will not hurt
11361 * anywhere. The other way to take care of sequentially repeating
11362 * frameset pages is to add new methods to nsIDocShellTreeItem.
11363 * Hopefully I don't have to do that.
11364 */
11365 if (equalUri &&
11366 (mozilla::SessionHistoryInParent() ? !!mActiveEntry : !!mOSHE) &&
11367 (mLoadType == LOAD_NORMAL || mLoadType == LOAD_LINK ||
11368 mLoadType == LOAD_STOP_CONTENT) &&
11369 !inputStream) {
11370 mLoadType = LOAD_NORMAL_REPLACE;
11371 }
11372
11373 // If this is a refresh to the currently loaded url, we don't
11374 // have to update session or global history.
11375 if (mLoadType == LOAD_REFRESH && !inputStream && equalUri) {
11376 SetHistoryEntryAndUpdateBC(Some<nsISHEntry*>(mOSHE), Nothing());
11377 }
11378
11379 /* If the user pressed shift-reload, cache will create a new cache key
11380 * for the page. Save the new cacheKey in Session History.
11381 * see bug 90098
11382 */
11383 if (aChannel && IsForceReloadType(mLoadType)) {
11384 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!" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 11386); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!updateSHistory || IsSubframe()"
") (" "We shouldn't be updating session history for forced" " reloads unless we're in a newly created iframe!"
")"); do { MOZ_CrashSequence(__null, 11386); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
11385 "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!" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 11386); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!updateSHistory || IsSubframe()"
") (" "We shouldn't be updating session history for forced" " reloads unless we're in a newly created iframe!"
")"); do { MOZ_CrashSequence(__null, 11386); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
11386 " 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!" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 11386); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!updateSHistory || IsSubframe()"
") (" "We shouldn't be updating session history for forced" " reloads unless we're in a newly created iframe!"
")"); do { MOZ_CrashSequence(__null, 11386); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11387
11388 nsCOMPtr<nsICacheInfoChannel> cacheChannel(do_QueryInterface(aChannel));
11389 uint32_t cacheKey = 0;
11390 // Get the Cache Key and store it in SH.
11391 if (cacheChannel) {
11392 cacheChannel->GetCacheKey(&cacheKey);
11393 }
11394 // If we already have a loading history entry, store the new cache key
11395 // in it. Otherwise, since we're doing a reload and won't be updating
11396 // our history entry, store the cache key in our current history entry.
11397 SetCacheKeyOnHistoryEntry(mLSHE ? mLSHE : mOSHE, cacheKey);
11398
11399 if (!mozilla::SessionHistoryInParent()) {
11400 // Since we're force-reloading, clear all the sub frame history.
11401 ClearFrameHistory(mLSHE);
11402 ClearFrameHistory(mOSHE);
11403 }
11404 }
11405
11406 if (!mozilla::SessionHistoryInParent()) {
11407 // Clear subframe history on refresh.
11408 // XXX: history.go(0) won't go this path as mLoadType is LOAD_HISTORY in
11409 // this case. One should re-validate after bug 1331865 fixed.
11410 if (mLoadType == LOAD_REFRESH) {
11411 ClearFrameHistory(mLSHE);
11412 ClearFrameHistory(mOSHE);
11413 }
11414
11415 if (updateSHistory) {
11416 // Update session history if necessary...
11417 if (!mLSHE && (mItemType == typeContent) && mURIResultedInDocument) {
11418 /* This is a fresh page getting loaded for the first time
11419 *.Create a Entry for it and add it to SH, if this is the
11420 * rootDocShell
11421 */
11422 (void)AddToSessionHistory(aURI, aChannel, aTriggeringPrincipal,
11423 aPrincipalToInherit,
11424 aPartitionedPrincipalToInherit, aCsp,
11425 aCloneSHChildren, getter_AddRefs(mLSHE));
11426 }
11427 } else if (GetSessionHistory() && mLSHE && mURIResultedInDocument) {
11428 // Even if we don't add anything to SHistory, ensure the current index
11429 // points to the same SHEntry as our mLSHE.
11430
11431 GetSessionHistory()->LegacySHistory()->EnsureCorrectEntryAtCurrIndex(
11432 mLSHE);
11433 }
11434 }
11435
11436 // If this is a POST request, we do not want to include this in global
11437 // history.
11438 if (ShouldAddURIVisit(aChannel) && updateGHistory && aAddToGlobalHistory &&
11439 !net::ChannelIsPost(aChannel)) {
11440 nsCOMPtr<nsIURI> previousURI;
11441 uint32_t previousFlags = 0;
11442
11443 if (mLoadType & LOAD_CMD_RELOAD) {
11444 // On a reload request, we don't set redirecting flags.
11445 previousURI = aURI;
11446 } else {
11447 ExtractLastVisit(aChannel, getter_AddRefs(previousURI), &previousFlags);
11448 }
11449
11450 AddURIVisit(aURI, previousURI, previousFlags, responseStatus);
11451 }
11452
11453 // If this was a history load or a refresh, or it was a history load but
11454 // later changed to LOAD_NORMAL_REPLACE due to redirection, update the index
11455 // in session history.
11456 if (!mozilla::SessionHistoryInParent() && rootSH &&
11457 ((mLoadType & (LOAD_CMD_HISTORY | LOAD_CMD_RELOAD)) ||
11458 mLoadType == LOAD_NORMAL_REPLACE || mLoadType == LOAD_REFRESH_REPLACE)) {
11459 mPreviousEntryIndex = rootSH->Index();
11460 if (!mozilla::SessionHistoryInParent()) {
11461 rootSH->LegacySHistory()->UpdateIndex();
11462 }
11463 mLoadedEntryIndex = rootSH->Index();
11464 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)
11465 ("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)
11466 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)
;
11467 }
11468
11469 // aCloneSHChildren exactly means "we are not loading a new document".
11470 uint32_t locationFlags =
11471 aCloneSHChildren ? uint32_t(LOCATION_CHANGE_SAME_DOCUMENT) : 0;
11472
11473 bool onLocationChangeNeeded =
11474 SetCurrentURI(aURI, aChannel, false,
11475 /* aIsInitialAboutBlank */ false, locationFlags);
11476 // Make sure to store the referrer from the channel, if any
11477 nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(aChannel));
11478 if (httpChannel) {
11479 mReferrerInfo = httpChannel->GetReferrerInfo();
11480 }
11481 return onLocationChangeNeeded;
11482}
11483
11484Maybe<Wireframe> nsDocShell::GetWireframe() {
11485 const bool collectWireFrame =
11486 mozilla::SessionHistoryInParent() &&
11487 StaticPrefs::browser_history_collectWireframes() &&
11488 mBrowsingContext->IsTopContent() && mActiveEntry;
11489
11490 if (!collectWireFrame) {
11491 return Nothing();
11492 }
11493
11494 RefPtr<Document> doc = mDocumentViewer->GetDocument();
11495 Nullable<Wireframe> wireframe;
11496 doc->GetWireframeWithoutFlushing(false, wireframe);
11497 if (wireframe.IsNull()) {
11498 return Nothing();
11499 }
11500 return Some(wireframe.Value());
11501}
11502
11503bool nsDocShell::CollectWireframe() {
11504 Maybe<Wireframe> wireframe = GetWireframe();
11505 if (wireframe.isNothing()) {
11506 return false;
11507 }
11508
11509 if (XRE_IsParentProcess()) {
11510 SessionHistoryEntry* entry =
11511 mBrowsingContext->Canonical()->GetActiveSessionHistoryEntry();
11512 if (entry) {
11513 entry->SetWireframe(wireframe);
11514 }
11515 } else {
11516 mozilla::Unused
11517 << ContentChild::GetSingleton()->SendSessionHistoryEntryWireframe(
11518 mBrowsingContext, wireframe.ref());
11519 }
11520
11521 return true;
11522}
11523
11524//*****************************************************************************
11525// nsDocShell: Session History
11526//*****************************************************************************
11527
11528NS_IMETHODIMPnsresult
11529nsDocShell::AddState(JS::Handle<JS::Value> aData, const nsAString& aTitle,
11530 const nsAString& aURL, bool aReplace, JSContext* aCx) {
11531 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)
11532 ("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)
11533 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)
11534 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)
;
11535 // Implements History.pushState and History.replaceState
11536
11537 // Here's what we do, roughly in the order specified by HTML5. The specific
11538 // steps we are executing are at
11539 // <https://html.spec.whatwg.org/multipage/history.html#dom-history-pushstate>,
11540 // <https://html.spec.whatwg.org/#shared-history-push/replace-state-steps>,
11541 // and
11542 // <https://html.spec.whatwg.org/multipage/history.html#url-and-history-update-steps>.
11543 // This function basically implements #dom-history-pushstate and
11544 // UpdateURLAndHistory implements #url-and-history-update-steps.
11545 //
11546 // A. Serialize aData using structured clone. This is #dom-history-pushstate
11547 // step 5.
11548 // B. If the third argument is present, #dom-history-pushstate step 7.
11549 // 7.1. Resolve the url, relative to our document.
11550 // 7.2. If (a) fails, raise a SECURITY_ERR
11551 // 7.4. Compare the resulting absolute URL to the document's address. If
11552 // any part of the URLs difer other than the <path>, <query>, and
11553 // <fragment> components, raise a SECURITY_ERR and abort.
11554 // C. If !aReplace, #url-and-history-update-steps steps 2.1-2.3:
11555 // Remove from the session history all entries after the current entry,
11556 // as we would after a regular navigation, and save the current
11557 // entry's scroll position (bug 590573).
11558 // D. #url-and-history-update-steps step 2.4 or step 3. As apropriate,
11559 // either add a state object entry to the session history after the
11560 // current entry with the following properties, or modify the current
11561 // session history entry to set
11562 // a. cloned data as the state object,
11563 // b. if the third argument was present, the absolute URL found in
11564 // step 2
11565 // Also clear the new history entry's POST data (see bug 580069).
11566 // E. If aReplace is false (i.e. we're doing a pushState instead of a
11567 // replaceState), notify bfcache that we've navigated to a new page.
11568 // F. If the third argument is present, set the document's current address
11569 // to the absolute URL found in step B. This is
11570 // #url-and-history-update-steps step 4.
11571 //
11572 // It's important that this function not run arbitrary scripts after step A
11573 // and before completing step E. For example, if a script called
11574 // history.back() before we completed step E, bfcache might destroy an
11575 // active content viewer. Since EvictOutOfRangeDocumentViewers at the end of
11576 // step E might run script, we can't just put a script blocker around the
11577 // critical section.
11578 //
11579 // Note that we completely ignore the aTitle parameter.
11580
11581 nsresult rv;
11582
11583 RefPtr<Document> document = GetDocument();
11584 NS_ENSURE_TRUE(document, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(document)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "document" ") failed", nullptr
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 11584);
return NS_ERROR_FAILURE; } } while (false)
;
11585
11586 // Don't clobber the load type of an existing network load.
11587 Maybe<AutoRestore<uint32_t>> loadTypeResetter;
11588 if (StaticPrefs::
11589 docshell_shistory_sameDocumentNavigationOverridesLoadType() &&
11590 !document->NodePrincipal()->IsURIInPrefList(
11591 "docshell.shistory.sameDocumentNavigationOverridesLoadType."
11592 "forceDisable")) {
11593 loadTypeResetter.emplace(mLoadType);
11594 }
11595
11596 // pushState effectively becomes replaceState when we've started a network
11597 // load but haven't adopted its document yet. This mirrors what we do with
11598 // changes to the hash at this stage of the game.
11599 if (JustStartedNetworkLoad()) {
11600 if (!loadTypeResetter.isSome()) {
11601 loadTypeResetter.emplace(mLoadType);
11602 }
11603 aReplace = true;
11604 }
11605
11606 // Step A: Serialize aData using structured clone.
11607 // https://html.spec.whatwg.org/multipage/history.html#dom-history-pushstate
11608 // step 5.
11609 nsCOMPtr<nsIStructuredCloneContainer> scContainer;
11610
11611 // scContainer->Init might cause arbitrary JS to run, and this code might
11612 // navigate the page we're on, potentially to a different origin! (bug
11613 // 634834) To protect against this, we abort if our principal changes due
11614 // to the InitFromJSVal() call.
11615 {
11616 RefPtr<Document> origDocument = GetDocument();
11617 if (!origDocument) {
11618 return NS_ERROR_DOM_SECURITY_ERR;
11619 }
11620 nsCOMPtr<nsIPrincipal> origPrincipal = origDocument->NodePrincipal();
11621
11622 scContainer = new nsStructuredCloneContainer();
11623 rv = scContainer->InitFromJSVal(aData, aCx);
11624 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, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 11624); return rv; } } while (false)
;
11625
11626 RefPtr<Document> newDocument = GetDocument();
11627 if (!newDocument) {
11628 return NS_ERROR_DOM_SECURITY_ERR;
11629 }
11630 nsCOMPtr<nsIPrincipal> newPrincipal = newDocument->NodePrincipal();
11631
11632 bool principalsEqual = false;
11633 origPrincipal->Equals(newPrincipal, &principalsEqual);
11634 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, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 11634); return NS_ERROR_DOM_SECURITY_ERR; } } while (false)
;
11635 }
11636
11637 // Check that the state object isn't too long.
11638 int32_t maxStateObjSize = StaticPrefs::browser_history_maxStateObjectSize();
11639 if (maxStateObjSize < 0) {
11640 maxStateObjSize = 0;
11641 }
11642
11643 uint64_t scSize;
11644 rv = scContainer->GetSerializedNBytes(&scSize);
11645 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, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 11645); return rv; } } while (false)
;
11646
11647 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, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 11647); return NS_ERROR_ILLEGAL_VALUE; } } while (false)
;
11648
11649 // Step B: Resolve aURL.
11650 // https://html.spec.whatwg.org/multipage/history.html#dom-history-pushstate
11651 // step 7.
11652 bool equalURIs = true;
11653 nsCOMPtr<nsIURI> currentURI;
11654 if (mCurrentURI) {
11655 currentURI = nsIOService::CreateExposableURI(mCurrentURI);
11656 } else {
11657 currentURI = mCurrentURI;
11658 }
11659 nsCOMPtr<nsIURI> newURI;
11660 if (aURL.Length() == 0) {
11661 newURI = currentURI;
11662 } else {
11663 // 7.1: Resolve aURL relative to mURI
11664
11665 nsIURI* docBaseURI = document->GetDocBaseURI();
11666 if (!docBaseURI) {
11667 return NS_ERROR_FAILURE;
11668 }
11669
11670 nsAutoCString spec;
11671 docBaseURI->GetSpec(spec);
11672
11673 rv = NS_NewURI(getter_AddRefs(newURI), aURL,
11674 document->GetDocumentCharacterSet(), docBaseURI);
11675
11676 // 7.2: If 2a fails, raise a SECURITY_ERR
11677 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
11678 return NS_ERROR_DOM_SECURITY_ERR;
11679 }
11680
11681 if (!document->CanRewriteURL(newURI)) {
11682 return NS_ERROR_DOM_SECURITY_ERR;
11683 }
11684
11685 if (currentURI) {
11686 currentURI->Equals(newURI, &equalURIs);
11687 } else {
11688 equalURIs = false;
11689 }
11690
11691 } // end of same-origin check
11692
11693 // https://html.spec.whatwg.org/#shared-history-push/replace-state-steps
11694 // Step 8
11695 if (nsCOMPtr<nsPIDOMWindowInner> window = document->GetInnerWindow()) {
11696 if (RefPtr<Navigation> navigation = window->Navigation()) {
11697 bool shouldContinue = navigation->FirePushReplaceReloadNavigateEvent(
11698 aCx, aReplace ? NavigationType::Replace : NavigationType::Push,
11699 newURI,
11700 /* aIsSameDocument */ true, /* aIsSync */ true,
11701 /* aUserInvolvement */ Nothing(),
11702 /* aSourceElement */ nullptr, /* aFormDataEntryList */ nullptr,
11703 /* aNavigationAPIState */ nullptr, scContainer);
11704
11705 // Step 9
11706 if (!shouldContinue) {
11707 return NS_OK;
11708 }
11709 }
11710 }
11711
11712 // Step 10
11713 // Run #url-and-history-update-steps
11714 rv = UpdateURLAndHistory(document, newURI, scContainer,
11715 aReplace ? NavigationHistoryBehavior::Replace
11716 : NavigationHistoryBehavior::Push,
11717 currentURI, equalURIs);
11718 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, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 11718); return rv; } } while (false)
;
11719
11720 return NS_OK;
11721}
11722
11723nsresult nsDocShell::UpdateURLAndHistory(
11724 Document* aDocument, nsIURI* aNewURI, nsIStructuredCloneContainer* aData,
11725 NavigationHistoryBehavior aHistoryHandling, nsIURI* aCurrentURI,
11726 bool aEqualURIs) {
11727 // Implements
11728 // https://html.spec.whatwg.org/multipage/history.html#url-and-history-update-steps
11729 MOZ_ASSERT(aHistoryHandling != NavigationHistoryBehavior::Auto)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aHistoryHandling != NavigationHistoryBehavior::Auto)
>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(aHistoryHandling != NavigationHistoryBehavior::Auto)
)), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aHistoryHandling != NavigationHistoryBehavior::Auto"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 11729);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "aHistoryHandling != NavigationHistoryBehavior::Auto"
")"); do { MOZ_CrashSequence(__null, 11729); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11730 bool isReplace = aHistoryHandling == NavigationHistoryBehavior::Replace;
11731
11732 // If we have a pending title change, handle it before creating a new entry.
11733 aDocument->DoNotifyPossibleTitleChange();
11734
11735 // Step 2, if aReplace is false: Create a new entry in the session
11736 // history. This will erase all SHEntries after the new entry and make this
11737 // entry the current one. This operation may modify mOSHE, which we need
11738 // later, so we keep a reference here.
11739 NS_ENSURE_TRUE(mOSHE || mActiveEntry || isReplace, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(mOSHE || mActiveEntry || isReplace
)), 0))) { NS_DebugBreak(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "mOSHE || mActiveEntry || isReplace"
") failed", nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 11739); return NS_ERROR_FAILURE; } } while (false)
;
11740 nsCOMPtr<nsISHEntry> oldOSHE = mOSHE;
11741
11742 // If this push/replaceState changed the document's current URI and the new
11743 // URI differs from the old URI in more than the hash, or if the old
11744 // SHEntry's URI was modified in this way by a push/replaceState call
11745 // set URIWasModified to true for the current SHEntry (bug 669671).
11746 bool sameExceptHashes = true;
11747 aNewURI->EqualsExceptRef(aCurrentURI, &sameExceptHashes);
11748 bool uriWasModified;
11749 if (sameExceptHashes) {
11750 if (mozilla::SessionHistoryInParent()) {
11751 uriWasModified = mActiveEntry && mActiveEntry->GetURIWasModified();
11752 } else {
11753 uriWasModified = oldOSHE && oldOSHE->GetURIWasModified();
11754 }
11755 } else {
11756 uriWasModified = true;
11757 }
11758
11759 mLoadType = LOAD_PUSHSTATE;
11760
11761 nsCOMPtr<nsISHEntry> newSHEntry;
11762 if (!isReplace) {
11763 // Step 2.
11764
11765 // Step 2.2, "Remove any tasks queued by the history traversal task
11766 // source that are associated with any Document objects in the
11767 // top-level browsing context's document family." This is very hard in
11768 // SessionHistoryInParent since we can't synchronously access the
11769 // pending navigations that are already sent to the parent. We can
11770 // abort any AsyncGo navigations that are waiting to be sent. If we
11771 // send a message to the parent, it would be processed after any
11772 // navigations previously sent. So long as we consider the "history
11773 // traversal task source" to be the list in this process we match the
11774 // spec. If we move the entire list to the parent, we can handle the
11775 // aborting of loads there, but we don't have a way to synchronously
11776 // remove entries as we do here for non-SHIP.
11777 RefPtr<ChildSHistory> shistory = GetRootSessionHistory();
11778 if (shistory) {
11779 shistory->RemovePendingHistoryNavigations();
11780 }
11781
11782 nsPoint scrollPos = GetCurScrollPos();
11783
11784 bool scrollRestorationIsManual;
11785 if (mozilla::SessionHistoryInParent()) {
11786 // FIXME Need to save the current scroll position on mActiveEntry.
11787 scrollRestorationIsManual = mActiveEntry->GetScrollRestorationIsManual();
11788 } else {
11789 // Save the current scroll position (bug 590573). Step 2.3.
11790 mOSHE->SetScrollPosition(scrollPos.x, scrollPos.y);
11791
11792 scrollRestorationIsManual = mOSHE->GetScrollRestorationIsManual();
11793 }
11794
11795 nsCOMPtr<nsIContentSecurityPolicy> csp = aDocument->GetCsp();
11796
11797 if (mozilla::SessionHistoryInParent()) {
11798 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)
11799 ("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)
;
11800
11801 nsString title(mActiveEntry->GetTitle());
11802 nsCOMPtr<nsIReferrerInfo> referrerInfo = mActiveEntry->GetReferrerInfo();
11803
11804 UpdateActiveEntry(false,
11805 /* aPreviousScrollPos = */ Some(scrollPos), aNewURI,
11806 /* aOriginalURI = */ nullptr,
11807 /* aReferrerInfo = */ referrerInfo,
11808 /* aTriggeringPrincipal = */ aDocument->NodePrincipal(),
11809 csp, title, scrollRestorationIsManual, aData,
11810 uriWasModified, aDocument->PartitionedPrincipal());
11811 } else {
11812 // Since we're not changing which page we have loaded, pass
11813 // true for aCloneChildren.
11814 nsresult rv = AddToSessionHistory(
11815 aNewURI, nullptr,
11816 aDocument->NodePrincipal(), // triggeringPrincipal
11817 nullptr, nullptr, csp, true, getter_AddRefs(newSHEntry));
11818 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, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 11818); return rv; } } while (false)
;
11819
11820 NS_ENSURE_TRUE(newSHEntry, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(newSHEntry)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "newSHEntry" ") failed",
nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp",
11820); return NS_ERROR_FAILURE; } } while (false)
;
11821
11822 // Session history entries created by pushState inherit scroll restoration
11823 // mode from the current entry.
11824 newSHEntry->SetScrollRestorationIsManual(scrollRestorationIsManual);
11825
11826 // Set the new SHEntry's title (bug 655273).
11827 nsString title;
11828 mOSHE->GetTitle(title);
11829 newSHEntry->SetTitle(title);
11830
11831 nsCOMPtr<nsIReferrerInfo> referrerInfo = mOSHE->GetReferrerInfo();
11832 newSHEntry->SetReferrerInfo(referrerInfo);
11833
11834 // Link the new SHEntry to the old SHEntry's BFCache entry, since the
11835 // two entries correspond to the same document.
11836 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, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 11837); return NS_ERROR_FAILURE; } } while (false)
11837 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, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 11837); return NS_ERROR_FAILURE; } } while (false)
;
11838
11839 // AddToSessionHistory may not modify mOSHE. In case it doesn't,
11840 // we'll just set mOSHE here.
11841 mOSHE = newSHEntry;
11842 }
11843 } else if (mozilla::SessionHistoryInParent()) {
11844 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)
11845 ("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)
11846 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)
;
11847 // Setting the resultPrincipalURI to nullptr is fine here: it will cause
11848 // NS_GetFinalChannelURI to use the originalURI as the URI, which is aNewURI
11849 // in our case. We could also set it to aNewURI, with the same result.
11850 // We don't use aTitle here, see bug 544535.
11851 nsString title;
11852 nsCOMPtr<nsIReferrerInfo> referrerInfo;
11853 if (mActiveEntry) {
11854 title = mActiveEntry->GetTitle();
11855 referrerInfo = mActiveEntry->GetReferrerInfo();
11856 } else {
11857 referrerInfo = nullptr;
11858 }
11859 UpdateActiveEntry(
11860 true, /* aPreviousScrollPos = */ Nothing(), aNewURI, aNewURI,
11861 /* aReferrerInfo = */ referrerInfo, aDocument->NodePrincipal(),
11862 aDocument->GetCsp(), title,
11863 mActiveEntry && mActiveEntry->GetScrollRestorationIsManual(), aData,
11864 uriWasModified, aDocument->PartitionedPrincipal());
11865 } else {
11866 // Step 3.
11867 newSHEntry = mOSHE;
11868
11869 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)
;
11870 // Since we're not changing which page we have loaded, pass
11871 // true for aCloneChildren.
11872 if (!newSHEntry) {
11873 nsresult rv = AddToSessionHistory(
11874 aNewURI, nullptr,
11875 aDocument->NodePrincipal(), // triggeringPrincipal
11876 nullptr, nullptr, aDocument->GetCsp(), true,
11877 getter_AddRefs(newSHEntry));
11878 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, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 11878); return rv; } } while (false)
;
11879 mOSHE = newSHEntry;
11880 }
11881
11882 nsCOMPtr<nsIReferrerInfo> referrerInfo = mOSHE->GetReferrerInfo();
11883
11884 newSHEntry->SetURI(aNewURI);
11885 newSHEntry->SetOriginalURI(aNewURI);
11886 // We replaced the URI of the entry, clear the unstripped URI as it
11887 // shouldn't be used for reloads anymore.
11888 newSHEntry->SetUnstrippedURI(nullptr);
11889 // Setting the resultPrincipalURI to nullptr is fine here: it will cause
11890 // NS_GetFinalChannelURI to use the originalURI as the URI, which is aNewURI
11891 // in our case. We could also set it to aNewURI, with the same result.
11892 newSHEntry->SetResultPrincipalURI(nullptr);
11893 newSHEntry->SetLoadReplace(false);
11894 newSHEntry->SetReferrerInfo(referrerInfo);
11895 }
11896
11897 if (!mozilla::SessionHistoryInParent()) {
11898 // Step 2.4 and 3: Modify new/original session history entry and clear its
11899 // POST data, if there is any.
11900 newSHEntry->SetStateData(aData);
11901 newSHEntry->SetPostData(nullptr);
11902
11903 newSHEntry->SetURIWasModified(uriWasModified);
11904
11905 // Step E as described at the top of AddState: If aReplace is false,
11906 // indicating that we're doing a pushState rather than a replaceState,
11907 // notify bfcache that we've added a page to the history so it can evict
11908 // content viewers if appropriate. Otherwise call ReplaceEntry so that we
11909 // notify nsIHistoryListeners that an entry was replaced. We may not have a
11910 // root session history if this call is coming from a document.open() in a
11911 // docshell subtree that disables session history.
11912 RefPtr<ChildSHistory> rootSH = GetRootSessionHistory();
11913 if (rootSH) {
11914 rootSH->LegacySHistory()->EvictDocumentViewersOrReplaceEntry(newSHEntry,
11915 isReplace);
11916 }
11917 }
11918
11919 // Step 4: If the document's URI changed, update document's URI and update
11920 // global history.
11921 //
11922 // We need to call FireOnLocationChange so that the browser's address bar
11923 // gets updated and the back button is enabled, but we only need to
11924 // explicitly call FireOnLocationChange if we're not calling SetCurrentURI,
11925 // since SetCurrentURI will call FireOnLocationChange for us.
11926 //
11927 // Both SetCurrentURI(...) and FireDummyOnLocationChange() pass
11928 // nullptr for aRequest param to FireOnLocationChange(...). Such an update
11929 // notification is allowed only when we know docshell is not loading a new
11930 // document and it requires LOCATION_CHANGE_SAME_DOCUMENT flag. Otherwise,
11931 // FireOnLocationChange(...) breaks security UI.
11932 //
11933 // If the docshell is shutting down, don't update the document URI, as we
11934 // can't load into a docshell that is being destroyed.
11935 if (!aEqualURIs && !mIsBeingDestroyed) {
11936 aDocument->SetDocumentURI(aNewURI);
11937 SetCurrentURI(aNewURI, nullptr, /* aFireLocationChange */ true,
11938 /* aIsInitialAboutBlank */ false,
11939 GetSameDocumentNavigationFlags(aNewURI));
11940
11941 AddURIVisit(aNewURI, aCurrentURI, 0);
11942
11943 // AddURIVisit doesn't set the title for the new URI in global history,
11944 // so do that here.
11945 UpdateGlobalHistoryTitle(aNewURI);
11946
11947 // Inform the favicon service that our old favicon applies to this new
11948 // URI.
11949 CopyFavicon(aCurrentURI, aNewURI, UsePrivateBrowsing());
11950 } else {
11951 FireDummyOnLocationChange();
11952 }
11953 aDocument->SetStateObject(aData);
11954
11955 if (RefPtr navigation = aDocument->GetInnerWindow()->Navigation()) {
11956 MOZ_LOG(gNavigationLog, LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = gNavigationLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "nsDocShell %p triggering a navigation event for a same-document "
"navigation from UpdateURLAndHistory -> isReplace: %s", this
, isReplace ? "true" : "false"); } } while (0)
11957 ("nsDocShell %p triggering a navigation event for a same-document "do { const ::mozilla::LogModule* moz_real_module = gNavigationLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "nsDocShell %p triggering a navigation event for a same-document "
"navigation from UpdateURLAndHistory -> isReplace: %s", this
, isReplace ? "true" : "false"); } } while (0)
11958 "navigation from UpdateURLAndHistory -> isReplace: %s",do { const ::mozilla::LogModule* moz_real_module = gNavigationLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "nsDocShell %p triggering a navigation event for a same-document "
"navigation from UpdateURLAndHistory -> isReplace: %s", this
, isReplace ? "true" : "false"); } } while (0)
11959 this, isReplace ? "true" : "false"))do { const ::mozilla::LogModule* moz_real_module = gNavigationLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "nsDocShell %p triggering a navigation event for a same-document "
"navigation from UpdateURLAndHistory -> isReplace: %s", this
, isReplace ? "true" : "false"); } } while (0)
;
11960 // Step 11: Update the navigation API entries for a same-document
11961 // navigation given document's relevant global object's navigation API,
11962 // newEntry, and historyHandling.
11963 navigation->UpdateEntriesForSameDocumentNavigation(
11964 mActiveEntry.get(),
11965 isReplace ? NavigationType::Replace : NavigationType::Push);
11966 }
11967
11968 return NS_OK;
11969}
11970
11971NS_IMETHODIMPnsresult
11972nsDocShell::GetCurrentScrollRestorationIsManual(bool* aIsManual) {
11973 if (mozilla::SessionHistoryInParent()) {
11974 *aIsManual = mActiveEntry && mActiveEntry->GetScrollRestorationIsManual();
11975 return NS_OK;
11976 }
11977
11978 *aIsManual = false;
11979 if (mOSHE) {
11980 return mOSHE->GetScrollRestorationIsManual(aIsManual);
11981 }
11982
11983 return NS_OK;
11984}
11985
11986NS_IMETHODIMPnsresult
11987nsDocShell::SetCurrentScrollRestorationIsManual(bool aIsManual) {
11988 SetScrollRestorationIsManualOnHistoryEntry(mOSHE, aIsManual);
11989
11990 return NS_OK;
11991}
11992
11993void nsDocShell::SetScrollRestorationIsManualOnHistoryEntry(
11994 nsISHEntry* aSHEntry, bool aIsManual) {
11995 if (aSHEntry) {
11996 aSHEntry->SetScrollRestorationIsManual(aIsManual);
11997 }
11998
11999 if (mActiveEntry && mBrowsingContext) {
12000 mActiveEntry->SetScrollRestorationIsManual(aIsManual);
12001 if (XRE_IsParentProcess()) {
12002 SessionHistoryEntry* entry =
12003 mBrowsingContext->Canonical()->GetActiveSessionHistoryEntry();
12004 if (entry) {
12005 entry->SetScrollRestorationIsManual(aIsManual);
12006 }
12007 } else {
12008 mozilla::Unused << ContentChild::GetSingleton()
12009 ->SendSessionHistoryEntryScrollRestorationIsManual(
12010 mBrowsingContext, aIsManual);
12011 }
12012 }
12013}
12014
12015void nsDocShell::SetCacheKeyOnHistoryEntry(nsISHEntry* aSHEntry,
12016 uint32_t aCacheKey) {
12017 if (aSHEntry) {
12018 aSHEntry->SetCacheKey(aCacheKey);
12019 }
12020
12021 if (mActiveEntry && mBrowsingContext) {
12022 mActiveEntry->SetCacheKey(aCacheKey);
12023 if (XRE_IsParentProcess()) {
12024 SessionHistoryEntry* entry =
12025 mBrowsingContext->Canonical()->GetActiveSessionHistoryEntry();
12026 if (entry) {
12027 entry->SetCacheKey(aCacheKey);
12028 }
12029 } else {
12030 mozilla::Unused
12031 << ContentChild::GetSingleton()->SendSessionHistoryEntryCacheKey(
12032 mBrowsingContext, aCacheKey);
12033 }
12034 }
12035}
12036
12037/* static */
12038bool nsDocShell::ShouldAddToSessionHistory(nsIURI* aURI, nsIChannel* aChannel) {
12039 // I believe none of the about: urls should go in the history. But then
12040 // that could just be me... If the intent is only deny about:blank then we
12041 // should just do a spec compare, rather than two gets of the scheme and
12042 // then the path. -Gagan
12043 nsresult rv;
12044 nsAutoCString buf;
12045
12046 rv = aURI->GetScheme(buf);
12047 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
12048 return false;
12049 }
12050
12051 if (buf.EqualsLiteral("about")) {
12052 rv = aURI->GetPathQueryRef(buf);
12053 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
12054 return false;
12055 }
12056
12057 if (buf.EqualsLiteral("blank")) {
12058 return false;
12059 }
12060 // We only want to add about:newtab if it's not privileged, and
12061 // if it is not configured to show the blank page.
12062 if (buf.EqualsLiteral("newtab")) {
12063 if (!StaticPrefs::browser_newtabpage_enabled()) {
12064 return false;
12065 }
12066
12067 NS_ENSURE_TRUE(aChannel, false)do { if ((__builtin_expect(!!(!(aChannel)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aChannel" ") failed", nullptr
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 12067);
return false; } } while (false)
;
12068 nsCOMPtr<nsIPrincipal> resultPrincipal;
12069 rv = nsContentUtils::GetSecurityManager()->GetChannelResultPrincipal(
12070 aChannel, getter_AddRefs(resultPrincipal));
12071 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, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 12071); return false; } } while (false)
;
12072 return !resultPrincipal->IsSystemPrincipal();
12073 }
12074 }
12075
12076 return true;
12077}
12078
12079nsresult nsDocShell::AddToSessionHistory(
12080 nsIURI* aURI, nsIChannel* aChannel, nsIPrincipal* aTriggeringPrincipal,
12081 nsIPrincipal* aPrincipalToInherit,
12082 nsIPrincipal* aPartitionedPrincipalToInherit,
12083 nsIContentSecurityPolicy* aCsp, bool aCloneChildren,
12084 nsISHEntry** aNewEntry) {
12085 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" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 12085); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aURI" ") ("
"uri is null" ")"); do { MOZ_CrashSequence(__null, 12085); __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
;
12086 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"
")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 12086
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aChannel || !aTriggeringPrincipal"
") (" "Shouldn't have both set" ")"); do { MOZ_CrashSequence
(__null, 12086); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
12087 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()", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 12087); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "!mozilla::SessionHistoryInParent()"
")"); do { MOZ_CrashSequence(__null, 12087); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12088
12089#if defined(DEBUG1)
12090 if (MOZ_LOG_TEST(gDocShellLog, LogLevel::Debug)(__builtin_expect(!!(mozilla::detail::log_test(gDocShellLog, LogLevel
::Debug)), 0))
) {
12091 nsAutoCString chanName;
12092 if (aChannel) {
12093 aChannel->GetName(chanName);
12094 } else {
12095 chanName.AssignLiteral("<no channel>");
12096 }
12097
12098 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)
12099 ("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)
12100 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)
;
12101 }
12102#endif
12103
12104 nsresult rv = NS_OK;
12105 nsCOMPtr<nsISHEntry> entry;
12106
12107 /*
12108 * If this is a LOAD_FLAGS_REPLACE_HISTORY in a subframe, we use
12109 * the existing SH entry in the page and replace the url and
12110 * other vitalities.
12111 */
12112 if (LOAD_TYPE_HAS_FLAGS(mLoadType, LOAD_FLAGS_REPLACE_HISTORY)((mLoadType) & ((LOAD_FLAGS_REPLACE_HISTORY) << 16)
)
&&
12113 !mBrowsingContext->IsTop()) {
12114 // This is a subframe
12115 entry = mOSHE;
12116 if (entry) {
12117 entry->ClearEntry();
12118 }
12119 }
12120
12121 // Create a new entry if necessary.
12122 if (!entry) {
12123 entry = new nsSHEntry();
12124 }
12125
12126 // Get the post data & referrer
12127 nsCOMPtr<nsIInputStream> inputStream;
12128 nsCOMPtr<nsIURI> originalURI;
12129 nsCOMPtr<nsIURI> resultPrincipalURI;
12130 nsCOMPtr<nsIURI> unstrippedURI;
12131 bool loadReplace = false;
12132 nsCOMPtr<nsIReferrerInfo> referrerInfo;
12133 uint32_t cacheKey = 0;
12134 nsCOMPtr<nsIPrincipal> triggeringPrincipal = aTriggeringPrincipal;
12135 nsCOMPtr<nsIPrincipal> principalToInherit = aPrincipalToInherit;
12136 nsCOMPtr<nsIPrincipal> partitionedPrincipalToInherit =
12137 aPartitionedPrincipalToInherit;
12138 nsCOMPtr<nsIContentSecurityPolicy> csp = aCsp;
12139 bool expired = false; // by default the page is not expired
12140 bool discardLayoutState = false;
12141 nsCOMPtr<nsICacheInfoChannel> cacheChannel;
12142 bool userActivation = false;
12143
12144 if (aChannel) {
12145 cacheChannel = do_QueryInterface(aChannel);
12146
12147 /* If there is a caching channel, get the Cache Key and store it
12148 * in SH.
12149 */
12150 if (cacheChannel) {
12151 cacheChannel->GetCacheKey(&cacheKey);
12152 }
12153 nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(aChannel));
12154
12155 // Check if the httpChannel is hiding under a multipartChannel
12156 if (!httpChannel) {
12157 GetHttpChannel(aChannel, getter_AddRefs(httpChannel));
12158 }
12159 if (httpChannel) {
12160 nsCOMPtr<nsIUploadChannel> uploadChannel(do_QueryInterface(httpChannel));
12161 if (uploadChannel) {
12162 uploadChannel->GetUploadStream(getter_AddRefs(inputStream));
12163 }
12164 httpChannel->GetOriginalURI(getter_AddRefs(originalURI));
12165 uint32_t loadFlags;
12166 aChannel->GetLoadFlags(&loadFlags);
12167 loadReplace = loadFlags & nsIChannel::LOAD_REPLACE;
12168 rv = httpChannel->GetReferrerInfo(getter_AddRefs(referrerInfo));
12169 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)))", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 12169); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 12169); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12170
12171 discardLayoutState = ShouldDiscardLayoutState(httpChannel);
12172 }
12173
12174 nsCOMPtr<nsILoadInfo> loadInfo = aChannel->LoadInfo();
12175 if (!triggeringPrincipal) {
12176 triggeringPrincipal = loadInfo->TriggeringPrincipal();
12177 }
12178 if (!csp) {
12179 csp = loadInfo->GetCspToInherit();
12180 }
12181
12182 loadInfo->GetResultPrincipalURI(getter_AddRefs(resultPrincipalURI));
12183
12184 loadInfo->GetUnstrippedURI(getter_AddRefs(unstrippedURI));
12185
12186 userActivation = loadInfo->GetHasValidUserGestureActivation();
12187
12188 // For now keep storing just the principal in the SHEntry.
12189 if (!principalToInherit) {
12190 if (loadInfo->GetLoadingSandboxed()) {
12191 if (loadInfo->GetLoadingPrincipal()) {
12192 principalToInherit = NullPrincipal::CreateWithInheritedAttributes(
12193 loadInfo->GetLoadingPrincipal());
12194 } else {
12195 // get the OriginAttributes
12196 OriginAttributes attrs;
12197 loadInfo->GetOriginAttributes(&attrs);
12198 principalToInherit = NullPrincipal::Create(attrs);
12199 }
12200 } else {
12201 principalToInherit = loadInfo->PrincipalToInherit();
12202 }
12203 }
12204
12205 if (!partitionedPrincipalToInherit) {
12206 // XXXehsan is it correct to fall back to the principal to inherit in all
12207 // cases? For example, what about the cases where we are using the load
12208 // info's principal to inherit? Do we need to add a similar concept to
12209 // load info for partitioned principal?
12210 partitionedPrincipalToInherit = principalToInherit;
12211 }
12212 }
12213
12214 nsAutoString srcdoc;
12215 bool srcdocEntry = false;
12216 nsCOMPtr<nsIURI> baseURI;
12217
12218 nsCOMPtr<nsIInputStreamChannel> inStrmChan = do_QueryInterface(aChannel);
12219 if (inStrmChan) {
12220 bool isSrcdocChannel;
12221 inStrmChan->GetIsSrcdocChannel(&isSrcdocChannel);
12222 if (isSrcdocChannel) {
12223 inStrmChan->GetSrcdocData(srcdoc);
12224 srcdocEntry = true;
12225 inStrmChan->GetBaseURI(getter_AddRefs(baseURI));
12226 } else {
12227 srcdoc.SetIsVoid(true);
12228 }
12229 }
12230 /* If cache got a 'no-store', ask SH not to store
12231 * HistoryLayoutState. By default, SH will set this
12232 * flag to true and save HistoryLayoutState.
12233 */
12234 bool saveLayoutState = !discardLayoutState;
12235
12236 if (cacheChannel) {
12237 // Check if the page has expired from cache
12238 uint32_t expTime = 0;
12239 cacheChannel->GetCacheTokenExpirationTime(&expTime);
12240 uint32_t now = PRTimeToSeconds(PR_Now());
12241 if (expTime <= now) {
12242 expired = true;
12243 }
12244 }
12245
12246 // Title is set in nsDocShell::SetTitle()
12247 entry->Create(aURI, // uri
12248 u""_ns, // Title
12249 inputStream, // Post data stream
12250 cacheKey, // CacheKey
12251 mContentTypeHint, // Content-type
12252 triggeringPrincipal, // Channel or provided principal
12253 principalToInherit, partitionedPrincipalToInherit, csp,
12254 HistoryID(), GetCreatedDynamically(), originalURI,
12255 resultPrincipalURI, unstrippedURI, loadReplace, referrerInfo,
12256 srcdoc, srcdocEntry, baseURI, saveLayoutState, expired,
12257 userActivation);
12258
12259 if (mBrowsingContext->IsTop() && GetSessionHistory()) {
12260 Maybe<int32_t> previousEntryIndex;
12261 Maybe<int32_t> loadedEntryIndex;
12262
12263 if (mBrowsingContext->IsTop() &&
12264 !ShouldAddToSessionHistory(aURI, aChannel)) {
12265 entry->SetTransient();
12266 }
12267 rv = GetSessionHistory()->LegacySHistory()->AddToRootSessionHistory(
12268 aCloneChildren, mOSHE, mBrowsingContext, entry, mLoadType,
12269 &previousEntryIndex, &loadedEntryIndex);
12270
12271 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" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 12271); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
") (" "Could not add entry to root session history" ")"); do
{ MOZ_CrashSequence(__null, 12271); __attribute__((nomerge))
::abort(); } while (false); } } while (false)
;
12272 if (previousEntryIndex.isSome()) {
12273 mPreviousEntryIndex = previousEntryIndex.value();
12274 }
12275 if (loadedEntryIndex.isSome()) {
12276 mLoadedEntryIndex = loadedEntryIndex.value();
12277 }
12278
12279 // aCloneChildren implies that we are retaining the same document, thus we
12280 // need to signal to the top WC that the new SHEntry may receive a fresh
12281 // user interaction flag.
12282 if (aCloneChildren) {
12283 WindowContext* topWc = mBrowsingContext->GetTopWindowContext();
12284 if (topWc && !topWc->IsDiscarded()) {
12285 MOZ_ALWAYS_SUCCEEDS(topWc->SetSHEntryHasUserInteraction(false))do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(topWc->SetSHEntryHasUserInteraction(false))), 1)))), 1)))
{ } else { do { do { } while (false); MOZ_ReportCrash("" "NS_SUCCEEDED(topWc->SetSHEntryHasUserInteraction(false))"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 12285);
AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED(topWc->SetSHEntryHasUserInteraction(false))"
")"); do { MOZ_CrashSequence(__null, 12285); __attribute__((
nomerge)) ::abort(); } while (false); } while (false); } } while
(false)
;
12286 }
12287 }
12288 } else {
12289 // This is a subframe, make sure that this new SHEntry will be
12290 // marked with user interaction.
12291 WindowContext* topWc = mBrowsingContext->GetTopWindowContext();
12292 if (topWc && !topWc->IsDiscarded()) {
12293 MOZ_ALWAYS_SUCCEEDS(topWc->SetSHEntryHasUserInteraction(false))do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(topWc->SetSHEntryHasUserInteraction(false))), 1)))), 1)))
{ } else { do { do { } while (false); MOZ_ReportCrash("" "NS_SUCCEEDED(topWc->SetSHEntryHasUserInteraction(false))"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 12293);
AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED(topWc->SetSHEntryHasUserInteraction(false))"
")"); do { MOZ_CrashSequence(__null, 12293); __attribute__((
nomerge)) ::abort(); } while (false); } while (false); } } while
(false)
;
12294 }
12295 if (!mOSHE || !LOAD_TYPE_HAS_FLAGS(mLoadType, LOAD_FLAGS_REPLACE_HISTORY)((mLoadType) & ((LOAD_FLAGS_REPLACE_HISTORY) << 16)
)
) {
12296 rv = AddChildSHEntryToParent(entry, mBrowsingContext->ChildOffset(),
12297 aCloneChildren);
12298 }
12299 }
12300
12301 // Return the new SH entry...
12302 if (aNewEntry) {
12303 *aNewEntry = nullptr;
12304 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
12305 entry.forget(aNewEntry);
12306 }
12307 }
12308
12309 return rv;
12310}
12311
12312void nsDocShell::UpdateActiveEntry(
12313 bool aReplace, const Maybe<nsPoint>& aPreviousScrollPos, nsIURI* aURI,
12314 nsIURI* aOriginalURI, nsIReferrerInfo* aReferrerInfo,
12315 nsIPrincipal* aTriggeringPrincipal, nsIContentSecurityPolicy* aCsp,
12316 const nsAString& aTitle, bool aScrollRestorationIsManual,
12317 nsIStructuredCloneContainer* aData, bool aURIWasModified,
12318 nsIPrincipal* aPartitionedPrincipal) {
12319 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()", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 12319); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mozilla::SessionHistoryInParent()"
")"); do { MOZ_CrashSequence(__null, 12319); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12320 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" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 12320); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aURI" ") ("
"uri is null" ")"); do { MOZ_CrashSequence(__null, 12320); __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
;
12321 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" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 12322); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mLoadType == LOAD_PUSHSTATE"
") (" "This code only deals with pushState" ")"); do { MOZ_CrashSequence
(__null, 12322); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
12322 "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" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 12322); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mLoadType == LOAD_PUSHSTATE"
") (" "This code only deals with pushState" ")"); do { MOZ_CrashSequence
(__null, 12322); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
12323 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", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 12323); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aReplace"
")"); do { MOZ_CrashSequence(__null, 12323); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false); } } while
(false)
;
12324
12325 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)
12326 ("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)
12327 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)
;
12328
12329 // Even if we're replacing an existing entry we create new a
12330 // SessionHistoryInfo. In the parent process we'll keep the existing
12331 // SessionHistoryEntry, but just replace its SessionHistoryInfo, that way the
12332 // entry keeps identity but its data is replaced.
12333 bool replace = aReplace && mActiveEntry;
12334
12335 if (!replace) {
12336 CollectWireframe();
12337 }
12338
12339 UniquePtr<SessionHistoryInfo> previousActiveEntry(mActiveEntry.release());
12340 if (previousActiveEntry) {
12341 // Link this entry to the previous active entry.
12342 mActiveEntry = MakeUnique<SessionHistoryInfo>(*previousActiveEntry, aURI);
12343 } else {
12344 mActiveEntry = MakeUnique<SessionHistoryInfo>(
12345 aURI, aTriggeringPrincipal, nullptr, nullptr, aCsp, mContentTypeHint);
12346 }
12347 mActiveEntry->SetOriginalURI(aOriginalURI);
12348 mActiveEntry->SetUnstrippedURI(nullptr);
12349 mActiveEntry->SetReferrerInfo(aReferrerInfo);
12350 mActiveEntry->SetTitle(aTitle);
12351 mActiveEntry->SetStateData(static_cast<nsStructuredCloneContainer*>(aData));
12352 mActiveEntry->SetURIWasModified(aURIWasModified);
12353 mActiveEntry->SetScrollRestorationIsManual(aScrollRestorationIsManual);
12354 mActiveEntry->SetPartitionedPrincipalToInherit(aPartitionedPrincipal);
12355
12356 if (replace) {
12357 mBrowsingContext->ReplaceActiveSessionHistoryEntry(mActiveEntry.get());
12358 } else {
12359 mBrowsingContext->IncrementHistoryEntryCountForBrowsingContext();
12360 // FIXME We should probably just compute mChildOffset in the parent
12361 // instead of passing it over IPC here.
12362 mBrowsingContext->SetActiveSessionHistoryEntry(
12363 aPreviousScrollPos, mActiveEntry.get(), previousActiveEntry.get(),
12364 mLoadType,
12365 /* aCacheKey = */ 0);
12366 // FIXME Do we need to update mPreviousEntryIndex and mLoadedEntryIndex?
12367 }
12368}
12369
12370nsresult nsDocShell::LoadHistoryEntry(nsISHEntry* aEntry, uint32_t aLoadType,
12371 bool aUserActivation) {
12372 NS_ENSURE_TRUE(aEntry, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(aEntry)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aEntry" ") failed", nullptr
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 12372);
return NS_ERROR_FAILURE; } } while (false)
;
12373
12374 nsresult rv;
12375 RefPtr<nsDocShellLoadState> loadState;
12376 rv = aEntry->CreateLoadInfo(getter_AddRefs(loadState));
12377 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, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 12377); return rv; } } while (false)
;
12378
12379 // Calling CreateAboutBlankDocumentViewer can set mOSHE to null, and if
12380 // that's the only thing holding a ref to aEntry that will cause aEntry to
12381 // die while we're loading it. So hold a strong ref to aEntry here, just
12382 // in case.
12383 nsCOMPtr<nsISHEntry> kungFuDeathGrip(aEntry);
12384
12385 loadState->SetHasValidUserGestureActivation(
12386 loadState->HasValidUserGestureActivation() || aUserActivation);
12387
12388 loadState->SetTextDirectiveUserActivation(
12389 loadState->GetTextDirectiveUserActivation() || aUserActivation);
12390
12391 return LoadHistoryEntry(loadState, aLoadType, aEntry == mOSHE);
12392}
12393
12394nsresult nsDocShell::LoadHistoryEntry(const LoadingSessionHistoryInfo& aEntry,
12395 uint32_t aLoadType,
12396 bool aUserActivation) {
12397 RefPtr<nsDocShellLoadState> loadState = aEntry.CreateLoadInfo();
12398 loadState->SetHasValidUserGestureActivation(
12399 loadState->HasValidUserGestureActivation() || aUserActivation);
12400
12401 loadState->SetTextDirectiveUserActivation(
12402 loadState->GetTextDirectiveUserActivation() || aUserActivation);
12403
12404 return LoadHistoryEntry(loadState, aLoadType, aEntry.mLoadingCurrentEntry);
12405}
12406
12407nsresult nsDocShell::LoadHistoryEntry(nsDocShellLoadState* aLoadState,
12408 uint32_t aLoadType,
12409 bool aLoadingCurrentEntry) {
12410 if (!IsNavigationAllowed()) {
12411 return NS_OK;
12412 }
12413
12414 // We are setting load type afterwards so we don't have to
12415 // send it in an IPC message
12416 aLoadState->SetLoadType(aLoadType);
12417
12418 nsresult rv;
12419 if (aLoadState->URI()->SchemeIs("javascript")) {
12420 // We're loading a URL that will execute script from inside asyncOpen.
12421 // Replace the current document with about:blank now to prevent
12422 // anything from the current document from leaking into any JavaScript
12423 // code in the URL.
12424 // Don't cache the presentation if we're going to just reload the
12425 // current entry. Caching would lead to trying to save the different
12426 // content viewers in the same nsISHEntry object.
12427 rv = CreateAboutBlankDocumentViewer(
12428 aLoadState->PrincipalToInherit(),
12429 aLoadState->PartitionedPrincipalToInherit(), nullptr, nullptr,
12430 /* aIsInitialDocument */ false, Nothing(), !aLoadingCurrentEntry);
12431
12432 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
12433 // The creation of the intermittent about:blank content
12434 // viewer failed for some reason (potentially because the
12435 // user prevented it). Interrupt the history load.
12436 return NS_OK;
12437 }
12438
12439 if (!aLoadState->TriggeringPrincipal()) {
12440 // Ensure that we have a triggeringPrincipal. Otherwise javascript:
12441 // URIs will pick it up from the about:blank page we just loaded,
12442 // and we don't really want even that in this case.
12443 nsCOMPtr<nsIPrincipal> principal =
12444 NullPrincipal::Create(GetOriginAttributes());
12445 aLoadState->SetTriggeringPrincipal(principal);
12446 }
12447 }
12448
12449 /* If there is a valid postdata *and* the user pressed
12450 * reload or shift-reload, take user's permission before we
12451 * repost the data to the server.
12452 */
12453 if ((aLoadType & LOAD_CMD_RELOAD) && aLoadState->PostDataStream()) {
12454 bool repost;
12455 rv = ConfirmRepost(&repost);
12456 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
12457 return rv;
12458 }
12459
12460 // If the user pressed cancel in the dialog, return. We're done here.
12461 if (!repost) {
12462 return NS_BINDING_ABORTED;
12463 }
12464 }
12465
12466 // If there is no valid triggeringPrincipal, we deny the load
12467 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"
")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 12468
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->TriggeringPrincipal()"
") (" "need a valid triggeringPrincipal to load from history"
")"); do { MOZ_CrashSequence(__null, 12468); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
12468 "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"
")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 12468
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->TriggeringPrincipal()"
") (" "need a valid triggeringPrincipal to load from history"
")"); do { MOZ_CrashSequence(__null, 12468); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12469 if (!aLoadState->TriggeringPrincipal()) {
12470 return NS_ERROR_FAILURE;
12471 }
12472
12473 return InternalLoad(aLoadState); // No nsIRequest
12474}
12475
12476NS_IMETHODIMPnsresult
12477nsDocShell::PersistLayoutHistoryState() {
12478 nsresult rv = NS_OK;
12479
12480 if (mozilla::SessionHistoryInParent() ? !!mActiveEntry : !!mOSHE) {
12481 bool scrollRestorationIsManual;
12482 if (mozilla::SessionHistoryInParent()) {
12483 scrollRestorationIsManual = mActiveEntry->GetScrollRestorationIsManual();
12484 } else {
12485 scrollRestorationIsManual = mOSHE->GetScrollRestorationIsManual();
12486 }
12487 nsCOMPtr<nsILayoutHistoryState> layoutState;
12488 if (RefPtr<PresShell> presShell = GetPresShell()) {
12489 rv = presShell->CaptureHistoryState(getter_AddRefs(layoutState));
12490 } else if (scrollRestorationIsManual) {
12491 // Even if we don't have layout anymore, we may want to reset the
12492 // current scroll state in layout history.
12493 GetLayoutHistoryState(getter_AddRefs(layoutState));
12494 }
12495
12496 if (scrollRestorationIsManual && layoutState) {
12497 layoutState->ResetScrollState();
12498 }
12499 }
12500
12501 return rv;
12502}
12503
12504void nsDocShell::SwapHistoryEntries(nsISHEntry* aOldEntry,
12505 nsISHEntry* aNewEntry) {
12506 if (aOldEntry == mOSHE) {
12507 mOSHE = aNewEntry;
12508 }
12509
12510 if (aOldEntry == mLSHE) {
12511 mLSHE = aNewEntry;
12512 }
12513}
12514
12515void nsDocShell::SetHistoryEntryAndUpdateBC(const Maybe<nsISHEntry*>& aLSHE,
12516 const Maybe<nsISHEntry*>& aOSHE) {
12517 // We want to hold on to the reference in mLSHE before we update it.
12518 // Otherwise, SetHistoryEntry could release the last reference to
12519 // the entry while aOSHE is pointing to it.
12520 nsCOMPtr<nsISHEntry> deathGripOldLSHE;
12521 if (aLSHE.isSome()) {
12522 deathGripOldLSHE = SetHistoryEntry(&mLSHE, aLSHE.value());
12523 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()", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 12523); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mLSHE.get() == aLSHE.value()"
")"); do { MOZ_CrashSequence(__null, 12523); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12524 }
12525 nsCOMPtr<nsISHEntry> deathGripOldOSHE;
12526 if (aOSHE.isSome()) {
12527 deathGripOldOSHE = SetHistoryEntry(&mOSHE, aOSHE.value());
12528 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()", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 12528); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mOSHE.get() == aOSHE.value()"
")"); do { MOZ_CrashSequence(__null, 12528); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12529 }
12530}
12531
12532already_AddRefed<nsISHEntry> nsDocShell::SetHistoryEntry(
12533 nsCOMPtr<nsISHEntry>* aPtr, nsISHEntry* aEntry) {
12534 // We need to sync up the docshell and session history trees for
12535 // subframe navigation. If the load was in a subframe, we forward up to
12536 // the root docshell, which will then recursively sync up all docshells
12537 // to their corresponding entries in the new session history tree.
12538 // If we don't do this, then we can cache a content viewer on the wrong
12539 // cloned entry, and subsequently restore it at the wrong time.
12540 RefPtr<BrowsingContext> topBC = mBrowsingContext->Top();
12541 if (topBC->IsDiscarded()) {
12542 topBC = nullptr;
12543 }
12544 RefPtr<BrowsingContext> currBC =
12545 mBrowsingContext->IsDiscarded() ? nullptr : mBrowsingContext;
12546 if (topBC && *aPtr) {
12547 (*aPtr)->SyncTreesForSubframeNavigation(aEntry, topBC, currBC);
12548 }
12549 nsCOMPtr<nsISHEntry> entry(aEntry);
12550 entry.swap(*aPtr);
12551 return entry.forget();
12552}
12553
12554already_AddRefed<ChildSHistory> nsDocShell::GetRootSessionHistory() {
12555 RefPtr<ChildSHistory> childSHistory =
12556 mBrowsingContext->Top()->GetChildSessionHistory();
12557 return childSHistory.forget();
12558}
12559
12560nsresult nsDocShell::GetHttpChannel(nsIChannel* aChannel,
12561 nsIHttpChannel** aReturn) {
12562 NS_ENSURE_ARG_POINTER(aReturn)do { if ((__builtin_expect(!!(!(aReturn)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aReturn" ") failed", nullptr
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 12562);
return NS_ERROR_INVALID_POINTER; } } while (false)
;
12563 if (!aChannel) {
12564 return NS_ERROR_FAILURE;
12565 }
12566
12567 nsCOMPtr<nsIMultiPartChannel> multiPartChannel(do_QueryInterface(aChannel));
12568 if (multiPartChannel) {
12569 nsCOMPtr<nsIChannel> baseChannel;
12570 multiPartChannel->GetBaseChannel(getter_AddRefs(baseChannel));
12571 nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(baseChannel));
12572 *aReturn = httpChannel;
12573 NS_IF_ADDREF(*aReturn)ns_if_addref(*aReturn);
12574 }
12575 return NS_OK;
12576}
12577
12578bool nsDocShell::ShouldDiscardLayoutState(nsIHttpChannel* aChannel) {
12579 // By default layout State will be saved.
12580 if (!aChannel) {
12581 return false;
12582 }
12583
12584 // figure out if SH should be saving layout state
12585 bool noStore = false;
12586 Unused << aChannel->IsNoStoreResponse(&noStore);
12587 return noStore;
12588}
12589
12590NS_IMETHODIMPnsresult
12591nsDocShell::GetEditor(nsIEditor** aEditor) {
12592 NS_ENSURE_ARG_POINTER(aEditor)do { if ((__builtin_expect(!!(!(aEditor)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aEditor" ") failed", nullptr
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 12592);
return NS_ERROR_INVALID_POINTER; } } while (false)
;
12593 RefPtr<HTMLEditor> htmlEditor = GetHTMLEditorInternal();
12594 htmlEditor.forget(aEditor);
12595 return NS_OK;
12596}
12597
12598NS_IMETHODIMPnsresult
12599nsDocShell::SetEditor(nsIEditor* aEditor) {
12600 HTMLEditor* htmlEditor = aEditor ? aEditor->GetAsHTMLEditor() : nullptr;
12601 // If TextEditor comes, throw an error.
12602 if (aEditor && !htmlEditor) {
12603 return NS_ERROR_INVALID_ARG;
12604 }
12605 return SetHTMLEditorInternal(htmlEditor);
12606}
12607
12608HTMLEditor* nsDocShell::GetHTMLEditorInternal() {
12609 return mEditorData ? mEditorData->GetHTMLEditor() : nullptr;
12610}
12611
12612nsresult nsDocShell::SetHTMLEditorInternal(HTMLEditor* aHTMLEditor) {
12613 if (!aHTMLEditor && !mEditorData) {
12614 return NS_OK;
12615 }
12616
12617 nsresult rv = EnsureEditorData();
12618 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
12619 return rv;
12620 }
12621
12622 return mEditorData->SetHTMLEditor(aHTMLEditor);
12623}
12624
12625NS_IMETHODIMPnsresult
12626nsDocShell::GetEditable(bool* aEditable) {
12627 NS_ENSURE_ARG_POINTER(aEditable)do { if ((__builtin_expect(!!(!(aEditable)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aEditable" ") failed", nullptr
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 12627);
return NS_ERROR_INVALID_POINTER; } } while (false)
;
12628 *aEditable = mEditorData && mEditorData->GetEditable();
12629 return NS_OK;
12630}
12631
12632NS_IMETHODIMPnsresult
12633nsDocShell::GetHasEditingSession(bool* aHasEditingSession) {
12634 NS_ENSURE_ARG_POINTER(aHasEditingSession)do { if ((__builtin_expect(!!(!(aHasEditingSession)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aHasEditingSession" ") failed"
, nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 12634); return NS_ERROR_INVALID_POINTER; } } while (false)
;
12635
12636 if (mEditorData) {
12637 *aHasEditingSession = !!mEditorData->GetEditingSession();
12638 } else {
12639 *aHasEditingSession = false;
12640 }
12641
12642 return NS_OK;
12643}
12644
12645NS_IMETHODIMPnsresult
12646nsDocShell::MakeEditable(bool aInWaitForUriLoad) {
12647 nsresult rv = EnsureEditorData();
12648 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
12649 return rv;
12650 }
12651
12652 return mEditorData->MakeEditable(aInWaitForUriLoad);
12653}
12654
12655/* static */ bool nsDocShell::ShouldAddURIVisit(nsIChannel* aChannel) {
12656 bool needToAddURIVisit = true;
12657 nsCOMPtr<nsIPropertyBag2> props(do_QueryInterface(aChannel));
12658 if (props) {
12659 mozilla::Unused << props->GetPropertyAsBool(
12660 u"docshell.needToAddURIVisit"_ns, &needToAddURIVisit);
12661 }
12662
12663 return needToAddURIVisit;
12664}
12665
12666/* static */ void nsDocShell::ExtractLastVisit(
12667 nsIChannel* aChannel, nsIURI** aURI, uint32_t* aChannelRedirectFlags) {
12668 nsCOMPtr<nsIPropertyBag2> props(do_QueryInterface(aChannel));
12669 if (!props) {
12670 return;
12671 }
12672
12673 nsresult rv;
12674 nsCOMPtr<nsIURI> uri(do_GetProperty(props, u"docshell.previousURI"_ns, &rv));
12675 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
12676 uri.forget(aURI);
12677
12678 rv = props->GetPropertyAsUint32(u"docshell.previousFlags"_ns,
12679 aChannelRedirectFlags);
12680
12681 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)", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 12683); } } while (false)
12682 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)", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 12683); } } while (false)
12683 "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)", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 12683); } } while (false)
;
12684
12685 } else {
12686 // There is no last visit for this channel, so this must be the first
12687 // link. Link the visit to the referrer of this request, if any.
12688 // Treat referrer as null if there is an error getting it.
12689 NS_GetReferrerFromChannel(aChannel, aURI);
12690 }
12691}
12692
12693void nsDocShell::SaveLastVisit(nsIChannel* aChannel, nsIURI* aURI,
12694 uint32_t aChannelRedirectFlags) {
12695 nsCOMPtr<nsIWritablePropertyBag2> props(do_QueryInterface(aChannel));
12696 if (!props || !aURI) {
12697 return;
12698 }
12699
12700 props->SetPropertyAsInterface(u"docshell.previousURI"_ns, aURI);
12701 props->SetPropertyAsUint32(u"docshell.previousFlags"_ns,
12702 aChannelRedirectFlags);
12703}
12704
12705/* static */ void nsDocShell::InternalAddURIVisit(
12706 nsIURI* aURI, nsIURI* aPreviousURI, uint32_t aChannelRedirectFlags,
12707 uint32_t aResponseStatus, BrowsingContext* aBrowsingContext,
12708 nsIWidget* aWidget, uint32_t aLoadType, bool aWasUpgraded) {
12709 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!"
")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 12709
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aURI" ") (" "Visited URI is null!"
")"); do { MOZ_CrashSequence(__null, 12709); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12710 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" ")"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 12711);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadType != LOAD_ERROR_PAGE && aLoadType != LOAD_BYPASS_HISTORY"
") (" "Do not add error or bypass pages to global history" ")"
); do { MOZ_CrashSequence(__null, 12711); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
12711 "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" ")"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 12711);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadType != LOAD_ERROR_PAGE && aLoadType != LOAD_BYPASS_HISTORY"
") (" "Do not add error or bypass pages to global history" ")"
); do { MOZ_CrashSequence(__null, 12711); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
12712
12713 bool usePrivateBrowsing = false;
12714 aBrowsingContext->GetUsePrivateBrowsing(&usePrivateBrowsing);
12715
12716 // Only content-type docshells save URI visits. Also don't do
12717 // anything here if we're not supposed to use global history.
12718 if (!aBrowsingContext->IsContent() ||
12719 !aBrowsingContext->GetUseGlobalHistory() || usePrivateBrowsing) {
12720 return;
12721 }
12722
12723 nsCOMPtr<IHistory> history = components::History::Service();
12724
12725 if (history) {
12726 uint32_t visitURIFlags = 0;
12727
12728 if (aBrowsingContext->IsTop()) {
12729 visitURIFlags |= IHistory::TOP_LEVEL;
12730 }
12731
12732 if (aChannelRedirectFlags & nsIChannelEventSink::REDIRECT_TEMPORARY) {
12733 visitURIFlags |= IHistory::REDIRECT_TEMPORARY;
12734 } else if (aChannelRedirectFlags &
12735 nsIChannelEventSink::REDIRECT_PERMANENT) {
12736 visitURIFlags |= IHistory::REDIRECT_PERMANENT;
12737 } else {
12738 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." ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 12740); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aChannelRedirectFlags"
") (" "One of REDIRECT_TEMPORARY or REDIRECT_PERMANENT must be set "
"if any flags in aChannelRedirectFlags is set." ")"); do { MOZ_CrashSequence
(__null, 12740); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
12739 "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." ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 12740); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aChannelRedirectFlags"
") (" "One of REDIRECT_TEMPORARY or REDIRECT_PERMANENT must be set "
"if any flags in aChannelRedirectFlags is set." ")"); do { MOZ_CrashSequence
(__null, 12740); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
12740 "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." ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 12740); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aChannelRedirectFlags"
") (" "One of REDIRECT_TEMPORARY or REDIRECT_PERMANENT must be set "
"if any flags in aChannelRedirectFlags is set." ")"); do { MOZ_CrashSequence
(__null, 12740); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
12741 }
12742
12743 if (aResponseStatus >= 300 && aResponseStatus < 400) {
12744 visitURIFlags |= IHistory::REDIRECT_SOURCE;
12745 if (aResponseStatus == 301 || aResponseStatus == 308) {
12746 visitURIFlags |= IHistory::REDIRECT_SOURCE_PERMANENT;
12747 }
12748 }
12749 // Errors 400-501 and 505 are considered unrecoverable, in the sense a
12750 // simple retry attempt by the user is unlikely to solve them.
12751 // 408 is special cased, since may actually indicate a temporary
12752 // connection problem.
12753 else if (aResponseStatus != 408 &&
12754 ((aResponseStatus >= 400 && aResponseStatus <= 501) ||
12755 aResponseStatus == 505)) {
12756 visitURIFlags |= IHistory::UNRECOVERABLE_ERROR;
12757 }
12758
12759 if (aWasUpgraded) {
12760 visitURIFlags |=
12761 IHistory::REDIRECT_SOURCE | IHistory::REDIRECT_SOURCE_UPGRADED;
12762 }
12763
12764 mozilla::Unused << history->VisitURI(aWidget, aURI, aPreviousURI,
12765 visitURIFlags,
12766 aBrowsingContext->BrowserId());
12767 }
12768}
12769
12770void nsDocShell::AddURIVisit(nsIURI* aURI, nsIURI* aPreviousURI,
12771 uint32_t aChannelRedirectFlags,
12772 uint32_t aResponseStatus) {
12773 nsPIDOMWindowOuter* outer = GetWindow();
12774 nsCOMPtr<nsIWidget> widget = widget::WidgetUtils::DOMWindowToWidget(outer);
12775
12776 InternalAddURIVisit(aURI, aPreviousURI, aChannelRedirectFlags,
12777 aResponseStatus, mBrowsingContext, widget, mLoadType,
12778 false);
12779}
12780
12781//*****************************************************************************
12782// nsDocShell: Helper Routines
12783//*****************************************************************************
12784
12785NS_IMETHODIMPnsresult
12786nsDocShell::SetLoadType(uint32_t aLoadType) {
12787 mLoadType = aLoadType;
12788 return NS_OK;
12789}
12790
12791NS_IMETHODIMPnsresult
12792nsDocShell::GetLoadType(uint32_t* aLoadType) {
12793 *aLoadType = mLoadType;
12794 return NS_OK;
12795}
12796
12797nsresult nsDocShell::ConfirmRepost(bool* aRepost) {
12798 if (StaticPrefs::dom_confirm_repost_testing_always_accept()) {
12799 *aRepost = true;
12800 return NS_OK;
12801 }
12802
12803 nsCOMPtr<nsIPromptCollection> prompter =
12804 do_GetService("@mozilla.org/embedcomp/prompt-collection;1");
12805 if (!prompter) {
12806 return NS_ERROR_NOT_AVAILABLE;
12807 }
12808
12809 return prompter->ConfirmRepost(mBrowsingContext, aRepost);
12810}
12811
12812nsresult nsDocShell::GetPromptAndStringBundle(nsIPrompt** aPrompt,
12813 nsIStringBundle** aStringBundle) {
12814 NS_ENSURE_SUCCESS(GetInterface(NS_GET_IID(nsIPrompt), (void**)aPrompt),do { nsresult __rv = GetInterface((nsIPrompt::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::kIID), (void**)aPrompt)"
, "NS_ERROR_FAILURE", static_cast<uint32_t>(__rv), name
? " (" : "", name ? name : "", name ? ")" : ""); NS_DebugBreak
(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 12815); return NS_ERROR_FAILURE; } } while (false)
12815 NS_ERROR_FAILURE)do { nsresult __rv = GetInterface((nsIPrompt::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::kIID), (void**)aPrompt)"
, "NS_ERROR_FAILURE", static_cast<uint32_t>(__rv), name
? " (" : "", name ? name : "", name ? ")" : ""); NS_DebugBreak
(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 12815); return NS_ERROR_FAILURE; } } while (false)
;
12816
12817 nsCOMPtr<nsIStringBundleService> stringBundleService =
12818 mozilla::components::StringBundle::Service();
12819 NS_ENSURE_TRUE(stringBundleService, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(stringBundleService)), 0))) {
NS_DebugBreak(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "stringBundleService"
") failed", nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 12819); return NS_ERROR_FAILURE; } } while (false)
;
12820
12821 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, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 12823); return NS_ERROR_FAILURE; } } while (false)
12822 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, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 12823); return NS_ERROR_FAILURE; } } while (false)
12823 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, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 12823); return NS_ERROR_FAILURE; } } while (false)
;
12824
12825 return NS_OK;
12826}
12827
12828ScrollContainerFrame* nsDocShell::GetRootScrollContainerFrame() {
12829 PresShell* presShell = GetPresShell();
12830 NS_ENSURE_TRUE(presShell, nullptr)do { if ((__builtin_expect(!!(!(presShell)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "presShell" ") failed", nullptr
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 12830);
return nullptr; } } while (false)
;
12831
12832 return presShell->GetRootScrollContainerFrame();
12833}
12834
12835nsresult nsDocShell::EnsureScriptEnvironment() {
12836 if (mScriptGlobal) {
12837 return NS_OK;
12838 }
12839
12840 if (mIsBeingDestroyed) {
12841 return NS_ERROR_NOT_AVAILABLE;
12842 }
12843
12844#ifdef DEBUG1
12845 NS_ASSERTION(!mInEnsureScriptEnv,do { if (!(!mInEnsureScriptEnv)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "Infinite loop! Calling EnsureScriptEnvironment() from " "within EnsureScriptEnvironment()!"
, "!mInEnsureScriptEnv", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 12847); MOZ_PretendNoReturn(); } } while (0)
12846 "Infinite loop! Calling EnsureScriptEnvironment() from "do { if (!(!mInEnsureScriptEnv)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "Infinite loop! Calling EnsureScriptEnvironment() from " "within EnsureScriptEnvironment()!"
, "!mInEnsureScriptEnv", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 12847); MOZ_PretendNoReturn(); } } while (0)
12847 "within EnsureScriptEnvironment()!")do { if (!(!mInEnsureScriptEnv)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "Infinite loop! Calling EnsureScriptEnvironment() from " "within EnsureScriptEnvironment()!"
, "!mInEnsureScriptEnv", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 12847); MOZ_PretendNoReturn(); } } while (0)
;
12848
12849 // Yeah, this isn't re-entrant safe, but that's ok since if we
12850 // re-enter this method, we'll infinitely loop...
12851 AutoRestore<bool> boolSetter(mInEnsureScriptEnv);
12852 mInEnsureScriptEnv = true;
12853#endif
12854
12855 nsCOMPtr<nsIWebBrowserChrome> browserChrome(do_GetInterface(mTreeOwner));
12856 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, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 12856); return NS_ERROR_NOT_AVAILABLE; } } while (false)
;
12857
12858 uint32_t chromeFlags;
12859 browserChrome->GetChromeFlags(&chromeFlags);
12860
12861 // If our window is modal and we're not opened as chrome, make
12862 // this window a modal content window.
12863 mScriptGlobal = nsGlobalWindowOuter::Create(this, mItemType == typeChrome);
12864 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",
"/root/firefox-clang/docshell/base/nsDocShell.cpp", 12864); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "mScriptGlobal" ")"); do { MOZ_CrashSequence
(__null, 12864); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
12865
12866 // Ensure the script object is set up to run script.
12867 return mScriptGlobal->EnsureScriptEnvironment();
12868}
12869
12870nsresult nsDocShell::EnsureEditorData() {
12871 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"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 12871);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mIsBeingDestroyed"
")"); do { MOZ_CrashSequence(__null, 12871); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12872
12873 bool openDocHasDetachedEditor = mOSHE && mOSHE->HasDetachedEditor();
12874 if (!mEditorData && !mIsBeingDestroyed && !openDocHasDetachedEditor) {
12875 // We shouldn't recreate the editor data if it already exists, or
12876 // we're shutting down, or we already have a detached editor data
12877 // stored in the session history. We should only have one editordata
12878 // per docshell.
12879 mEditorData = MakeUnique<nsDocShellEditorData>(this);
12880 }
12881
12882 return mEditorData ? NS_OK : NS_ERROR_NOT_AVAILABLE;
12883}
12884
12885nsresult nsDocShell::EnsureFind() {
12886 if (!mFind) {
12887 mFind = new nsWebBrowserFind();
12888 }
12889
12890 // we promise that the nsIWebBrowserFind that we return has been set
12891 // up to point to the focused, or content window, so we have to
12892 // set that up each time.
12893
12894 nsIScriptGlobalObject* scriptGO = GetScriptGlobalObject();
12895 NS_ENSURE_TRUE(scriptGO, NS_ERROR_UNEXPECTED)do { if ((__builtin_expect(!!(!(scriptGO)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "scriptGO" ") failed", nullptr
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 12895);
return NS_ERROR_UNEXPECTED; } } while (false)
;
12896
12897 // default to our window
12898 nsCOMPtr<nsPIDOMWindowOuter> ourWindow = do_QueryInterface(scriptGO);
12899 nsCOMPtr<nsPIDOMWindowOuter> windowToSearch;
12900 nsFocusManager::GetFocusedDescendant(ourWindow,
12901 nsFocusManager::eIncludeAllDescendants,
12902 getter_AddRefs(windowToSearch));
12903
12904 nsCOMPtr<nsIWebBrowserFindInFrames> findInFrames = do_QueryInterface(mFind);
12905 if (!findInFrames) {
12906 return NS_ERROR_NO_INTERFACE;
12907 }
12908
12909 nsresult rv = findInFrames->SetRootSearchFrame(ourWindow);
12910 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
12911 return rv;
12912 }
12913 rv = findInFrames->SetCurrentSearchFrame(windowToSearch);
12914 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
12915 return rv;
12916 }
12917
12918 return NS_OK;
12919}
12920
12921NS_IMETHODIMPnsresult
12922nsDocShell::IsBeingDestroyed(bool* aDoomed) {
12923 NS_ENSURE_ARG(aDoomed)do { if ((__builtin_expect(!!(!(aDoomed)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aDoomed" ") failed", nullptr
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 12923);
return NS_ERROR_INVALID_ARG; } } while (false)
;
12924 *aDoomed = mIsBeingDestroyed;
12925 return NS_OK;
12926}
12927
12928NS_IMETHODIMPnsresult
12929nsDocShell::GetIsExecutingOnLoadHandler(bool* aResult) {
12930 NS_ENSURE_ARG(aResult)do { if ((__builtin_expect(!!(!(aResult)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aResult" ") failed", nullptr
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 12930);
return NS_ERROR_INVALID_ARG; } } while (false)
;
12931 *aResult = mIsExecutingOnLoadHandler;
12932 return NS_OK;
12933}
12934
12935NS_IMETHODIMPnsresult
12936nsDocShell::GetLayoutHistoryState(nsILayoutHistoryState** aLayoutHistoryState) {
12937 nsCOMPtr<nsILayoutHistoryState> state;
12938 if (mozilla::SessionHistoryInParent()) {
12939 if (mActiveEntry) {
12940 state = mActiveEntry->GetLayoutHistoryState();
12941 }
12942 } else {
12943 if (mOSHE) {
12944 state = mOSHE->GetLayoutHistoryState();
12945 }
12946 }
12947 state.forget(aLayoutHistoryState);
12948 return NS_OK;
12949}
12950
12951NS_IMETHODIMPnsresult
12952nsDocShell::SetLayoutHistoryState(nsILayoutHistoryState* aLayoutHistoryState) {
12953 if (mOSHE) {
12954 mOSHE->SetLayoutHistoryState(aLayoutHistoryState);
12955 }
12956 if (mActiveEntry) {
12957 mActiveEntry->SetLayoutHistoryState(aLayoutHistoryState);
12958 }
12959 return NS_OK;
12960}
12961
12962nsDocShell::InterfaceRequestorProxy::InterfaceRequestorProxy(
12963 nsIInterfaceRequestor* aRequestor) {
12964 if (aRequestor) {
12965 mWeakPtr = do_GetWeakReference(aRequestor);
12966 }
12967}
12968
12969nsDocShell::InterfaceRequestorProxy::~InterfaceRequestorProxy() {
12970 mWeakPtr = nullptr;
12971}
12972
12973NS_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" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 12973); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { MOZ_CrashSequence(__null, 12973
); __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" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 12973); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"nsDocShell::InterfaceRequestorProxy\" != nullptr"
") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__null
, 12973); __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" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 12973); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { MOZ_CrashSequence(__null, 12973
); __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" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 12973); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"nsDocShell::InterfaceRequestorProxy\" != nullptr"
") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__null
, 12973); __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"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 12973);
MOZ_PretendNoReturn(); } } while (0); nsresult rv = NS_ERROR_FAILURE
; static_assert(1 > 0, "Need more arguments to NS_INTERFACE_TABLE"
); static const QITableEntry table[] = { {&mozilla::detail
::kImplementedIID<nsDocShell::InterfaceRequestorProxy, nsIInterfaceRequestor
>, int32_t( reinterpret_cast<char*>(static_cast<nsIInterfaceRequestor
*>((nsDocShell::InterfaceRequestorProxy*)0x1000)) - reinterpret_cast
<char*>((nsDocShell::InterfaceRequestorProxy*)0x1000))}
, {&mozilla::detail::kImplementedIID<nsDocShell::InterfaceRequestorProxy
, nsISupports>, int32_t(reinterpret_cast<char*>(static_cast
<nsISupports*>( static_cast<nsIInterfaceRequestor*>
((nsDocShell::InterfaceRequestorProxy*)0x1000))) - reinterpret_cast
<char*>((nsDocShell::InterfaceRequestorProxy*)0x1000))}
, { nullptr, 0 } } ; static_assert(std::size(table) > 1, "need at least 1 interface"
); rv = NS_TableDrivenQI(static_cast<void*>(this), aIID
, aInstancePtr, table); return rv; }
12974
12975NS_IMETHODIMPnsresult
12976nsDocShell::InterfaceRequestorProxy::GetInterface(const nsIID& aIID,
12977 void** aSink) {
12978 NS_ENSURE_ARG_POINTER(aSink)do { if ((__builtin_expect(!!(!(aSink)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aSink" ") failed", nullptr
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 12978);
return NS_ERROR_INVALID_POINTER; } } while (false)
;
12979 nsCOMPtr<nsIInterfaceRequestor> ifReq = do_QueryReferent(mWeakPtr);
12980 if (ifReq) {
12981 return ifReq->GetInterface(aIID, aSink);
12982 }
12983 *aSink = nullptr;
12984 return NS_NOINTERFACE;
12985}
12986
12987//*****************************************************************************
12988// nsDocShell::nsIAuthPromptProvider
12989//*****************************************************************************
12990
12991NS_IMETHODIMPnsresult
12992nsDocShell::GetAuthPrompt(uint32_t aPromptReason, const nsIID& aIID,
12993 void** aResult) {
12994 // a priority prompt request will override a false mAllowAuth setting
12995 bool priorityPrompt = (aPromptReason == PROMPT_PROXY);
12996
12997 if (!mAllowAuth && !priorityPrompt) {
12998 return NS_ERROR_NOT_AVAILABLE;
12999 }
13000
13001 // we're either allowing auth, or it's a proxy request
13002 nsresult rv;
13003 nsCOMPtr<nsIPromptFactory> wwatch =
13004 do_GetService(NS_WINDOWWATCHER_CONTRACTID"@mozilla.org/embedcomp/window-watcher;1", &rv);
13005 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, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 13005); return rv; } } while (false)
;
13006
13007 rv = EnsureScriptEnvironment();
13008 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, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 13008); return rv; } } while (false)
;
13009
13010 // Get the an auth prompter for our window so that the parenting
13011 // of the dialogs works as it should when using tabs.
13012
13013 return wwatch->GetPrompt(mScriptGlobal, aIID,
13014 reinterpret_cast<void**>(aResult));
13015}
13016
13017//*****************************************************************************
13018// nsDocShell::nsILoadContext
13019//*****************************************************************************
13020
13021NS_IMETHODIMPnsresult
13022nsDocShell::GetAssociatedWindow(mozIDOMWindowProxy** aWindow) {
13023 CallGetInterface(this, aWindow);
13024 return NS_OK;
13025}
13026
13027NS_IMETHODIMPnsresult
13028nsDocShell::GetTopWindow(mozIDOMWindowProxy** aWindow) {
13029 return mBrowsingContext->GetTopWindow(aWindow);
13030}
13031
13032NS_IMETHODIMPnsresult
13033nsDocShell::GetTopFrameElement(Element** aElement) {
13034 return mBrowsingContext->GetTopFrameElement(aElement);
13035}
13036
13037NS_IMETHODIMPnsresult
13038nsDocShell::GetUseTrackingProtection(bool* aUseTrackingProtection) {
13039 return mBrowsingContext->GetUseTrackingProtection(aUseTrackingProtection);
13040}
13041
13042NS_IMETHODIMPnsresult
13043nsDocShell::SetUseTrackingProtection(bool aUseTrackingProtection) {
13044 return mBrowsingContext->SetUseTrackingProtection(aUseTrackingProtection);
13045}
13046
13047NS_IMETHODIMPnsresult
13048nsDocShell::GetIsContent(bool* aIsContent) {
13049 *aIsContent = (mItemType == typeContent);
13050 return NS_OK;
13051}
13052
13053bool nsDocShell::IsOKToLoadURI(nsIURI* aURI) {
13054 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!" ")"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 13054);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "aURI" ") (" "Must have a URI!"
")"); do { MOZ_CrashSequence(__null, 13054); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
13055
13056 if (!mFiredUnloadEvent) {
13057 return true;
13058 }
13059
13060 if (!mLoadingURI) {
13061 return false;
13062 }
13063
13064 bool isPrivateWin = false;
13065 Document* doc = GetDocument();
13066 if (doc) {
13067 isPrivateWin =
13068 doc->NodePrincipal()->OriginAttributesRef().IsPrivateBrowsing();
13069 }
13070
13071 nsCOMPtr<nsIScriptSecurityManager> secMan =
13072 do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID"@mozilla.org/scriptsecuritymanager;1");
13073 return secMan && NS_SUCCEEDED(secMan->CheckSameOriginURI(((bool)(__builtin_expect(!!(!NS_FAILED_impl(secMan->CheckSameOriginURI
( aURI, mLoadingURI, false, isPrivateWin))), 1)))
13074 aURI, mLoadingURI, false, isPrivateWin))((bool)(__builtin_expect(!!(!NS_FAILED_impl(secMan->CheckSameOriginURI
( aURI, mLoadingURI, false, isPrivateWin))), 1)))
;
13075}
13076
13077//
13078// Routines for selection and clipboard
13079//
13080nsresult nsDocShell::GetControllerForCommand(const char* aCommand,
13081 nsIController** aResult) {
13082 NS_ENSURE_ARG_POINTER(aResult)do { if ((__builtin_expect(!!(!(aResult)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aResult" ") failed", nullptr
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 13082);
return NS_ERROR_INVALID_POINTER; } } while (false)
;
13083 *aResult = nullptr;
13084
13085 NS_ENSURE_TRUE(mScriptGlobal, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(mScriptGlobal)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "mScriptGlobal" ") failed"
, nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 13085); return NS_ERROR_FAILURE; } } while (false)
;
13086
13087 nsCOMPtr<nsPIWindowRoot> root = mScriptGlobal->GetTopWindowRoot();
13088 NS_ENSURE_TRUE(root, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(root)), 0))) { NS_DebugBreak(
NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "root" ") failed", nullptr
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 13088);
return NS_ERROR_FAILURE; } } while (false)
;
13089
13090 return root->GetControllerForCommand(aCommand, false /* for any window */,
13091 aResult);
13092}
13093
13094NS_IMETHODIMPnsresult
13095nsDocShell::IsCommandEnabled(const char* aCommand, bool* aResult) {
13096 NS_ENSURE_ARG_POINTER(aResult)do { if ((__builtin_expect(!!(!(aResult)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aResult" ") failed", nullptr
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 13096);
return NS_ERROR_INVALID_POINTER; } } while (false)
;
13097 *aResult = false;
13098
13099 nsresult rv = NS_ERROR_FAILURE;
13100
13101 nsCOMPtr<nsIController> controller;
13102 rv = GetControllerForCommand(aCommand, getter_AddRefs(controller));
13103 if (controller) {
13104 rv = controller->IsCommandEnabled(aCommand, aResult);
13105 }
13106
13107 return rv;
13108}
13109
13110NS_IMETHODIMPnsresult
13111nsDocShell::DoCommand(const char* aCommand) {
13112 nsresult rv = NS_ERROR_FAILURE;
13113
13114 nsCOMPtr<nsIController> controller;
13115 rv = GetControllerForCommand(aCommand, getter_AddRefs(controller));
13116 if (controller) {
13117 rv = controller->DoCommand(aCommand);
13118 }
13119
13120 return rv;
13121}
13122
13123NS_IMETHODIMPnsresult
13124nsDocShell::DoCommandWithParams(const char* aCommand,
13125 nsICommandParams* aParams) {
13126 nsCOMPtr<nsIController> controller;
13127 nsresult rv = GetControllerForCommand(aCommand, getter_AddRefs(controller));
13128 if (NS_WARN_IF(NS_FAILED(rv))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(rv
)), 0))), "NS_FAILED(rv)", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 13128)
) {
13129 return rv;
13130 }
13131
13132 nsCOMPtr<nsICommandController> commandController =
13133 do_QueryInterface(controller, &rv);
13134 if (NS_WARN_IF(NS_FAILED(rv))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(rv
)), 0))), "NS_FAILED(rv)", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 13134)
) {
13135 return rv;
13136 }
13137
13138 return commandController->DoCommandWithParams(aCommand, aParams);
13139}
13140
13141nsresult nsDocShell::EnsureCommandHandler() {
13142 if (!mCommandManager) {
13143 if (nsCOMPtr<nsPIDOMWindowOuter> domWindow = GetWindow()) {
13144 mCommandManager = new nsCommandManager(domWindow);
13145 }
13146 }
13147 return mCommandManager ? NS_OK : NS_ERROR_FAILURE;
13148}
13149
13150// link handling
13151
13152class OnLinkClickEvent : public Runnable {
13153 public:
13154 OnLinkClickEvent(nsDocShell* aHandler, nsIContent* aContent,
13155 nsDocShellLoadState* aLoadState, bool aNoOpenerImplied,
13156 nsIPrincipal* aTriggeringPrincipal);
13157
13158 NS_IMETHODvirtual nsresult Run() override {
13159 // We need to set up an AutoJSAPI here for the following reason: When we
13160 // do OnLinkClickSync we'll eventually end up in
13161 // nsGlobalWindow::OpenInternal which only does popup blocking if
13162 // !LegacyIsCallerChromeOrNativeCode(). So we need to fake things so that
13163 // we don't look like native code as far as LegacyIsCallerNativeCode() is
13164 // concerned. (Bug 1930445)
13165 AutoJSAPI jsapi;
13166 if (jsapi.Init(mContent->OwnerDoc()->GetScopeObject())) {
13167 mHandler->OnLinkClickSync(mContent, mLoadState, mNoOpenerImplied,
13168 mTriggeringPrincipal);
13169 }
13170 return NS_OK;
13171 }
13172
13173 private:
13174 RefPtr<nsDocShell> mHandler;
13175 nsCOMPtr<nsIContent> mContent;
13176 RefPtr<nsDocShellLoadState> mLoadState;
13177 nsCOMPtr<nsIPrincipal> mTriggeringPrincipal;
13178 bool mNoOpenerImplied;
13179};
13180
13181OnLinkClickEvent::OnLinkClickEvent(nsDocShell* aHandler, nsIContent* aContent,
13182 nsDocShellLoadState* aLoadState,
13183 bool aNoOpenerImplied,
13184 nsIPrincipal* aTriggeringPrincipal)
13185 : mozilla::Runnable("OnLinkClickEvent"),
13186 mHandler(aHandler),
13187 mContent(aContent),
13188 mLoadState(aLoadState),
13189 mTriggeringPrincipal(aTriggeringPrincipal),
13190 mNoOpenerImplied(aNoOpenerImplied) {}
13191
13192nsresult nsDocShell::OnLinkClick(
13193 nsIContent* aContent, nsIURI* aURI, const nsAString& aTargetSpec,
13194 const nsAString& aFileName, nsIInputStream* aPostDataStream,
13195 nsIInputStream* aHeadersDataStream, bool aIsUserTriggered,
13196 UserNavigationInvolvement aUserInvolvement,
13197 nsIPrincipal* aTriggeringPrincipal, nsIContentSecurityPolicy* aCsp) {
13198#ifndef ANDROID
13199 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" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 13199); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aTriggeringPrincipal"
") (" "Need a valid triggeringPrincipal" ")"); do { MOZ_CrashSequence
(__null, 13199); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
13200#endif
13201 NS_ASSERTION(NS_IsMainThread(), "wrong thread")do { if (!(NS_IsMainThread())) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "wrong thread", "NS_IsMainThread()", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 13201); MOZ_PretendNoReturn(); } } while (0)
;
13202
13203 if (!IsNavigationAllowed() || !IsOKToLoadURI(aURI)) {
13204 return NS_OK;
13205 }
13206
13207 // On history navigation through Back/Forward buttons, don't execute
13208 // automatic JavaScript redirection such as |anchorElement.click()| or
13209 // |formElement.submit()|.
13210 //
13211 // XXX |formElement.submit()| bypasses this checkpoint because it calls
13212 // nsDocShell::OnLinkClickSync(...) instead.
13213 if (ShouldBlockLoadingForBackButton()) {
13214 return NS_OK;
13215 }
13216
13217 if (aContent->IsEditable()) {
13218 return NS_OK;
13219 }
13220
13221 Document* ownerDoc = aContent->OwnerDoc();
13222 if (nsContentUtils::IsExternalProtocol(aURI)) {
13223 ownerDoc->EnsureNotEnteringAndExitFullscreen();
13224 }
13225
13226 bool noOpenerImplied = false;
13227 nsAutoString target(aTargetSpec);
13228 if (aFileName.IsVoid() &&
13229 ShouldOpenInBlankTarget(aTargetSpec, aURI, aContent, aIsUserTriggered)) {
13230 target = u"_blank";
13231 if (!aTargetSpec.Equals(target)) {
13232 noOpenerImplied = true;
13233 }
13234 }
13235
13236 // https://html.spec.whatwg.org/#downloading-hyperlinks
13237 // Step 6, step 6.1, step 6.2
13238 // aFileName not being void implies a download attribute, since we've already
13239 // checked if the attribute is present in `nsContentUtils::TriggerLinkClick`
13240 // and made it void otherwise.
13241 if (!aFileName.IsVoid() &&
13242 aUserInvolvement != UserNavigationInvolvement::BrowserUI) {
13243 if (nsCOMPtr<nsPIDOMWindowInner> window = ownerDoc->GetInnerWindow()) {
13244 if (RefPtr<Navigation> navigation = window->Navigation()) {
13245 AutoJSAPI jsapi;
13246 if (jsapi.Init(window)) {
13247 RefPtr element = aContent->AsElement();
13248 // Step 6.4
13249 bool shouldContinue = navigation->FireDownloadRequestNavigateEvent(
13250 jsapi.cx(), aURI, aUserInvolvement, element, aFileName);
13251
13252 // Step 6.5
13253 if (!shouldContinue) {
13254 return NS_OK;
13255 }
13256 }
13257 }
13258 }
13259 }
13260
13261 RefPtr<nsDocShellLoadState> loadState = new nsDocShellLoadState(aURI);
13262 loadState->SetTarget(target);
13263 loadState->SetFileName(aFileName);
13264 loadState->SetPostDataStream(aPostDataStream);
13265 loadState->SetHeadersStream(aHeadersDataStream);
13266 loadState->SetFirstParty(true);
13267 loadState->SetTriggeringPrincipal(
13268 aTriggeringPrincipal ? aTriggeringPrincipal : aContent->NodePrincipal());
13269 loadState->SetPrincipalToInherit(aContent->NodePrincipal());
13270 loadState->SetCsp(aCsp ? aCsp : aContent->GetCsp());
13271 loadState->SetAllowFocusMove(UserActivation::IsHandlingUserInput());
13272
13273 const bool hasValidUserGestureActivation =
13274 ownerDoc->HasValidTransientUserGestureActivation();
13275 loadState->SetHasValidUserGestureActivation(hasValidUserGestureActivation);
13276 loadState->SetTextDirectiveUserActivation(
13277 ownerDoc->ConsumeTextDirectiveUserActivation() ||
13278 hasValidUserGestureActivation);
13279 loadState->SetUserNavigationInvolvement(aUserInvolvement);
13280 loadState->SetTriggeringClassificationFlags(
13281 ownerDoc->GetScriptTrackingFlags());
13282
13283 nsCOMPtr<nsIRunnable> ev = new OnLinkClickEvent(
13284 this, aContent, loadState, noOpenerImplied, aTriggeringPrincipal);
13285 return Dispatch(ev.forget());
13286}
13287
13288bool nsDocShell::ShouldOpenInBlankTarget(const nsAString& aOriginalTarget,
13289 nsIURI* aLinkURI, nsIContent* aContent,
13290 bool aIsUserTriggered) {
13291 if (aLinkURI->SchemeIs("javascript")) {
13292 return false;
13293 }
13294
13295 // External links from within app tabs should always open in new tabs
13296 // instead of replacing the app tab's page (Bug 575561)
13297 // nsIURI.host can throw for non-nsStandardURL nsIURIs. If we fail to
13298 // get either host, just return false to use the original target.
13299 nsAutoCString linkHost;
13300 if (NS_FAILED(aLinkURI->GetHost(linkHost))((bool)(__builtin_expect(!!(NS_FAILED_impl(aLinkURI->GetHost
(linkHost))), 0)))
) {
13301 return false;
13302 }
13303
13304 // The targetTopLevelLinkClicksToBlank property on BrowsingContext allows
13305 // privileged code to change the default targeting behaviour. In particular,
13306 // if a user-initiated link click for the (or targetting the) top-level frame
13307 // is detected, we default the target to "_blank" to give it a new
13308 // top-level BrowsingContext.
13309 if (mBrowsingContext->TargetTopLevelLinkClicksToBlank() && aIsUserTriggered &&
13310 ((aOriginalTarget.IsEmpty() && mBrowsingContext->IsTop()) ||
13311 aOriginalTarget == u"_top"_ns)) {
13312 return true;
13313 }
13314
13315 // Don't modify non-default targets.
13316 if (!aOriginalTarget.IsEmpty()) {
13317 return false;
13318 }
13319
13320 // Only check targets that are in extension panels or app tabs.
13321 // (isAppTab will be false for app tab subframes).
13322 nsString mmGroup = mBrowsingContext->Top()->GetMessageManagerGroup();
13323 if (!mmGroup.EqualsLiteral("webext-browsers") &&
13324 !mBrowsingContext->IsAppTab()) {
13325 return false;
13326 }
13327
13328 nsCOMPtr<nsIURI> docURI = aContent->OwnerDoc()->GetDocumentURIObject();
13329 if (!docURI) {
13330 return false;
13331 }
13332
13333 nsAutoCString docHost;
13334 if (NS_FAILED(docURI->GetHost(docHost))((bool)(__builtin_expect(!!(NS_FAILED_impl(docURI->GetHost
(docHost))), 0)))
) {
13335 return false;
13336 }
13337
13338 if (linkHost.Equals(docHost)) {
13339 return false;
13340 }
13341
13342 // Special case: ignore "www" prefix if it is part of host string
13343 return linkHost.Length() < docHost.Length()
13344 ? !docHost.Equals("www."_ns + linkHost)
13345 : !linkHost.Equals("www."_ns + docHost);
13346}
13347
13348static bool ElementCanHaveNoopener(nsIContent* aContent) {
13349 // Make sure we are dealing with either an <A>, <AREA>, or <FORM> element in
13350 // the HTML, XHTML, or SVG namespace.
13351 return aContent->IsAnyOfHTMLElements(nsGkAtoms::a, nsGkAtoms::area,
13352 nsGkAtoms::form) ||
13353 aContent->IsSVGElement(nsGkAtoms::a);
13354}
13355
13356nsresult nsDocShell::OnLinkClickSync(nsIContent* aContent,
13357 nsDocShellLoadState* aLoadState,
13358 bool aNoOpenerImplied,
13359 nsIPrincipal* aTriggeringPrincipal) {
13360 if (!IsNavigationAllowed() || !IsOKToLoadURI(aLoadState->URI())) {
13361 return NS_OK;
13362 }
13363
13364 // XXX When the linking node was HTMLFormElement, it is synchronous event.
13365 // That is, the caller of this method is not |OnLinkClickEvent::Run()|
13366 // but |HTMLFormElement::SubmitSubmission(...)|.
13367 if (aContent->IsHTMLElement(nsGkAtoms::form) &&
13368 ShouldBlockLoadingForBackButton()) {
13369 return NS_OK;
13370 }
13371
13372 if (aContent->IsEditable()) {
13373 return NS_OK;
13374 }
13375
13376 // if the triggeringPrincipal is not passed explicitly, then we
13377 // fall back to using doc->NodePrincipal() as the triggeringPrincipal.
13378 nsCOMPtr<nsIPrincipal> triggeringPrincipal =
13379 aTriggeringPrincipal ? aTriggeringPrincipal : aContent->NodePrincipal();
13380
13381 {
13382 // defer to an external protocol handler if necessary...
13383 nsCOMPtr<nsIExternalProtocolService> extProtService =
13384 do_GetService(NS_EXTERNALPROTOCOLSERVICE_CONTRACTID"@mozilla.org/uriloader/external-protocol-service;1");
13385 if (extProtService) {
13386 nsAutoCString scheme;
13387 aLoadState->URI()->GetScheme(scheme);
13388 if (!scheme.IsEmpty()) {
13389 // if the URL scheme does not correspond to an exposed protocol, then
13390 // we need to hand this link click over to the external protocol
13391 // handler.
13392 bool isExposed;
13393 nsresult rv =
13394 extProtService->IsExposedProtocol(scheme.get(), &isExposed);
13395 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && !isExposed) {
13396 return extProtService->LoadURI(
13397 aLoadState->URI(), triggeringPrincipal, nullptr, mBrowsingContext,
13398 /* aTriggeredExternally */
13399 false,
13400 /* aHasValidUserGestureActivation */
13401 aContent->OwnerDoc()->HasValidTransientUserGestureActivation(),
13402 /* aNewWindowTarget */ false);
13403 }
13404 }
13405 }
13406 }
13407 uint32_t triggeringSandboxFlags = 0;
13408 uint64_t triggeringWindowId = 0;
13409 bool triggeringStorageAccess = false;
13410 if (mBrowsingContext) {
13411 triggeringSandboxFlags = aContent->OwnerDoc()->GetSandboxFlags();
13412 triggeringWindowId = aContent->OwnerDoc()->InnerWindowID();
13413 triggeringStorageAccess = aContent->OwnerDoc()->UsingStorageAccess();
13414 }
13415
13416 uint32_t flags = INTERNAL_LOAD_FLAGS_NONE;
13417 bool elementCanHaveNoopener = ElementCanHaveNoopener(aContent);
13418 bool triggeringPrincipalIsSystemPrincipal =
13419 aLoadState->TriggeringPrincipal()->IsSystemPrincipal();
13420 if (elementCanHaveNoopener) {
13421 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()"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 13421);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "aContent->IsHTMLElement() || aContent->IsSVGElement()"
")"); do { MOZ_CrashSequence(__null, 13421); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
13422 nsAutoString relString;
13423 aContent->AsElement()->GetAttr(nsGkAtoms::rel, relString);
13424 nsWhitespaceTokenizerTemplate<nsContentUtils::IsHTMLWhitespace> tok(
13425 relString);
13426
13427 bool targetBlank = aLoadState->Target().LowerCaseEqualsLiteral("_blank");
13428 bool explicitOpenerSet = false;
13429
13430 // The opener behaviour follows a hierarchy, such that if a higher
13431 // priority behaviour is specified, it always takes priority. That
13432 // priority is currently: norefrerer > noopener > opener > default
13433
13434 while (tok.hasMoreTokens()) {
13435 const nsAString& token = tok.nextToken();
13436 if (token.LowerCaseEqualsLiteral("noreferrer")) {
13437 flags |= INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER |
13438 INTERNAL_LOAD_FLAGS_NO_OPENER;
13439 // noreferrer cannot be overwritten by a 'rel=opener'.
13440 explicitOpenerSet = true;
13441 break;
13442 }
13443
13444 if (token.LowerCaseEqualsLiteral("noopener")) {
13445 flags |= INTERNAL_LOAD_FLAGS_NO_OPENER;
13446 explicitOpenerSet = true;
13447 }
13448
13449 if (targetBlank && StaticPrefs::dom_targetBlankNoOpener_enabled() &&
13450 token.LowerCaseEqualsLiteral("opener") && !explicitOpenerSet) {
13451 explicitOpenerSet = true;
13452 }
13453 }
13454
13455 if (targetBlank && StaticPrefs::dom_targetBlankNoOpener_enabled() &&
13456 !explicitOpenerSet && !triggeringPrincipalIsSystemPrincipal) {
13457 flags |= INTERNAL_LOAD_FLAGS_NO_OPENER;
13458 }
13459
13460 if (aNoOpenerImplied) {
13461 flags |= INTERNAL_LOAD_FLAGS_NO_OPENER;
13462 }
13463 }
13464
13465 // Get the owner document of the link that was clicked, this will be
13466 // the document that the link is in, or the last document that the
13467 // link was in. From that document, we'll get the URI to use as the
13468 // referrer, since the current URI in this docshell may be a
13469 // new document that we're in the process of loading.
13470 RefPtr<Document> referrerDoc = aContent->OwnerDoc();
13471
13472 // Now check that the referrerDoc's inner window is the current inner
13473 // window for mScriptGlobal. If it's not, then we don't want to
13474 // follow this link.
13475 nsPIDOMWindowInner* referrerInner = referrerDoc->GetInnerWindow();
13476 if (!mScriptGlobal || !referrerInner ||
13477 mScriptGlobal->GetCurrentInnerWindow() != referrerInner) {
13478 // We're no longer the current inner window
13479 return NS_OK;
13480 }
13481
13482 // referrer could be null here in some odd cases, but that's ok,
13483 // we'll just load the link w/o sending a referrer in those cases.
13484
13485 // If this is an anchor element, grab its type property to use as a hint
13486 nsAutoString typeHint;
13487 RefPtr<HTMLAnchorElement> anchor = HTMLAnchorElement::FromNode(aContent);
13488 if (anchor) {
13489 anchor->GetType(typeHint);
13490 NS_ConvertUTF16toUTF8 utf8Hint(typeHint);
13491 nsAutoCString type, dummy;
13492 NS_ParseRequestContentType(utf8Hint, type, dummy);
13493 CopyUTF8toUTF16(type, typeHint);
13494 }
13495
13496 uint32_t loadType = LOAD_LINK;
13497 if (aLoadState->IsFormSubmission()) {
13498 if (aLoadState->Target().IsEmpty()) {
13499 // We set the right load type here for form submissions with an empty
13500 // target. Form submission with a non-empty target are handled in
13501 // nsDocShell::PerformRetargeting after we've selected the correct target
13502 // BC.
13503 loadType = GetLoadTypeForFormSubmission(GetBrowsingContext(), aLoadState);
13504 }
13505 } else {
13506 // Link click can be triggered inside an onload handler, and we don't want
13507 // to add history entry in this case.
13508 bool inOnLoadHandler = false;
13509 GetIsExecutingOnLoadHandler(&inOnLoadHandler);
13510 if (inOnLoadHandler) {
13511 loadType = LOAD_NORMAL_REPLACE;
13512 }
13513 }
13514
13515 nsCOMPtr<nsIReferrerInfo> referrerInfo =
13516 elementCanHaveNoopener ? new ReferrerInfo(*aContent->AsElement())
13517 : new ReferrerInfo(*referrerDoc);
13518
13519 aLoadState->SetTriggeringSandboxFlags(triggeringSandboxFlags);
13520 aLoadState->SetTriggeringWindowId(triggeringWindowId);
13521 aLoadState->SetTriggeringStorageAccess(triggeringStorageAccess);
13522 aLoadState->SetReferrerInfo(referrerInfo);
13523 aLoadState->SetInternalLoadFlags(flags);
13524 aLoadState->SetTypeHint(NS_ConvertUTF16toUTF8(typeHint));
13525 aLoadState->SetLoadType(loadType);
13526 aLoadState->SetSourceBrowsingContext(mBrowsingContext);
13527 aLoadState->SetSourceElement(aContent->AsElement());
13528
13529 nsresult rv = InternalLoad(aLoadState);
13530
13531 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
13532 nsPingListener::DispatchPings(this, aContent, aLoadState->URI(),
13533 referrerInfo);
13534 }
13535
13536 return rv;
13537}
13538
13539nsresult nsDocShell::OnOverLink(nsIContent* aContent, nsIURI* aURI,
13540 const nsAString& aTargetSpec) {
13541 if (aContent->IsEditable()) {
13542 return NS_OK;
13543 }
13544
13545 nsresult rv = NS_ERROR_FAILURE;
13546
13547 nsCOMPtr<nsIWebBrowserChrome> browserChrome = do_GetInterface(mTreeOwner);
13548 if (!browserChrome) {
13549 return rv;
13550 }
13551
13552 nsCOMPtr<nsIURI> exposableURI = nsIOService::CreateExposableURI(aURI);
13553 nsAutoCString spec;
13554 rv = exposableURI->GetDisplaySpec(spec);
13555 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, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 13555); return rv; } } while (false)
;
13556
13557 NS_ConvertUTF8toUTF16 uStr(spec);
13558
13559 PredictorPredict(aURI, mCurrentURI, nsINetworkPredictor::PREDICT_LINK,
13560 aContent->NodePrincipal()->OriginAttributesRef(), nullptr);
13561
13562 rv = browserChrome->SetLinkStatus(uStr);
13563 return rv;
13564}
13565
13566nsresult nsDocShell::OnLeaveLink() {
13567 nsCOMPtr<nsIWebBrowserChrome> browserChrome(do_GetInterface(mTreeOwner));
13568 nsresult rv = NS_ERROR_FAILURE;
13569
13570 if (browserChrome) {
13571 rv = browserChrome->SetLinkStatus(u""_ns);
13572 }
13573 return rv;
13574}
13575
13576bool nsDocShell::ShouldBlockLoadingForBackButton() {
13577 if (!(mLoadType & LOAD_CMD_HISTORY) ||
13578 UserActivation::IsHandlingUserInput() ||
13579 !Preferences::GetBool("accessibility.blockjsredirection")) {
13580 return false;
13581 }
13582
13583 bool canGoForward = false;
13584 GetCanGoForward(&canGoForward);
13585 return canGoForward;
13586}
13587
13588//----------------------------------------------------------------------
13589// Web Shell Services API
13590
13591// This functions is only called when a new charset is detected in loading a
13592// document.
13593nsresult nsDocShell::CharsetChangeReloadDocument(
13594 mozilla::NotNull<const mozilla::Encoding*> aEncoding, int32_t aSource) {
13595 // XXX hack. keep the aCharset and aSource wait to pick it up
13596 nsCOMPtr<nsIDocumentViewer> viewer;
13597 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, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 13597); return NS_ERROR_FAILURE; } } while (false)
;
13598 if (viewer) {
13599 int32_t source;
13600 Unused << viewer->GetReloadEncodingAndSource(&source);
13601 if (aSource > source) {
13602 viewer->SetReloadEncodingAndSource(aEncoding, aSource);
13603 if (eCharsetReloadRequested != mCharsetReloadState) {
13604 mCharsetReloadState = eCharsetReloadRequested;
13605 switch (mLoadType) {
13606 case LOAD_RELOAD_BYPASS_PROXY_AND_CACHE:
13607 return Reload(LOAD_FLAGS_CHARSET_CHANGE | LOAD_FLAGS_BYPASS_CACHE |
13608 LOAD_FLAGS_BYPASS_PROXY);
13609 case LOAD_RELOAD_BYPASS_CACHE:
13610 return Reload(LOAD_FLAGS_CHARSET_CHANGE | LOAD_FLAGS_BYPASS_CACHE);
13611 default:
13612 return Reload(LOAD_FLAGS_CHARSET_CHANGE);
13613 }
13614 }
13615 }
13616 }
13617 // return failure if this request is not accepted due to mCharsetReloadState
13618 return NS_ERROR_DOCSHELL_REQUEST_REJECTED;
13619}
13620
13621nsresult nsDocShell::CharsetChangeStopDocumentLoad() {
13622 if (eCharsetReloadRequested != mCharsetReloadState) {
13623 Stop(nsIWebNavigation::STOP_ALL);
13624 return NS_OK;
13625 }
13626 // return failer if this request is not accepted due to mCharsetReloadState
13627 return NS_ERROR_DOCSHELL_REQUEST_REJECTED;
13628}
13629
13630NS_IMETHODIMPnsresult nsDocShell::ExitPrintPreview() {
13631#if NS_PRINT_PREVIEW1
13632 nsCOMPtr<nsIWebBrowserPrint> viewer = do_QueryInterface(mDocumentViewer);
13633 return viewer->ExitPrintPreview();
13634#else
13635 return NS_OK;
13636#endif
13637}
13638
13639/* [infallible] */
13640NS_IMETHODIMPnsresult nsDocShell::GetIsTopLevelContentDocShell(
13641 bool* aIsTopLevelContentDocShell) {
13642 *aIsTopLevelContentDocShell = false;
13643
13644 if (mItemType == typeContent) {
13645 *aIsTopLevelContentDocShell = mBrowsingContext->IsTopContent();
13646 }
13647
13648 return NS_OK;
13649}
13650
13651// Implements nsILoadContext.originAttributes
13652NS_IMETHODIMPnsresult
13653nsDocShell::GetScriptableOriginAttributes(JSContext* aCx,
13654 JS::MutableHandle<JS::Value> aVal) {
13655 return mBrowsingContext->GetScriptableOriginAttributes(aCx, aVal);
13656}
13657
13658// Implements nsIDocShell.GetOriginAttributes()
13659NS_IMETHODIMPnsresult
13660nsDocShell::GetOriginAttributes(JSContext* aCx,
13661 JS::MutableHandle<JS::Value> aVal) {
13662 return mBrowsingContext->GetScriptableOriginAttributes(aCx, aVal);
13663}
13664
13665bool nsDocShell::ServiceWorkerAllowedToControlWindow(nsIPrincipal* aPrincipal,
13666 nsIURI* aURI) {
13667 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", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 13667); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPrincipal"
")"); do { MOZ_CrashSequence(__null, 13667); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
13668 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", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 13668); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aURI" ")")
; do { MOZ_CrashSequence(__null, 13668); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
13669
13670 if (UsePrivateBrowsing() || mBrowsingContext->GetSandboxFlags()) {
13671 return false;
13672 }
13673
13674 nsCOMPtr<nsIDocShellTreeItem> parent;
13675 GetInProcessSameTypeParent(getter_AddRefs(parent));
13676 nsPIDOMWindowOuter* parentOuter = parent ? parent->GetWindow() : nullptr;
13677 nsPIDOMWindowInner* parentInner =
13678 parentOuter ? parentOuter->GetCurrentInnerWindow() : nullptr;
13679
13680 StorageAccess storage =
13681 StorageAllowedForNewWindow(aPrincipal, aURI, parentInner);
13682
13683 // If the partitioned service worker is enabled, service worker is allowed to
13684 // control the window if partition is enabled.
13685 if (StaticPrefs::privacy_partition_serviceWorkers() && parentInner) {
13686 RefPtr<Document> doc = parentInner->GetExtantDoc();
13687
13688 if (doc && StoragePartitioningEnabled(storage, doc->CookieJarSettings())) {
13689 return true;
13690 }
13691 }
13692
13693 return storage == StorageAccess::eAllow;
13694}
13695
13696nsresult nsDocShell::SetOriginAttributes(const OriginAttributes& aAttrs) {
13697 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"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 13697);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mIsBeingDestroyed"
")"); do { MOZ_CrashSequence(__null, 13697); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
13698 return mBrowsingContext->SetOriginAttributes(aAttrs);
13699}
13700
13701NS_IMETHODIMPnsresult
13702nsDocShell::ResumeRedirectedLoad(uint64_t aIdentifier, int32_t aHistoryIndex) {
13703 RefPtr<nsDocShell> self = this;
13704 RefPtr<ChildProcessChannelListener> cpcl =
13705 ChildProcessChannelListener::GetSingleton();
13706
13707 // Call into InternalLoad with the pending channel when it is received.
13708 cpcl->RegisterCallback(
13709 aIdentifier, [self, aHistoryIndex](
13710 nsDocShellLoadState* aLoadState,
13711 nsTArray<Endpoint<extensions::PStreamFilterParent>>&&
13712 aStreamFilterEndpoints,
13713 nsDOMNavigationTiming* aTiming) {
13714 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()"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 13714);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->GetPendingRedirectedChannel()"
")"); do { MOZ_CrashSequence(__null, 13714); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
13715 if (NS_WARN_IF(self->mIsBeingDestroyed)NS_warn_if_impl(self->mIsBeingDestroyed, "self->mIsBeingDestroyed"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 13715)
) {
13716 aLoadState->GetPendingRedirectedChannel()->CancelWithReason(
13717 NS_BINDING_ABORTED, "nsDocShell::mIsBeingDestroyed"_ns);
13718 return NS_BINDING_ABORTED;
13719 }
13720
13721 self->mLoadType = aLoadState->LoadType();
13722 nsCOMPtr<nsIURI> previousURI;
13723 uint32_t previousFlags = 0;
13724 ExtractLastVisit(aLoadState->GetPendingRedirectedChannel(),
13725 getter_AddRefs(previousURI), &previousFlags);
13726 self->SaveLastVisit(aLoadState->GetPendingRedirectedChannel(),
13727 previousURI, previousFlags);
13728
13729 if (aTiming) {
13730 self->mTiming = new nsDOMNavigationTiming(self, aTiming);
13731 self->mBlankTiming = false;
13732 }
13733
13734 // If we're performing a history load, locate the correct history entry,
13735 // and set the relevant bits on our loadState.
13736 if (aHistoryIndex >= 0 && self->GetSessionHistory() &&
13737 !mozilla::SessionHistoryInParent()) {
13738 nsCOMPtr<nsISHistory> legacySHistory =
13739 self->GetSessionHistory()->LegacySHistory();
13740
13741 nsCOMPtr<nsISHEntry> entry;
13742 nsresult rv = legacySHistory->GetEntryAtIndex(aHistoryIndex,
13743 getter_AddRefs(entry));
13744 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
13745 legacySHistory->InternalSetRequestedIndex(aHistoryIndex);
13746 aLoadState->SetLoadType(LOAD_HISTORY);
13747 aLoadState->SetSHEntry(entry);
13748 }
13749 }
13750
13751 self->InternalLoad(aLoadState);
13752
13753 if (aLoadState->GetOriginalURIString().isSome()) {
13754 // Save URI string in case it's needed later when
13755 // sending to search engine service in EndPageLoad()
13756 self->mOriginalUriString = *aLoadState->GetOriginalURIString();
13757 }
13758
13759 for (auto& endpoint : aStreamFilterEndpoints) {
13760 extensions::StreamFilterParent::Attach(
13761 aLoadState->GetPendingRedirectedChannel(), std::move(endpoint));
13762 }
13763
13764 // If the channel isn't pending, then it means that InternalLoad
13765 // never connected it, and we shouldn't try to continue. This
13766 // can happen even if InternalLoad returned NS_OK.
13767 bool pending = false;
13768 aLoadState->GetPendingRedirectedChannel()->IsPending(&pending);
13769 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", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 13769); MOZ_PretendNoReturn(); } } while (0)
;
13770 if (!pending) {
13771 return NS_BINDING_ABORTED;
13772 }
13773 return NS_OK;
13774 });
13775 return NS_OK;
13776}
13777
13778NS_IMETHODIMPnsresult
13779nsDocShell::SetOriginAttributes(JS::Handle<JS::Value> aOriginAttributes,
13780 JSContext* aCx) {
13781 OriginAttributes attrs;
13782 if (!aOriginAttributes.isObject() || !attrs.Init(aCx, aOriginAttributes)) {
13783 return NS_ERROR_INVALID_ARG;
13784 }
13785
13786 return SetOriginAttributes(attrs);
13787}
13788
13789NS_IMETHODIMPnsresult
13790nsDocShell::GetAsyncPanZoomEnabled(bool* aOut) {
13791 if (PresShell* presShell = GetPresShell()) {
13792 *aOut = presShell->AsyncPanZoomEnabled();
13793 return NS_OK;
13794 }
13795
13796 // If we don't have a presShell, fall back to the default platform value of
13797 // whether or not APZ is enabled.
13798 *aOut = gfxPlatform::AsyncPanZoomEnabled();
13799 return NS_OK;
13800}
13801
13802bool nsDocShell::HasUnloadedParent() {
13803 for (WindowContext* wc = GetBrowsingContext()->GetParentWindowContext(); wc;
13804 wc = wc->GetParentWindowContext()) {
13805 if (!wc->IsCurrent() || wc->IsDiscarded() ||
13806 wc->GetBrowsingContext()->IsDiscarded()) {
13807 // If a parent is OOP and the parent WindowContext is no
13808 // longer current, we can assume the parent was unloaded.
13809 return true;
13810 }
13811
13812 if (wc->GetBrowsingContext()->IsInProcess() &&
13813 (!wc->GetBrowsingContext()->GetDocShell() ||
13814 wc->GetBrowsingContext()->GetDocShell()->GetIsInUnload())) {
13815 return true;
13816 }
13817 }
13818 return false;
13819}
13820
13821/* static */
13822bool nsDocShell::ShouldUpdateGlobalHistory(uint32_t aLoadType) {
13823 return !(aLoadType == LOAD_BYPASS_HISTORY || aLoadType == LOAD_ERROR_PAGE ||
13824 aLoadType & LOAD_CMD_HISTORY);
13825}
13826
13827void nsDocShell::UpdateGlobalHistoryTitle(nsIURI* aURI) {
13828 if (!mBrowsingContext->GetUseGlobalHistory() || UsePrivateBrowsing()) {
13829 return;
13830 }
13831
13832 // Global history is interested into sub-frame visits only for link-coloring
13833 // purposes, thus title updates are skipped for those.
13834 //
13835 // Moreover, some iframe documents (such as the ones created via
13836 // document.open()) inherit the document uri of the caller, which would cause
13837 // us to override a previously set page title with one from the subframe.
13838 if (IsSubframe()) {
13839 return;
13840 }
13841
13842 if (nsCOMPtr<IHistory> history = components::History::Service()) {
13843 history->SetURITitle(aURI, mTitle);
13844 }
13845}
13846
13847bool nsDocShell::IsInvisible() { return mInvisible; }
13848
13849void nsDocShell::SetInvisible(bool aInvisible) { mInvisible = aInvisible; }
13850
13851/* static */
13852void nsDocShell::MaybeNotifyKeywordSearchLoading(const nsString& aProvider,
13853 const nsString& aKeyword) {
13854 if (aProvider.IsEmpty()) {
13855 return;
13856 }
13857 nsresult rv;
13858 nsCOMPtr<nsISupportsString> isupportsString =
13859 do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID"@mozilla.org/supports-string;1", &rv);
13860 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, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 13860); return; } } while (false)
;
13861
13862 rv = isupportsString->SetData(aProvider);
13863 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, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 13863); return; } } while (false)
;
13864
13865 nsCOMPtr<nsIObserverService> obsSvc = services::GetObserverService();
13866 if (obsSvc) {
13867 // Note that "keyword-search" refers to a search via the url
13868 // bar, not a bookmarks keyword search.
13869 obsSvc->NotifyObservers(isupportsString, "keyword-search", aKeyword.get());
13870 }
13871}
13872
13873NS_IMETHODIMPnsresult
13874nsDocShell::ShouldPrepareForIntercept(nsIURI* aURI, nsIChannel* aChannel,
13875 bool* aShouldIntercept) {
13876 return mInterceptController->ShouldPrepareForIntercept(aURI, aChannel,
13877 aShouldIntercept);
13878}
13879
13880NS_IMETHODIMPnsresult
13881nsDocShell::ChannelIntercepted(nsIInterceptedChannel* aChannel) {
13882 return mInterceptController->ChannelIntercepted(aChannel);
13883}
13884
13885bool nsDocShell::InFrameSwap() {
13886 RefPtr<nsDocShell> shell = this;
13887 do {
13888 if (shell->mInFrameSwap) {
13889 return true;
13890 }
13891 shell = shell->GetInProcessParentDocshell();
13892 } while (shell);
13893 return false;
13894}
13895
13896UniquePtr<ClientSource> nsDocShell::TakeInitialClientSource() {
13897 return std::move(mInitialClientSource);
13898}
13899
13900NS_IMETHODIMPnsresult
13901nsDocShell::GetEditingSession(nsIEditingSession** aEditSession) {
13902 if (!NS_SUCCEEDED(EnsureEditorData())((bool)(__builtin_expect(!!(!NS_FAILED_impl(EnsureEditorData(
))), 1)))
) {
13903 return NS_ERROR_FAILURE;
13904 }
13905
13906 *aEditSession = do_AddRef(mEditorData->GetEditingSession()).take();
13907 return *aEditSession ? NS_OK : NS_ERROR_FAILURE;
13908}
13909
13910NS_IMETHODIMPnsresult
13911nsDocShell::GetScriptableBrowserChild(nsIBrowserChild** aBrowserChild) {
13912 *aBrowserChild = GetBrowserChild().take();
13913 return *aBrowserChild ? NS_OK : NS_ERROR_FAILURE;
13914}
13915
13916already_AddRefed<nsIBrowserChild> nsDocShell::GetBrowserChild() {
13917 nsCOMPtr<nsIBrowserChild> tc = do_QueryReferent(mBrowserChild);
13918 return tc.forget();
13919}
13920
13921nsCommandManager* nsDocShell::GetCommandManager() {
13922 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
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 13922);
return nullptr; } } while (false)
;
13923 return mCommandManager;
13924}
13925
13926NS_IMETHODIMP_(void)void
13927nsDocShell::GetOriginAttributes(mozilla::OriginAttributes& aAttrs) {
13928 mBrowsingContext->GetOriginAttributes(aAttrs);
13929}
13930
13931HTMLEditor* nsIDocShell::GetHTMLEditor() {
13932 nsDocShell* docShell = static_cast<nsDocShell*>(this);
13933 return docShell->GetHTMLEditorInternal();
13934}
13935
13936nsresult nsIDocShell::SetHTMLEditor(HTMLEditor* aHTMLEditor) {
13937 nsDocShell* docShell = static_cast<nsDocShell*>(this);
13938 return docShell->SetHTMLEditorInternal(aHTMLEditor);
13939}
13940
13941#define MATRIX_LENGTH 20
13942
13943NS_IMETHODIMPnsresult
13944nsDocShell::SetColorMatrix(const nsTArray<float>& aMatrix) {
13945 if (aMatrix.Length() == MATRIX_LENGTH) {
13946 mColorMatrix.reset(new gfx::Matrix5x4());
13947 static_assert(
13948 MATRIX_LENGTH * sizeof(float) == sizeof(mColorMatrix->components),
13949 "Size mismatch for our memcpy");
13950 memcpy(mColorMatrix->components, aMatrix.Elements(),
13951 sizeof(mColorMatrix->components));
13952 } else if (aMatrix.Length() == 0) {
13953 mColorMatrix.reset();
13954 } else {
13955 return NS_ERROR_INVALID_ARG;
13956 }
13957
13958 PresShell* presShell = GetPresShell();
13959 if (!presShell) {
13960 return NS_ERROR_FAILURE;
13961 }
13962
13963 nsIFrame* frame = presShell->GetRootFrame();
13964 if (!frame) {
13965 return NS_ERROR_FAILURE;
13966 }
13967
13968 frame->SchedulePaint();
13969
13970 return NS_OK;
13971}
13972
13973NS_IMETHODIMPnsresult
13974nsDocShell::GetColorMatrix(nsTArray<float>& aMatrix) {
13975 if (mColorMatrix) {
13976 aMatrix.SetLength(MATRIX_LENGTH);
13977 static_assert(
13978 MATRIX_LENGTH * sizeof(float) == sizeof(mColorMatrix->components),
13979 "Size mismatch for our memcpy");
13980 memcpy(aMatrix.Elements(), mColorMatrix->components,
13981 MATRIX_LENGTH * sizeof(float));
13982 }
13983
13984 return NS_OK;
13985}
13986
13987#undef MATRIX_LENGTH
13988
13989NS_IMETHODIMPnsresult
13990nsDocShell::GetIsForceReloading(bool* aForceReload) {
13991 *aForceReload = IsForceReloading();
13992 return NS_OK;
13993}
13994
13995bool nsDocShell::IsForceReloading() { return IsForceReloadType(mLoadType); }
13996
13997NS_IMETHODIMPnsresult
13998nsDocShell::GetBrowsingContextXPCOM(BrowsingContext** aBrowsingContext) {
13999 *aBrowsingContext = do_AddRef(mBrowsingContext).take();
14000 return NS_OK;
14001}
14002
14003BrowsingContext* nsDocShell::GetBrowsingContext() { return mBrowsingContext; }
14004
14005bool nsDocShell::GetIsAttemptingToNavigate() {
14006 // XXXbz the document.open spec says to abort even if there's just a
14007 // queued navigation task, sort of. It's not clear whether browsers
14008 // actually do that, and we didn't use to do it, so for now let's
14009 // not do that.
14010 // https://github.com/whatwg/html/issues/3447 tracks the spec side of this.
14011 if (mDocumentRequest) {
14012 // There's definitely a navigation in progress.
14013 return true;
14014 }
14015
14016 // javascript: channels have slightly weird behavior: they're LOAD_BACKGROUND
14017 // until the script runs, which means they're not sending loadgroup
14018 // notifications and hence not getting set as mDocumentRequest. Look through
14019 // our loadgroup for document-level javascript: loads.
14020 if (!mLoadGroup) {
14021 return false;
14022 }
14023
14024 nsCOMPtr<nsISimpleEnumerator> requests;
14025 mLoadGroup->GetRequests(getter_AddRefs(requests));
14026 bool hasMore = false;
14027 while (NS_SUCCEEDED(requests->HasMoreElements(&hasMore))((bool)(__builtin_expect(!!(!NS_FAILED_impl(requests->HasMoreElements
(&hasMore))), 1)))
&& hasMore) {
14028 nsCOMPtr<nsISupports> elem;
14029 requests->GetNext(getter_AddRefs(elem));
14030 nsCOMPtr<nsIScriptChannel> scriptChannel(do_QueryInterface(elem));
14031 if (!scriptChannel) {
14032 continue;
14033 }
14034
14035 if (scriptChannel->GetIsDocumentLoad()) {
14036 // This is a javascript: load that might lead to a new document,
14037 // hence a navigation.
14038 return true;
14039 }
14040 }
14041
14042 return mCheckingSessionHistory;
14043}
14044
14045mozilla::dom::SessionHistoryInfo* nsDocShell::GetActiveSessionHistoryInfo()
14046 const {
14047 return mActiveEntry.get();
14048}
14049
14050void nsDocShell::SetLoadingSessionHistoryInfo(
14051 const mozilla::dom::LoadingSessionHistoryInfo& aLoadingInfo,
14052 bool aNeedToReportActiveAfterLoadingBecomesActive) {
14053 // FIXME Would like to assert this, but can't yet.
14054 // MOZ_ASSERT(!mLoadingEntry);
14055 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)
14056 ("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)
14057 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)
;
14058 mLoadingEntry = MakeUnique<LoadingSessionHistoryInfo>(aLoadingInfo);
14059 mNeedToReportActiveAfterLoadingBecomesActive =
14060 aNeedToReportActiveAfterLoadingBecomesActive;
14061}
14062
14063void nsDocShell::MoveLoadingToActiveEntry(bool aExpired, uint32_t aCacheKey,
14064 nsIURI* aPreviousURI,
14065 nsIPrincipal* aPartitionedPrincipal) {
14066 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()", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 14066); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mozilla::SessionHistoryInParent()"
")"); do { MOZ_CrashSequence(__null, 14066); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
14067
14068 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)
14069 ("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)
;
14070
14071 UniquePtr<SessionHistoryInfo> previousActiveEntry(mActiveEntry.release());
14072 mozilla::UniquePtr<mozilla::dom::LoadingSessionHistoryInfo> loadingEntry;
14073 mActiveEntryIsLoadingFromSessionHistory =
14074 mLoadingEntry && mLoadingEntry->mLoadIsFromSessionHistory;
14075 if (mLoadingEntry) {
14076 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)
14077 ("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)
14078 "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)
14079 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)
;
14080 mLoadingEntry->mInfo.SetPartitionedPrincipalToInherit(
14081 aPartitionedPrincipal);
14082 mActiveEntry = MakeUnique<SessionHistoryInfo>(mLoadingEntry->mInfo);
14083 mLoadingEntry.swap(loadingEntry);
14084 if (!mActiveEntryIsLoadingFromSessionHistory) {
14085 if (mNeedToReportActiveAfterLoadingBecomesActive) {
14086 // Needed to pass various history length WPTs.
14087 mBrowsingContext->SetActiveSessionHistoryEntry(
14088 mozilla::Nothing(), mActiveEntry.get(), previousActiveEntry.get(),
14089 mLoadType,
14090 /* aUpdatedCacheKey = */ 0, false);
14091 }
14092 if (!(previousActiveEntry && previousActiveEntry->IsTransient())) {
14093 mBrowsingContext->IncrementHistoryEntryCountForBrowsingContext();
14094 }
14095 }
14096 }
14097 mNeedToReportActiveAfterLoadingBecomesActive = false;
14098
14099 if (mActiveEntry) {
14100 if (aCacheKey != 0) {
14101 mActiveEntry->SetCacheKey(aCacheKey);
14102 }
14103
14104 mActiveEntry->SetPartitionedPrincipalToInherit(aPartitionedPrincipal);
14105 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", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 14105); AnnotateMozCrashReason("MOZ_ASSERT" "(" "loadingEntry"
")"); do { MOZ_CrashSequence(__null, 14105); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
14106 uint32_t loadType =
14107 mLoadType == LOAD_ERROR_PAGE ? mFailedLoadType : mLoadType;
14108
14109 if (loadingEntry->mLoadId != UINT64_MAX(18446744073709551615UL)) {
14110 // We're passing in mCurrentURI, which could be null. SessionHistoryCommit
14111 // does require a non-null uri if this is for a refresh load of the same
14112 // URI, but in that case mCurrentURI won't be null here.
14113 mBrowsingContext->SessionHistoryCommit(
14114 *loadingEntry, loadType, aPreviousURI, previousActiveEntry.get(),
14115 false, aExpired, aCacheKey, aPartitionedPrincipal);
14116 }
14117
14118 // Only update navigation if the new entry will be persisted (i.e., is not
14119 // an about: page).
14120 if (!loadingEntry->mInfo.IsTransient() && GetWindow() &&
14121 GetWindow()->GetCurrentInnerWindow()) {
14122 if (RefPtr navigation =
14123 GetWindow()->GetCurrentInnerWindow()->Navigation()) {
14124 mBrowsingContext->GetContiguousHistoryEntries(*mActiveEntry,
14125 navigation);
14126 }
14127 }
14128 }
14129}
14130
14131static bool IsFaviconLoad(nsIRequest* aRequest) {
14132 nsCOMPtr<nsIChannel> channel = do_QueryInterface(aRequest);
14133 if (!channel) {
14134 return false;
14135 }
14136
14137 nsCOMPtr<nsILoadInfo> li = channel->LoadInfo();
14138 return li && li->InternalContentPolicyType() ==
14139 nsIContentPolicy::TYPE_INTERNAL_IMAGE_FAVICON;
14140}
14141
14142void nsDocShell::RecordSingleChannelId(bool aStartRequest,
14143 nsIRequest* aRequest) {
14144 // Ignore favicon loads, they don't need to block caching.
14145 if (IsFaviconLoad(aRequest)) {
14146 return;
14147 }
14148
14149 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"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 14149);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "mRequestForBlockingFromBFCacheCount > 0"
")"); do { MOZ_CrashSequence(__null, 14149); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false); } } while
(false)
;
14150
14151 mRequestForBlockingFromBFCacheCount += aStartRequest ? 1 : -1;
14152
14153 if (mBrowsingContext->GetCurrentWindowContext()) {
14154 // We have three states: no request, one request with an id and
14155 // eiher one request without an id or multiple requests. Nothing() is no
14156 // request, Some(non-zero) is one request with an id and Some(0) is one
14157 // request without an id or multiple requests.
14158 Maybe<uint64_t> singleChannelId;
14159 if (mRequestForBlockingFromBFCacheCount > 1) {
14160 singleChannelId = Some(0);
14161 } else if (mRequestForBlockingFromBFCacheCount == 1) {
14162 nsCOMPtr<nsIIdentChannel> identChannel;
14163 if (aStartRequest) {
14164 identChannel = do_QueryInterface(aRequest);
14165 } else {
14166 // aChannel is the channel that's being removed, but we need to check if
14167 // the remaining channel in the loadgroup has an id.
14168 nsCOMPtr<nsISimpleEnumerator> requests;
14169 mLoadGroup->GetRequests(getter_AddRefs(requests));
14170 for (const auto& request : SimpleEnumerator<nsIRequest>(requests)) {
14171 if (!IsFaviconLoad(request) &&
14172 !!(identChannel = do_QueryInterface(request))) {
14173 break;
14174 }
14175 }
14176 }
14177
14178 if (identChannel) {
14179 singleChannelId = Some(identChannel->ChannelId());
14180 } else {
14181 singleChannelId = Some(0);
14182 }
14183 } else {
14184 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"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 14184);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "mRequestForBlockingFromBFCacheCount == 0"
")"); do { MOZ_CrashSequence(__null, 14184); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
14185 singleChannelId = Nothing();
14186 }
14187
14188 if (MOZ_UNLIKELY(MOZ_LOG_TEST(gSHIPBFCacheLog, LogLevel::Verbose))(__builtin_expect(!!((__builtin_expect(!!(mozilla::detail::log_test
(gSHIPBFCacheLog, LogLevel::Verbose)), 0))), 0))
) {
14189 nsAutoCString uri("[no uri]");
14190 if (mCurrentURI) {
14191 uri = mCurrentURI->GetSpecOrDefault();
14192 }
14193 if (singleChannelId.isNothing()) {
14194 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)
14195 ("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)
14196 "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)
14197 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)
;
14198 } else if (singleChannelId.value() == 0) {
14199 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)
14200 ("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)
14201 "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)
14202 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)
;
14203 } else {
14204 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)
14205 ("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)
14206 " 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)
14207 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)
;
14208 }
14209 }
14210
14211 if (mSingleChannelId != singleChannelId) {
14212 mSingleChannelId = singleChannelId;
14213 WindowGlobalChild* wgc =
14214 mBrowsingContext->GetCurrentWindowContext()->GetWindowGlobalChild();
14215 if (wgc) {
14216 wgc->SendSetSingleChannelId(singleChannelId);
14217 }
14218 }
14219 }
14220}
14221
14222NS_IMETHODIMPnsresult
14223nsDocShell::OnStartRequest(nsIRequest* aRequest) {
14224 if (MOZ_UNLIKELY(MOZ_LOG_TEST(gSHIPBFCacheLog, LogLevel::Verbose))(__builtin_expect(!!((__builtin_expect(!!(mozilla::detail::log_test
(gSHIPBFCacheLog, LogLevel::Verbose)), 0))), 0))
) {
14225 nsAutoCString uri("[no uri]");
14226 if (mCurrentURI) {
14227 uri = mCurrentURI->GetSpecOrDefault();
14228 }
14229 nsAutoCString name;
14230 aRequest->GetName(name);
14231 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)
14232 ("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)
;
14233 }
14234 RecordSingleChannelId(true, aRequest);
14235 return nsDocLoader::OnStartRequest(aRequest);
14236}
14237
14238NS_IMETHODIMPnsresult
14239nsDocShell::OnStopRequest(nsIRequest* aRequest, nsresult aStatusCode) {
14240 if (MOZ_UNLIKELY(MOZ_LOG_TEST(gSHIPBFCacheLog, LogLevel::Verbose))(__builtin_expect(!!((__builtin_expect(!!(mozilla::detail::log_test
(gSHIPBFCacheLog, LogLevel::Verbose)), 0))), 0))
) {
14241 nsAutoCString uri("[no uri]");
14242 if (mCurrentURI) {
14243 uri = mCurrentURI->GetSpecOrDefault();
14244 }
14245 nsAutoCString name;
14246 aRequest->GetName(name);
14247 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)
14248 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)
14249 ("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)
;
14250 }
14251 RecordSingleChannelId(false, aRequest);
14252 return nsDocLoader::OnStopRequest(aRequest, aStatusCode);
14253}
14254
14255void nsDocShell::MaybeDisconnectChildListenersOnPageHide() {
14256 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()"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 14256);
AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "XRE_IsContentProcess()"
")"); do { MOZ_CrashSequence(__null, 14256); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
14257
14258 if (mChannelToDisconnectOnPageHide != 0 && mLoadGroup) {
14259 nsCOMPtr<nsISimpleEnumerator> requests;
14260 mLoadGroup->GetRequests(getter_AddRefs(requests));
14261 for (const auto& request : SimpleEnumerator<nsIRequest>(requests)) {
14262 RefPtr<DocumentChannel> channel = do_QueryObject(request);
14263 if (channel && channel->ChannelId() == mChannelToDisconnectOnPageHide) {
14264 static_cast<DocumentChannelChild*>(channel.get())
14265 ->DisconnectChildListeners(NS_BINDING_ABORTED, NS_BINDING_ABORTED);
14266 }
14267 }
14268 mChannelToDisconnectOnPageHide = 0;
14269 }
14270}
14271
14272bool nsDocShell::IsSameDocumentAsActiveEntry(
14273 const mozilla::dom::SessionHistoryInfo& aSHInfo) {
14274 return mActiveEntry ? mActiveEntry->SharesDocumentWith(aSHInfo) : false;
14275}
14276
14277// https://html.spec.whatwg.org/#nav-window
14278nsPIDOMWindowInner* nsDocShell::GetActiveWindow() {
14279 nsPIDOMWindowOuter* outer = GetWindow();
14280 return outer ? outer->GetCurrentInnerWindow() : nullptr;
14281}
14282
14283// https://html.spec.whatwg.org/#inform-the-navigation-api-about-aborting-navigation
14284void nsDocShell::InformNavigationAPIAboutAbortingNavigation() {
14285 // Step 1
14286 // This becomes an assert since we have a common event loop.
14287 MOZ_DIAGNOSTIC_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(NS_IsMainThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 14287);
AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "NS_IsMainThread()"
")"); do { MOZ_CrashSequence(__null, 14287); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
14288
14289 // No ongoing navigations if we don't have a window.
14290 RefPtr<nsPIDOMWindowInner> window = GetActiveWindow();
14291 if (!window) {
14292 return;
14293 }
14294
14295 // Step 2
14296 RefPtr<Navigation> navigation = window->Navigation();
14297 if (!navigation) {
14298 return;
14299 }
14300
14301 // Step 3
14302 if (!navigation->HasOngoingNavigateEvent()) {
14303 return;
14304 }
14305
14306 AutoJSAPI jsapi;
14307 if (!jsapi.Init(navigation->GetOwnerGlobal())) {
14308 return;
14309 }
14310
14311 // Step 4
14312 navigation->AbortOngoingNavigation(jsapi.cx());
14313}
14314
14315// https://html.spec.whatwg.org/#set-the-ongoing-navigation
14316void nsDocShell::SetOngoingNavigation(
14317 const Maybe<OngoingNavigation>& aOngoingNavigation) {
14318 // We currently only use #set-the-ongoing-navigation to call,
14319 // #inform-the-navigation-api-about-aborting-navigation, but really it should
14320 // be used for more. The spec keeps a piece of state on the navigable:
14321 // https://html.spec.whatwg.org/#ongoing-navigation. Spec uses it for several
14322 // things, for example right here in #set-the-ongoing-navigation to make sure
14323 // that we don't call #inform-the-navigation-api-about-aborting-navigation if
14324 // we're setting it to the same value. We currently only care about aborting
14325 // the currently firing navigate event. Also, in reality, this is very much
14326 // related to nsDocShell::GetIsAttemptingToNavigate() which is what we
14327 // currently use to determine if we need to stop an ongoing navigation in
14328 // Document::Open, whereas the spec checks if the ongoing navigation is a
14329 // NavigationID.
14330
14331 // Step 1, with the exception that we assume setting the ongoing navigation to
14332 // an id always means a fresh id.
14333 if (aOngoingNavigation == mOngoingNavigation &&
14334 aOngoingNavigation != Some(OngoingNavigation::NavigationID)) {
14335 return;
14336 }
14337
14338 // Step 2
14339 InformNavigationAPIAboutAbortingNavigation();
14340
14341 // Step 3
14342 mOngoingNavigation = aOngoingNavigation;
14343}