Bug Summary

File:root/firefox-clang/obj-x86_64-pc-linux-gnu/docshell/base/./../../../docshell/base/nsDocShell.cpp
Warning:line 3387, 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 -O2 -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-23/lib/clang/23 -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 -D _GLIBCXX_ASSERTIONS=1 -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/system_wrappers -U _FORTIFY_SOURCE -D _FORTIFY_SOURCE=2 -D DEBUG=1 -D MOZ_HAS_MOZGLUE -D MOZILLA_INTERNAL_API -D IMPL_LIBXUL -D MOZ_SUPPORT_LEAKCHECKING -D STATIC_EXPORTABLE_JS_API -I /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/third_party/abseil-cpp -I /root/firefox-clang/toolkit/components/telemetry -I /root/firefox-clang/xpcom/base -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/16/../../../../include/c++/16 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/16/../../../../include/x86_64-linux-gnu/c++/16 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/16/../../../../include/c++/16/backward -internal-isystem /usr/lib/llvm-23/lib/clang/23/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/16/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -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-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 -Wno-character-conversion -std=gnu++20 -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 -fno-implicit-modules -fskip-odr-check-in-gmf -fno-sized-deallocation -fno-aligned-allocation -fdiagnostics-absolute-paths -vectorize-loops -vectorize-slp -analyzer-checker optin.performance.Padding -analyzer-output=html -analyzer-config stable-report-filename=true -mllvm -dwarf-linkage-names=Abstract -faddrsig -fdwarf2-cfi-asm -o /tmp/scan-build-2026-09-01-224014-2642839-1 -x c++ Unified_cpp_docshell_base0.cpp
1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
5#include "nsDocShell.h"
6
7#include <algorithm>
8#include "mozilla/CycleCollectedJSContext.h"
9#include "mozilla/dom/HTMLFormElement.h"
10
11#ifdef XP_WIN
12# include <process.h>
13# define getpid _getpid
14#else
15# include <unistd.h> // for getpid()
16#endif
17
18#include "nsDeviceContext.h"
19#include "mozilla/Attributes.h"
20#include "mozilla/AutoRestore.h"
21#include "mozilla/BasePrincipal.h"
22#include "mozilla/Casting.h"
23#include "mozilla/CheckedInt.h"
24#include "mozilla/Components.h"
25#include "mozilla/Encoding.h"
26#include "mozilla/EventStateManager.h"
27#include "mozilla/HTMLEditor.h"
28#include "mozilla/InputTaskManager.h"
29#include "mozilla/LoadInfo.h"
30#include "mozilla/Logging.h"
31#include "mozilla/MediaFeatureChange.h"
32#include "mozilla/Preferences.h"
33#include "mozilla/PresShell.h"
34#include "mozilla/SchedulerGroup.h"
35#include "mozilla/ScopeExit.h"
36#include "mozilla/ScrollContainerFrame.h"
37#include "mozilla/ScrollTypes.h"
38#include "mozilla/SimpleEnumerator.h"
39#include "mozilla/StaticPrefs_browser.h"
40#include "mozilla/StaticPrefs_docshell.h"
41#include "mozilla/StaticPrefs_dom.h"
42#include "mozilla/StaticPrefs_extensions.h"
43#include "mozilla/StaticPrefs_network.h"
44#include "mozilla/StaticPrefs_privacy.h"
45#include "mozilla/StaticPrefs_security.h"
46#include "mozilla/StaticPrefs_ui.h"
47#include "mozilla/StaticPrefs_fission.h"
48#include "mozilla/StartupTimeline.h"
49#include "mozilla/StorageAccess.h"
50#include "mozilla/StoragePrincipalHelper.h"
51#include "mozilla/Telemetry.h"
52
53#include "mozilla/WidgetUtils.h"
54
55#include "mozilla/dom/AutoEntryScript.h"
56#include "mozilla/dom/ChildProcessChannelListener.h"
57#include "mozilla/dom/ClientChannelHelper.h"
58#include "mozilla/dom/ClientHandle.h"
59#include "mozilla/dom/ClientInfo.h"
60#include "mozilla/dom/ClientManager.h"
61#include "mozilla/dom/ClientSource.h"
62#include "mozilla/dom/ContentChild.h"
63#include "mozilla/dom/ContentFrameMessageManager.h"
64#include "mozilla/dom/DocGroup.h"
65#include "mozilla/dom/Element.h"
66#include "mozilla/dom/FragmentDirective.h"
67#include "mozilla/dom/HTMLAnchorElement.h"
68#include "mozilla/dom/HTMLIFrameElement.h"
69#include "mozilla/dom/Navigation.h"
70#include "mozilla/dom/NavigationBinding.h"
71#include "mozilla/dom/NavigationHistoryEntry.h"
72#include "mozilla/dom/NavigationUtils.h"
73#include "mozilla/dom/PerformanceNavigation.h"
74#include "mozilla/dom/PermissionMessageUtils.h"
75#include "mozilla/dom/PolicyContainer.h"
76#include "mozilla/dom/PopupBlocker.h"
77#include "mozilla/dom/ScreenOrientation.h"
78#include "mozilla/dom/ScriptSettings.h"
79#include "mozilla/dom/ServiceWorkerInterceptController.h"
80#include "mozilla/dom/ServiceWorkerUtils.h"
81#include "mozilla/dom/SessionHistoryEntry.h"
82#include "mozilla/dom/SessionStorageManager.h"
83#include "mozilla/dom/SessionStoreChangeListener.h"
84#include "mozilla/dom/SessionStoreChild.h"
85#include "mozilla/dom/SessionStoreUtils.h"
86#include "mozilla/dom/TrustedTypeUtils.h"
87#include "mozilla/dom/TrustedTypesConstants.h"
88#include "mozilla/dom/BrowserChild.h"
89#include "mozilla/dom/ToJSValue.h"
90#include "mozilla/dom/UserActivation.h"
91#include "mozilla/dom/ChildSHistory.h"
92#include "mozilla/dom/nsCSPContext.h"
93#include "mozilla/dom/nsHTTPSOnlyUtils.h"
94#include "mozilla/dom/LoadURIOptionsBinding.h"
95#include "mozilla/dom/JSWindowActorChild.h"
96#include "mozilla/dom/DocumentBinding.h"
97#include "mozilla/glean/DocshellMetrics.h"
98#include "mozilla/ipc/ProtocolUtils.h"
99#include "mozilla/net/DocumentChannel.h"
100#include "mozilla/net/DocumentChannelChild.h"
101#include "mozilla/net/ParentChannelWrapper.h"
102#include "mozilla/net/UrlClassifierFeatureFactory.h"
103#include "ReferrerInfo.h"
104
105#include "nsIAuthPrompt.h"
106#include "nsIAuthPrompt2.h"
107#include "nsICachingChannel.h"
108#include "nsICaptivePortalService.h"
109#include "nsIChannel.h"
110#include "nsIChannelEventSink.h"
111#include "nsIClassifiedChannel.h"
112#include "nsIClassOfService.h"
113#include "nsIConsoleReportCollector.h"
114#include "nsIContent.h"
115#include "nsIContentInlines.h"
116#include "nsIContentSecurityPolicy.h"
117#include "nsIController.h"
118#include "nsIDocShellTreeItem.h"
119#include "nsIDocShellTreeOwner.h"
120#include "nsIDocumentViewer.h"
121#include "mozilla/dom/Document.h"
122#include "nsHTMLDocument.h"
123#include "nsIDocumentLoaderFactory.h"
124#include "nsIDOMWindow.h"
125#include "nsIEditingSession.h"
126#include "nsIEffectiveTLDService.h"
127#include "nsExternalHelperAppService.h"
128#include "nsIExternalProtocolService.h"
129#include "nsIFormPOSTActionChannel.h"
130#include "nsIFrame.h"
131#include "nsIGlobalObject.h"
132#include "nsIHttpChannel.h"
133#include "nsIHttpChannelInternal.h"
134#include "nsIIDNService.h"
135#include "nsIInputStreamChannel.h"
136#include "nsIInterfaceRequestorUtils.h"
137#include "nsILayoutHistoryState.h"
138#include "nsILoadInfo.h"
139#include "nsILoadURIDelegate.h"
140#include "nsIMultiPartChannel.h"
141#include "nsINestedURI.h"
142#include "nsINode.h"
143#include "nsINSSErrorsService.h"
144#include "nsIObserverService.h"
145#include "nsIOService.h"
146#include "nsIPrincipal.h"
147#include "nsIPrivacyTransitionObserver.h"
148#include "nsIPrompt.h"
149#include "nsIPromptCollection.h"
150#include "nsIPromptFactory.h"
151#include "nsIPublicKeyPinningService.h"
152#include "nsIReflowObserver.h"
153#include "nsIScriptChannel.h"
154#include "nsIScriptObjectPrincipal.h"
155#include "nsIScriptSecurityManager.h"
156#include "nsScriptSecurityManager.h"
157#include "nsIScrollObserver.h"
158#include "nsISupportsPrimitives.h"
159#include "nsISecureBrowserUI.h"
160#include "nsISeekableStream.h"
161#include "nsISelectionDisplay.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 "nsAboutProtocolUtils.h"
193#include "nsArray.h"
194#include "nsArrayUtils.h"
195#include "nsBrowserStatusFilter.h"
196#include "nsCExternalHandlerService.h"
197#include "nsContentDLF.h"
198#include "nsContentPolicyUtils.h" // NS_CheckContentLoadPolicy(...)
199#include "nsContentSecurityManager.h"
200#include "nsContentSecurityUtils.h"
201#include "nsContentUtils.h"
202#include "nsCURILoader.h"
203#include "nsDocElementCreatedNotificationRunner.h"
204#include "nsDocShellCID.h"
205#include "nsDocShellEditorData.h"
206#include "nsDocShellEnumerator.h"
207#include "nsDocShellLoadState.h"
208#include "nsDocShellLoadTypes.h"
209#include "nsDOMCID.h"
210#include "nsDOMNavigationTiming.h"
211#include "nsDSURIContentListener.h"
212#include "nsEditingSession.h"
213#include "nsError.h"
214#include "nsEscape.h"
215#include "nsFocusManager.h"
216#include "nsGlobalWindowInner.h"
217#include "nsGlobalWindowOuter.h"
218#include "nsJSEnvironment.h"
219#include "nsNetCID.h"
220#include "nsNetUtil.h"
221#include "nsObjectLoadingContent.h"
222#include "nsPIDOMWindowInlines.h"
223#include "nsPingListener.h"
224#include "nsPoint.h"
225#include "nsQueryObject.h"
226#include "nsQueryActor.h"
227#include "nsRect.h"
228#include "nsRefreshTimer.h"
229#include "nsSandboxFlags.h"
230#include "nsSHistory.h"
231#include "nsStructuredCloneContainer.h"
232#include "nsSubDocumentFrame.h"
233#include "nsURILoader.h"
234#include "nsURLHelper.h"
235#include "nsViewSourceHandler.h"
236#include "nsWebBrowserFind.h"
237#include "nsWhitespaceTokenizer.h"
238#include "nsWidgetsCID.h"
239#include "nsXULAppAPI.h"
240
241#include "CertVerifier.h"
242#include "ThirdPartyUtil.h"
243#include "GeckoProfiler.h"
244#include "mozilla/NullPrincipal.h"
245#include "Navigator.h"
246#include "prenv.h"
247#include "mozilla/ipc/URIUtils.h"
248#include "sslerr.h"
249#include "mozpkix/pkix.h"
250#include "NSSErrorsService.h"
251
252#include "nsDocShellTelemetryUtils.h"
253
254#include "nsIOpenWindowInfo.h"
255
256#ifdef MOZ_PLACES1
257# include "mozilla/places/nsFaviconService.h"
258# include "mozIPlacesPendingOperation.h"
259#endif
260
261#ifdef NS_PRINTING1
262# include "nsIDocumentViewerPrint.h"
263# include "nsIWebBrowserPrint.h"
264#endif
265
266using namespace mozilla;
267using namespace mozilla::dom;
268using namespace mozilla::net;
269
270using mozilla::ipc::Endpoint;
271
272// Threshold value in ms for META refresh based redirects
273#define REFRESH_REDIRECT_TIMER15000 15000
274
275static mozilla::LazyLogModule gCharsetMenuLog("CharsetMenu");
276static mozilla::LazyLogModule gDocShellLog("nsDocShell");
277
278#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)
\
279 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)
280
281#ifdef DEBUG1
282unsigned long nsDocShell::gNumberOfDocShells = 0;
283static uint64_t gDocshellIDCounter = 0;
284
285static mozilla::LazyLogModule gDocShellAndDOMWindowLeakLogging(
286 "DocShellAndDOMWindowLeak");
287#endif
288static mozilla::LazyLogModule gDocShellLeakLog("nsDocShellLeak");
289extern mozilla::LazyLogModule gPageCacheLog;
290extern mozilla::LazyLogModule gNavigationAPILog;
291mozilla::LazyLogModule gSHLog("SessionHistory");
292extern mozilla::LazyLogModule gSHIPBFCacheLog;
293
294const char kAppstringsBundleURL[] =
295 "chrome://global/locale/appstrings.properties";
296
297static bool IsTopLevelDoc(BrowsingContext* aBrowsingContext,
298 nsILoadInfo* aLoadInfo) {
299 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"
, "./../../../docshell/base/nsDocShell.cpp", 299); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aBrowsingContext" ")"); do { MOZ_CrashSequence
(__null, 299); __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
300 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", "./../../../docshell/base/nsDocShell.cpp"
, 300); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadInfo" ")"
); do { MOZ_CrashSequence(__null, 300); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
301
302 if (aLoadInfo->GetExternalContentPolicyType() !=
303 ExtContentPolicy::TYPE_DOCUMENT) {
304 return false;
305 }
306
307 return aBrowsingContext->IsTopContent();
308}
309
310// True if loading for top level document loading in active tab.
311static bool IsUrgentStart(BrowsingContext* aBrowsingContext,
312 nsILoadInfo* aLoadInfo, uint32_t aLoadType) {
313 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"
, "./../../../docshell/base/nsDocShell.cpp", 313); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aBrowsingContext" ")"); do { MOZ_CrashSequence
(__null, 313); __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
314 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", "./../../../docshell/base/nsDocShell.cpp"
, 314); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadInfo" ")"
); do { MOZ_CrashSequence(__null, 314); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
315
316 if (!IsTopLevelDoc(aBrowsingContext, aLoadInfo)) {
317 return false;
318 }
319
320 if (aLoadType &
321 (nsIDocShell::LOAD_CMD_NORMAL | nsIDocShell::LOAD_CMD_HISTORY)) {
322 return true;
323 }
324
325 return aBrowsingContext->IsActive();
326}
327
328nsDocShell::nsDocShell(BrowsingContext* aBrowsingContext,
329 uint64_t aContentWindowID)
330 : nsDocLoader(true),
331 mContentWindowID(aContentWindowID),
332 mBrowsingContext(aBrowsingContext),
333 mParentCharset(nullptr),
334 mTreeOwner(nullptr),
335 mScrollbarPref(ScrollbarPreference::Auto),
336 mCharsetReloadState(eCharsetReloadInit),
337 mParentCharsetSource(0),
338 mFrameMargins(-1, -1),
339 mItemType(aBrowsingContext->IsContent() ? typeContent : typeChrome),
340 mPreviousEntryIndex(-1),
341 mLoadedEntryIndex(-1),
342 mBusyFlags(BUSY_FLAGS_NONE),
343 mAppType(nsIDocShell::APP_TYPE_UNKNOWN),
344 mLoadType(0),
345 mFailedLoadType(0),
346 mChannelToDisconnectOnPageHide(0),
347 mCreatingDocument(false),
348#ifdef DEBUG1
349 mInEnsureScriptEnv(false),
350#endif
351 mInitialized(false),
352 mAllowSubframes(true),
353 mAllowMetaRedirects(true),
354 mAllowImages(true),
355 mAllowMedia(true),
356 mAllowDNSPrefetch(true),
357 mAllowWindowControl(true),
358 mCSSErrorReportingEnabled(false),
359 mAllowAuth(mItemType == typeContent),
360 mAllowKeywordFixup(false),
361 mDisableMetaRefreshWhenInactive(false),
362 mWindowDraggingAllowed(false),
363 mInFrameSwap(false),
364 mFiredUnloadEvent(false),
365 mEODForCurrentDocument(false),
366 mURIResultedInDocument(false),
367 mIsBeingDestroyed(false),
368 mIsExecutingOnLoadHandler(false),
369 mInvisible(false),
370 mHasLoadedNonBlankURI(false),
371 mHasStartedLoadingOtherThanInitialBlankURI(false),
372 mBlankTiming(false),
373 mTitleValidForCurrentURI(false),
374 mWillChangeProcess(false),
375 mIsNavigating(false),
376 mForcedAutodetection(false),
377 mCheckingSessionHistory(false),
378 mNeedToReportActiveAfterLoadingBecomesActive(false) {
379 // If no outer window ID was provided, generate a new one.
380 if (aContentWindowID == 0) {
381 mContentWindowID = nsContentUtils::GenerateWindowId();
382 }
383
384 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)
;
385
386#ifdef DEBUG1
387 mDocShellID = gDocshellIDCounter++;
388 // We're counting the number of |nsDocShells| to help find leaks
389 ++gNumberOfDocShells;
390 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)
391 ("++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)
392 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)
;
393#endif
394}
395
396void nsDocShell::DestroyDocumentViewer() {
397 if (!mDocumentViewer) {
398 return;
399 }
400 mDocumentViewer->Close();
401 mDocumentViewer->Destroy();
402 mDocumentViewer = nullptr;
403}
404
405nsDocShell::~nsDocShell() {
406 // Avoid notifying observers while we're in the dtor.
407 mIsBeingDestroyed = true;
408
409 Destroy();
410
411 DestroyDocumentViewer();
412
413 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)
;
414
415#ifdef DEBUG1
416 if (MOZ_LOG_TEST(gDocShellAndDOMWindowLeakLogging, LogLevel::Info)(__builtin_expect(!!(mozilla::detail::log_test(gDocShellAndDOMWindowLeakLogging
, LogLevel::Info)), 0))
) {
417 nsAutoCString url;
418 if (mLastOpenedURI) {
419 url = mLastOpenedURI->GetSpecOrDefault();
420
421 // Data URLs can be very long, so truncate to avoid flooding the log.
422 const uint32_t maxURLLength = 1000;
423 if (url.Length() > maxURLLength) {
424 url.Truncate(maxURLLength);
425 }
426 }
427
428 // We're counting the number of |nsDocShells| to help find leaks
429 --gNumberOfDocShells;
430 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)
431 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)
432 ("--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)
433 (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)
;
434 }
435#endif
436}
437
438nsresult nsDocShell::InitWindow(nsIWidget* aParentWidget, int32_t aX,
439 int32_t aY, int32_t aWidth, int32_t aHeight,
440 nsIOpenWindowInfo* aOpenWindowInfo,
441 mozilla::dom::WindowGlobalChild* aWindowActor) {
442 SetParentWidget(aParentWidget);
443 SetPositionAndSize(aX, aY, aWidth, aHeight, 0);
444 return Initialize(aOpenWindowInfo, aWindowActor);
445}
446
447nsresult nsDocShell::Initialize(nsIOpenWindowInfo* aOpenWindowInfo,
448 mozilla::dom::WindowGlobalChild* aWindowActor) {
449 if (mInitialized) {
450 // We've already been initialized.
451 MOZ_ASSERT(!aOpenWindowInfo,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aOpenWindowInfo)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!aOpenWindowInfo))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("!aOpenWindowInfo"
" (" "Tried to reinitialize with override principal" ")", "./../../../docshell/base/nsDocShell.cpp"
, 452); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aOpenWindowInfo"
") (" "Tried to reinitialize with override principal" ")"); do
{ MOZ_CrashSequence(__null, 452); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
452 "Tried to reinitialize with override principal")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aOpenWindowInfo)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!aOpenWindowInfo))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("!aOpenWindowInfo"
" (" "Tried to reinitialize with override principal" ")", "./../../../docshell/base/nsDocShell.cpp"
, 452); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aOpenWindowInfo"
") (" "Tried to reinitialize with override principal" ")"); do
{ MOZ_CrashSequence(__null, 452); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
453 MOZ_ASSERT(!aWindowActor, "Tried to reinitialize with a window actor")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aWindowActor)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!aWindowActor))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("!aWindowActor" " ("
"Tried to reinitialize with a window actor" ")", "./../../../docshell/base/nsDocShell.cpp"
, 453); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aWindowActor"
") (" "Tried to reinitialize with a window actor" ")"); do {
MOZ_CrashSequence(__null, 453); __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
;
454 return NS_OK;
455 }
456
457 MOZ_ASSERT(aOpenWindowInfo,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aOpenWindowInfo)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aOpenWindowInfo))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("aOpenWindowInfo"
" (" "Must have openwindowinfo if not already initialized." ")"
, "./../../../docshell/base/nsDocShell.cpp", 458); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aOpenWindowInfo" ") (" "Must have openwindowinfo if not already initialized."
")"); do { MOZ_CrashSequence(__null, 458); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
458 "Must have openwindowinfo if not already initialized.")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aOpenWindowInfo)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aOpenWindowInfo))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("aOpenWindowInfo"
" (" "Must have openwindowinfo if not already initialized." ")"
, "./../../../docshell/base/nsDocShell.cpp", 458); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aOpenWindowInfo" ") (" "Must have openwindowinfo if not already initialized."
")"); do { MOZ_CrashSequence(__null, 458); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
459
460 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", "./../../../docshell/base/nsDocShell.cpp"
, 461); MOZ_PretendNoReturn(); } } while (0)
461 "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", "./../../../docshell/base/nsDocShell.cpp"
, 461); MOZ_PretendNoReturn(); } } while (0)
;
462
463 NS_ENSURE_TRUE(Preferences::GetRootBranch(), NS_ERROR_NOT_INITIALIZED)do { if ((__builtin_expect(!!(!(Preferences::GetRootBranch())
), 0))) { NS_DebugBreak(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "Preferences::GetRootBranch()"
") failed", nullptr, "./../../../docshell/base/nsDocShell.cpp"
, 463); return NS_ERROR_NOT_INITIALIZED; } } while (false)
;
464 mInitialized = true;
465
466 mDisableMetaRefreshWhenInactive =
467 Preferences::GetBool("browser.meta_refresh_when_inactive.disabled",
468 mDisableMetaRefreshWhenInactive);
469
470 nsresult rv = CreateInitialDocumentViewer(aOpenWindowInfo, aWindowActor);
471
472 if (nsCOMPtr<nsIObserverService> serv = services::GetObserverService()) {
473 const char* msg = mItemType == typeContent ? NS_WEBNAVIGATION_CREATE"webnavigation-create"
474 : NS_CHROME_WEBNAVIGATION_CREATE"chrome-webnavigation-create";
475 serv->NotifyWhenScriptSafe(GetAsSupports(this), msg, nullptr);
476 }
477
478 return rv;
479}
480
481/* static */
482already_AddRefed<nsDocShell> nsDocShell::Create(
483 BrowsingContext* aBrowsingContext, uint64_t aContentWindowID) {
484 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!" ")", "./../../../docshell/base/nsDocShell.cpp"
, 484); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aBrowsingContext"
") (" "DocShell without a BrowsingContext!" ")"); do { MOZ_CrashSequence
(__null, 484); __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
485
486 nsresult rv;
487 RefPtr<nsDocShell> ds = new nsDocShell(aBrowsingContext, aContentWindowID);
488
489 // Initialize the underlying nsDocLoader.
490 rv = ds->nsDocLoader::InitWithBrowsingContext(aBrowsingContext);
491 if (NS_WARN_IF(NS_FAILED(rv))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(rv
)), 0))), "NS_FAILED(rv)", "./../../../docshell/base/nsDocShell.cpp"
, 491)
) {
492 return nullptr;
493 }
494
495 // Create our ContentListener
496 ds->mContentListener = new nsDSURIContentListener(ds);
497
498 // We enable if we're in the parent process in order to support non-e10s
499 // configurations.
500 // Note: This check is duplicated in SharedWorkerInterfaceRequestor's
501 // constructor.
502 if (XRE_IsParentProcess()) {
503 ds->mInterceptController = MakeRefPtr<ServiceWorkerInterceptController>();
504 }
505
506 // We want to hold a strong ref to the loadgroup, so it better hold a weak
507 // ref to us... use an InterfaceRequestorProxy to do this.
508 RefPtr proxy = MakeRefPtr<InterfaceRequestorProxy>(ds);
509 ds->mLoadGroup->SetNotificationCallbacks(proxy);
510
511 // XXX(nika): We have our BrowsingContext, so we might be able to skip this.
512 // It could be nice to directly set up our DocLoader tree?
513 rv = nsDocLoader::AddDocLoaderAsChildOfRoot(ds);
514 if (NS_WARN_IF(NS_FAILED(rv))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(rv
)), 0))), "NS_FAILED(rv)", "./../../../docshell/base/nsDocShell.cpp"
, 514)
) {
515 return nullptr;
516 }
517
518 uint32_t notifyMask =
519 nsIWebProgress::NOTIFY_STATE_ALL | nsIWebProgress::NOTIFY_LOCATION |
520 nsIWebProgress::NOTIFY_SECURITY | nsIWebProgress::NOTIFY_STATUS;
521
522 // NOTE: Only listen for NOTIFY_PROGRESS on toplevel BrowsingContexts, as
523 // listeners in the browser UI only cares about total progress on the toplevel
524 // context. Aggregation of the total progress is currently handled within
525 // `nsDocLoader`, and does not take out-of-process iframes into account.
526 if (aBrowsingContext->IsTop()) {
527 notifyMask |= nsIWebProgress::NOTIFY_PROGRESS;
528 }
529
530 // Add |ds| as a progress listener to itself. A little weird, but simpler
531 // than reproducing all the listener-notification logic in overrides of the
532 // various methods via which nsDocLoader can be notified. Note that this
533 // holds an nsWeakPtr to |ds|, so it's ok.
534 rv = ds->AddProgressListener(ds, notifyMask);
535 if (NS_WARN_IF(NS_FAILED(rv))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(rv
)), 0))), "NS_FAILED(rv)", "./../../../docshell/base/nsDocShell.cpp"
, 535)
) {
536 return nullptr;
537 }
538
539 // If our BrowsingContext has private browsing enabled, update the number of
540 // private browsing docshells.
541 if (aBrowsingContext->UsePrivateBrowsing()) {
542 ds->NotifyPrivateBrowsingChanged();
543 }
544
545 // If our parent window is present in this process, set up our parent now.
546 RefPtr<WindowContext> parentWC = aBrowsingContext->GetParentWindowContext();
547 if (parentWC && parentWC->IsInProcess()) {
548 // If we don't have a parent element anymore, we can't finish this load!
549 // How'd we get here?
550 RefPtr<Element> parentElement = aBrowsingContext->GetEmbedderElement();
551 if (!parentElement) {
552 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" ")", "./../../../docshell/base/nsDocShell.cpp"
, 552); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "nsDocShell::Create() - !parentElement"
")"); do { MOZ_CrashSequence(__null, 552); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
553 return nullptr;
554 }
555
556 // We have an in-process parent window, but don't have a parent nsDocShell?
557 // How'd we get here!
558 nsCOMPtr<nsIDocShell> parentShell =
559 parentElement->OwnerDoc()->GetDocShell();
560 if (!parentShell) {
561 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" ")", "./../../../docshell/base/nsDocShell.cpp"
, 561); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "nsDocShell::Create() - !parentShell"
")"); do { MOZ_CrashSequence(__null, 561); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
562 return nullptr;
563 }
564 parentShell->AddChild(ds);
565 }
566
567 // Make |ds| the primary DocShell for the given context.
568 aBrowsingContext->SetDocShell(ds);
569
570 // Set |ds| default load flags on load group.
571 ds->SetLoadGroupDefaultLoadFlags(aBrowsingContext->GetDefaultLoadFlags());
572
573 return ds.forget();
574}
575
576void nsDocShell::DestroyChildren() {
577 for (auto* child : mChildList.ForwardRange()) {
578 nsCOMPtr<nsIDocShellTreeItem> shell = do_QueryObject(child);
579 NS_ASSERTION(shell, "docshell has null child")do { if (!(shell)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "docshell has null child"
, "shell", "./../../../docshell/base/nsDocShell.cpp", 579); MOZ_PretendNoReturn
(); } } while (0)
;
580
581 if (shell) {
582 shell->SetTreeOwner(nullptr);
583 }
584 }
585
586 nsDocLoader::DestroyChildren();
587}
588
589NS_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; }
590 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; }
591 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; }
592 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; }
593 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; }
594
595NS_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; }
596NS_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; }
597
598NS_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", "./../../../docshell/base/nsDocShell.cpp", 598
); 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
599 NS_INTERFACE_MAP_ENTRY(nsIDocShell)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIDocShell>)) foundInterface = static_cast
<nsIDocShell*>(this); else
600 NS_INTERFACE_MAP_ENTRY(nsIDocShellTreeItem)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIDocShellTreeItem>)) foundInterface
= static_cast<nsIDocShellTreeItem*>(this); else
601 NS_INTERFACE_MAP_ENTRY(nsIWebNavigation)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIWebNavigation>)) foundInterface
= static_cast<nsIWebNavigation*>(this); else
602 NS_INTERFACE_MAP_ENTRY(nsIBaseWindow)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIBaseWindow>)) foundInterface =
static_cast<nsIBaseWindow*>(this); else
603 NS_INTERFACE_MAP_ENTRY(nsIRefreshURI)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIRefreshURI>)) foundInterface =
static_cast<nsIRefreshURI*>(this); else
604 NS_INTERFACE_MAP_ENTRY(nsIWebProgressListener)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIWebProgressListener>)) foundInterface
= static_cast<nsIWebProgressListener*>(this); else
605 NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsISupportsWeakReference>)) foundInterface
= static_cast<nsISupportsWeakReference*>(this); else
606 NS_INTERFACE_MAP_ENTRY(nsIWebPageDescriptor)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIWebPageDescriptor>)) foundInterface
= static_cast<nsIWebPageDescriptor*>(this); else
607 NS_INTERFACE_MAP_ENTRY(nsIAuthPromptProvider)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIAuthPromptProvider>)) foundInterface
= static_cast<nsIAuthPromptProvider*>(this); else
608 NS_INTERFACE_MAP_ENTRY(nsILoadContext)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsILoadContext>)) foundInterface =
static_cast<nsILoadContext*>(this); else
609 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
610 mInterceptController)if ((mInterceptController) && aIID.Equals(mozilla::detail
::kImplementedIID<std::remove_reference_t<decltype(*this
)>, nsINetworkInterceptController>)) foundInterface = static_cast
<nsINetworkInterceptController*>(this); else
611NS_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; }
612
613NS_IMETHODIMPnsresult
614nsDocShell::GetInterface(const nsIID& aIID, void** aSink) {
615 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"
")", "./../../../docshell/base/nsDocShell.cpp", 615); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aSink" ") (" "null out param" ")"); do { MOZ_CrashSequence
(__null, 615); __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
616
617 *aSink = nullptr;
618
619 if (aIID.Equals(NS_GET_IID(nsICommandManager)(nsICommandManager::kIID))) {
620 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
, "./../../../docshell/base/nsDocShell.cpp", 620); return NS_ERROR_FAILURE
; } } while (false)
;
621 *aSink = static_cast<nsICommandManager*>(mCommandManager.get());
622 } else if (aIID.Equals(NS_GET_IID(nsIURIContentListener)(nsIURIContentListener::kIID))) {
623 *aSink = mContentListener;
624 } else if ((aIID.Equals(NS_GET_IID(nsIScriptGlobalObject)(nsIScriptGlobalObject::kIID)) ||
625 aIID.Equals(NS_GET_IID(nsIGlobalObject)(nsIGlobalObject::kIID)) ||
626 aIID.Equals(NS_GET_IID(nsPIDOMWindowOuter)(nsPIDOMWindowOuter::kIID)) ||
627 aIID.Equals(NS_GET_IID(mozIDOMWindowProxy)(mozIDOMWindowProxy::kIID)) ||
628 aIID.Equals(NS_GET_IID(nsIDOMWindow)(nsIDOMWindow::kIID))) &&
629 NS_SUCCEEDED(EnsureScriptEnvironment())((bool)(__builtin_expect(!!(!NS_FAILED_impl(EnsureScriptEnvironment
())), 1)))
) {
630 return mScriptGlobal->QueryInterface(aIID, aSink);
631 } else if (aIID.Equals(NS_GET_IID(Document)(Document::kIID)) && VerifyDocumentViewer()) {
632 RefPtr<Document> doc = mDocumentViewer->GetDocument();
633 doc.forget(aSink);
634 return *aSink ? NS_OK : NS_NOINTERFACE;
635 } else if (aIID.Equals(NS_GET_IID(nsIPrompt)(nsIPrompt::kIID)) &&
636 NS_SUCCEEDED(EnsureScriptEnvironment())((bool)(__builtin_expect(!!(!NS_FAILED_impl(EnsureScriptEnvironment
())), 1)))
) {
637 nsresult rv;
638 nsCOMPtr<nsIWindowWatcher> wwatch =
639 do_GetService(NS_WINDOWWATCHER_CONTRACTID"@mozilla.org/embedcomp/window-watcher;1", &rv);
640 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, "./../../../docshell/base/nsDocShell.cpp"
, 640); return rv; } } while (false)
;
641
642 // Get the an auth prompter for our window so that the parenting
643 // of the dialogs works as it should when using tabs.
644 nsIPrompt* prompt;
645 rv = wwatch->GetNewPrompter(mScriptGlobal, &prompt);
646 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, "./../../../docshell/base/nsDocShell.cpp"
, 646); return rv; } } while (false)
;
647
648 *aSink = prompt;
649 return NS_OK;
650 } else if (aIID.Equals(NS_GET_IID(nsIAuthPrompt)(nsIAuthPrompt::kIID)) ||
651 aIID.Equals(NS_GET_IID(nsIAuthPrompt2)(nsIAuthPrompt2::kIID))) {
652 return NS_SUCCEEDED(GetAuthPrompt(PROMPT_NORMAL, aIID, aSink))((bool)(__builtin_expect(!!(!NS_FAILED_impl(GetAuthPrompt(PROMPT_NORMAL
, aIID, aSink))), 1)))
653 ? NS_OK
654 : NS_NOINTERFACE;
655 } else if (aIID.Equals(NS_GET_IID(nsISHistory)(nsISHistory::kIID))) {
656 // This is deprecated, you should instead directly get
657 // ChildSHistory from the browsing context.
658 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"
")", "./../../../docshell/base/nsDocShell.cpp", 659); AnnotateMozCrashReason
("MOZ_DIAGNOSTIC_ASSERT" "(" "false" ") (" "Do not try to get a nsISHistory interface from nsIDocShell"
")"); do { MOZ_CrashSequence(__null, 659); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
659 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"
")", "./../../../docshell/base/nsDocShell.cpp", 659); AnnotateMozCrashReason
("MOZ_DIAGNOSTIC_ASSERT" "(" "false" ") (" "Do not try to get a nsISHistory interface from nsIDocShell"
")"); do { MOZ_CrashSequence(__null, 659); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
660 return NS_NOINTERFACE;
661 } else if (aIID.Equals(NS_GET_IID(nsIWebBrowserFind)(nsIWebBrowserFind::kIID))) {
662 nsresult rv = EnsureFind();
663 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
664 return rv;
665 }
666
667 *aSink = mFind;
668 NS_ADDREF((nsISupports*)*aSink)((nsISupports*)*aSink)->AddRef();
669 return NS_OK;
670 } else if (aIID.Equals(NS_GET_IID(nsISelectionDisplay)(nsISelectionDisplay::kIID))) {
671 if (PresShell* presShell = GetPresShell()) {
672 return presShell->QueryInterface(aIID, aSink);
673 }
674 } else if (aIID.Equals(NS_GET_IID(nsIDocShellTreeOwner)(nsIDocShellTreeOwner::kIID))) {
675 nsCOMPtr<nsIDocShellTreeOwner> treeOwner;
676 nsresult rv = GetTreeOwner(getter_AddRefs(treeOwner));
677 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && treeOwner) {
678 return treeOwner->QueryInterface(aIID, aSink);
679 }
680 } else if (aIID.Equals(NS_GET_IID(nsIBrowserChild)(nsIBrowserChild::kIID))) {
681 *aSink = GetBrowserChild().take();
682 return *aSink ? NS_OK : NS_ERROR_FAILURE;
683 } else {
684 return nsDocLoader::GetInterface(aIID, aSink);
685 }
686
687 NS_IF_ADDREF(((nsISupports*)*aSink))ns_if_addref(((nsISupports*)*aSink));
688 return *aSink ? NS_OK : NS_NOINTERFACE;
689}
690
691NS_IMETHODIMPnsresult
692nsDocShell::SetCancelContentJSEpoch(int32_t aEpoch) {
693 // Note: this gets called fairly early (before a pageload actually starts).
694 // We could probably defer this even longer.
695 nsCOMPtr<nsIBrowserChild> browserChild = GetBrowserChild();
696 static_cast<BrowserChild*>(browserChild.get())
697 ->SetCancelContentJSEpoch(aEpoch);
698 return NS_OK;
699}
700
701nsresult nsDocShell::CheckDisallowedJavascriptLoad(
702 nsDocShellLoadState* aLoadState) {
703 if (!aLoadState->URI()->SchemeIs("javascript")) {
704 return NS_OK;
705 }
706
707 if (nsCOMPtr<nsIPrincipal> targetPrincipal =
708 GetInheritedPrincipal(/* aConsiderCurrentDocument */ true)) {
709 if (!aLoadState->TriggeringPrincipal()->Subsumes(targetPrincipal)) {
710 return NS_ERROR_DOM_BAD_CROSS_ORIGIN_URI;
711 }
712 return NS_OK;
713 }
714 return NS_ERROR_DOM_BAD_CROSS_ORIGIN_URI;
715}
716
717NS_IMETHODIMPnsresult
718nsDocShell::LoadURI(nsDocShellLoadState* aLoadState, bool aSetNavigating) {
719 return LoadURI(aLoadState, aSetNavigating, false);
720}
721
722nsresult nsDocShell::LoadURI(nsDocShellLoadState* aLoadState,
723 bool aSetNavigating,
724 bool aContinueHandlingSubframeHistory) {
725 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!"
")", "./../../../docshell/base/nsDocShell.cpp", 725); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aLoadState" ") (" "Must have a valid load state!"
")"); do { MOZ_CrashSequence(__null, 725); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
726 // NOTE: This comparison between what appears to be internal/external load
727 // flags is intentional, as it's ensuring that the caller isn't using any of
728 // the flags reserved for implementations by the `nsIWebNavigation` interface.
729 // In the future, this check may be dropped.
730 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" ")", "./../../../docshell/base/nsDocShell.cpp"
, 732); AnnotateMozCrashReason("MOZ_ASSERT" "(" "(aLoadState->LoadFlags() & INTERNAL_LOAD_FLAGS_LOADURI_SETUP_FLAGS) == 0"
") (" "Should not have these flags set" ")"); do { MOZ_CrashSequence
(__null, 732); __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
731 (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" ")", "./../../../docshell/base/nsDocShell.cpp"
, 732); AnnotateMozCrashReason("MOZ_ASSERT" "(" "(aLoadState->LoadFlags() & INTERNAL_LOAD_FLAGS_LOADURI_SETUP_FLAGS) == 0"
") (" "Should not have these flags set" ")"); do { MOZ_CrashSequence
(__null, 732); __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
732 "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" ")", "./../../../docshell/base/nsDocShell.cpp"
, 732); AnnotateMozCrashReason("MOZ_ASSERT" "(" "(aLoadState->LoadFlags() & INTERNAL_LOAD_FLAGS_LOADURI_SETUP_FLAGS) == 0"
") (" "Should not have these flags set" ")"); do { MOZ_CrashSequence
(__null, 732); __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
733 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" ")", "./../../../docshell/base/nsDocShell.cpp"
, 734); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->TargetBrowsingContext().IsNull()"
") (" "Targeting doesn't occur until InternalLoad" ")"); do {
MOZ_CrashSequence(__null, 734); __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
734 "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" ")", "./../../../docshell/base/nsDocShell.cpp"
, 734); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->TargetBrowsingContext().IsNull()"
") (" "Targeting doesn't occur until InternalLoad" ")"); do {
MOZ_CrashSequence(__null, 734); __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
;
735
736 if (!aLoadState->TriggeringPrincipal()) {
737 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"
")", "./../../../docshell/base/nsDocShell.cpp", 737); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "false" ") (" "LoadURI must have a triggering principal"
")"); do { MOZ_CrashSequence(__null, 737); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
738 return NS_ERROR_FAILURE;
739 }
740
741 MOZ_TRY(CheckDisallowedJavascriptLoad(aLoadState))__extension__({ auto mozTryVarTempResult = ::mozilla::ToResult
(CheckDisallowedJavascriptLoad(aLoadState)); if ((__builtin_expect
(!!(mozTryVarTempResult.isErr()), 0))) { return mozTryVarTempResult
.propagateErr(); } mozTryVarTempResult.unwrap(); })
;
742
743 bool oldIsNavigating = mIsNavigating;
744 auto cleanupIsNavigating =
745 MakeScopeExit([&]() { mIsNavigating = oldIsNavigating; });
746 if (aSetNavigating) {
747 mIsNavigating = true;
748 }
749
750 PopupBlocker::PopupControlState popupState = PopupBlocker::openOverridden;
751 if (aLoadState->HasLoadFlags(LOAD_FLAGS_ALLOW_POPUPS)) {
752 popupState = PopupBlocker::openAllowed;
753 // If we allow popups as part of the navigation, ensure we fake a user
754 // interaction, so that popups can, in fact, be allowed to open.
755 if (WindowContext* wc = mBrowsingContext->GetCurrentWindowContext()) {
756 wc->NotifyUserGestureActivation();
757 }
758 }
759
760 AutoPopupStatePusherAutoPopupStatePusherInternal statePusher(popupState);
761
762 if (aLoadState->GetCancelContentJSEpoch().isSome()) {
763 SetCancelContentJSEpoch(*aLoadState->GetCancelContentJSEpoch());
764 }
765
766 // Note: we allow loads to get through here even if mFiredUnloadEvent is
767 // true; that case will get handled in LoadInternal or LoadHistoryEntry,
768 // so we pass false as the second parameter to IsNavigationAllowed.
769 // However, we don't allow the page to change location *in the middle of*
770 // firing beforeunload, so we do need to check if *beforeunload* is currently
771 // firing, so we call IsNavigationAllowed rather than just IsPrintingOrPP.
772 if (!IsNavigationAllowed(true, false)) {
773 return NS_OK; // JS may not handle returning of an error code
774 }
775
776 nsLoadFlags defaultLoadFlags = mBrowsingContext->GetDefaultLoadFlags();
777 if (aLoadState->HasLoadFlags(LOAD_FLAGS_FORCE_TRR)) {
778 defaultLoadFlags |= nsIRequest::LOAD_TRR_ONLY_MODE;
779 } else if (aLoadState->HasLoadFlags(LOAD_FLAGS_DISABLE_TRR)) {
780 defaultLoadFlags |= nsIRequest::LOAD_TRR_DISABLED_MODE;
781 }
782
783 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))"
, "./../../../docshell/base/nsDocShell.cpp", 783); AnnotateMozCrashReason
("MOZ_CRASH(" "NS_SUCCEEDED(mBrowsingContext->SetDefaultLoadFlags(defaultLoadFlags))"
")"); do { MOZ_CrashSequence(__null, 783); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
;
784
785 if (!StartupTimeline::HasRecord(StartupTimeline::FIRST_LOAD_URI) &&
786 mItemType == typeContent && !NS_IsAboutBlank(aLoadState->URI())) {
787 StartupTimeline::RecordOnce(StartupTimeline::FIRST_LOAD_URI);
788 }
789
790 // LoadType used to be set to a default value here, if no LoadInfo/LoadState
791 // object was passed in. That functionality has been removed as of bug
792 // 1492648. LoadType should now be set up by the caller at the time they
793 // create their nsDocShellLoadState object to pass into LoadURI.
794
795 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)
796 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)
797 ("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)
798 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)
;
799
800 if ((!aLoadState->LoadIsFromSessionHistory() &&
801 !LOAD_TYPE_HAS_FLAGS(aLoadState->LoadType(),((aLoadState->LoadType()) & ((LOAD_FLAGS_REPLACE_HISTORY
) << 16))
802 LOAD_FLAGS_REPLACE_HISTORY)((aLoadState->LoadType()) & ((LOAD_FLAGS_REPLACE_HISTORY
) << 16))
) ||
803 aContinueHandlingSubframeHistory) {
804 // This is possibly a subframe, so handle it accordingly.
805 //
806 // If history exists, it will be loaded into the aLoadState object, and the
807 // LoadType will be changed.
808 if (MaybeHandleSubframeHistory(aLoadState,
809 aContinueHandlingSubframeHistory)) {
810 // MaybeHandleSubframeHistory returns true if we need to continue loading
811 // asynchronously.
812 return NS_OK;
813 }
814 }
815
816 if (aLoadState->LoadIsFromSessionHistory()) {
817 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)
818 ("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)
;
819
820 // FIXME Null check aLoadState->GetLoadingSessionHistoryInfo()?
821 return LoadHistoryEntry(*aLoadState->GetLoadingSessionHistoryInfo(),
822 aLoadState->LoadType(),
823 aLoadState->HasValidUserGestureActivation(),
824 aLoadState->NotifiedBeforeUnloadListeners(),
825 aLoadState->IsResumingInterceptedNavigation());
826 }
827
828 // On history navigation via Back/Forward buttons, don't execute
829 // automatic JavaScript redirection such as |location.href = ...| or
830 // |window.open()|
831 //
832 // LOAD_NORMAL: window.open(...) etc.
833 // LOAD_STOP_CONTENT: location.href = ..., location.assign(...)
834 if ((aLoadState->LoadType() == LOAD_NORMAL ||
835 aLoadState->LoadType() == LOAD_STOP_CONTENT) &&
836 ShouldBlockLoadingForBackButton()) {
837 return NS_OK;
838 }
839
840 BrowsingContext::Type bcType = mBrowsingContext->GetType();
841
842 // Set up the inheriting principal in LoadState.
843 nsresult rv = aLoadState->SetupInheritingPrincipal(
844 bcType, mBrowsingContext->OriginAttributesRef());
845 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, "./../../../docshell/base/nsDocShell.cpp"
, 845); return rv; } } while (false)
;
846
847 rv = aLoadState->SetupTriggeringPrincipal(
848 mBrowsingContext->OriginAttributesRef());
849 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, "./../../../docshell/base/nsDocShell.cpp"
, 849); return rv; } } while (false)
;
850
851 aLoadState->CalculateLoadURIFlags();
852
853 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"
")", "./../../../docshell/base/nsDocShell.cpp", 854); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aLoadState->TypeHint().IsVoid()" ") (" "Typehint should be null when calling InternalLoad from LoadURI"
")"); do { MOZ_CrashSequence(__null, 854); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
854 "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"
")", "./../../../docshell/base/nsDocShell.cpp", 854); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aLoadState->TypeHint().IsVoid()" ") (" "Typehint should be null when calling InternalLoad from LoadURI"
")"); do { MOZ_CrashSequence(__null, 854); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
855 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"
")", "./../../../docshell/base/nsDocShell.cpp", 856); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aLoadState->FileName().IsVoid()" ") (" "FileName should be null when calling InternalLoad from LoadURI"
")"); do { MOZ_CrashSequence(__null, 856); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
856 "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"
")", "./../../../docshell/base/nsDocShell.cpp", 856); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aLoadState->FileName().IsVoid()" ") (" "FileName should be null when calling InternalLoad from LoadURI"
")"); do { MOZ_CrashSequence(__null, 856); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
857 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" ")", "./../../../docshell/base/nsDocShell.cpp"
, 859); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aLoadState->LoadIsFromSessionHistory()"
") (" "Shouldn't be loading from an entry when calling InternalLoad "
"from LoadURI" ")"); do { MOZ_CrashSequence(__null, 859); __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
858 "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" ")", "./../../../docshell/base/nsDocShell.cpp"
, 859); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aLoadState->LoadIsFromSessionHistory()"
") (" "Shouldn't be loading from an entry when calling InternalLoad "
"from LoadURI" ")"); do { MOZ_CrashSequence(__null, 859); __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
859 "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" ")", "./../../../docshell/base/nsDocShell.cpp"
, 859); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aLoadState->LoadIsFromSessionHistory()"
") (" "Shouldn't be loading from an entry when calling InternalLoad "
"from LoadURI" ")"); do { MOZ_CrashSequence(__null, 859); __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
;
860
861 // If we have a system triggering principal, we can assume that this load was
862 // triggered by some UI in the browser chrome, such as the URL bar or
863 // bookmark bar. This should count as a user interaction for the current sh
864 // entry, so that the user may navigate back to the current entry, from the
865 // entry that is going to be added as part of this load.
866 nsCOMPtr<nsIPrincipal> triggeringPrincipal =
867 aLoadState->TriggeringPrincipal();
868 if (triggeringPrincipal && triggeringPrincipal->IsSystemPrincipal()) {
869 WindowContext* topWc = mBrowsingContext->GetTopWindowContext();
870 // Already set by BrowsingContext::LoadURI for a parent initiated load;
871 // notifying again could flag the entry this load is about to add.
872 if (topWc && !topWc->IsDiscarded() &&
873 !topWc->GetSHEntryHasUserInteraction()) {
874 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))"
, "./../../../docshell/base/nsDocShell.cpp", 874); AnnotateMozCrashReason
("MOZ_CRASH(" "NS_SUCCEEDED(topWc->SetSHEntryHasUserInteraction(true))"
")"); do { MOZ_CrashSequence(__null, 874); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
;
875 }
876 }
877
878 rv = InternalLoad(aLoadState);
879 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, "./../../../docshell/base/nsDocShell.cpp"
, 879); return rv; } } while (false)
;
880
881 if (aLoadState->GetOriginalURIString().isSome()) {
882 // Save URI string in case it's needed later when
883 // sending to search engine service in EndPageLoad()
884 mOriginalUriString = *aLoadState->GetOriginalURIString();
885 }
886
887 return NS_OK;
888}
889
890bool nsDocShell::IsLoadingFromSessionHistory() {
891 return mActiveEntryIsLoadingFromSessionHistory;
892}
893
894// StopDetector is modeled similarly to OnloadBlocker; it is a rather
895// dummy nsIRequest implementation which can be added to an nsILoadGroup to
896// detect Cancel calls.
897class StopDetector final : public nsIRequest {
898 public:
899 StopDetector() = default;
900
901 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:
902 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;
903
904 bool Canceled() { return mCanceled; }
905
906 private:
907 ~StopDetector() = default;
908
909 bool mCanceled = false;
910};
911
912NS_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" ")", "./../../../docshell/base/nsDocShell.cpp"
, 912); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { MOZ_CrashSequence(__null, 912
); __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" ")", "./../../../docshell/base/nsDocShell.cpp"
, 912); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"StopDetector\" != nullptr"
") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__null
, 912); __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" ")", "./../../../docshell/base/nsDocShell.cpp"
, 912); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { MOZ_CrashSequence(__null, 912
); __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" ")", "./../../../docshell/base/nsDocShell.cpp"
, 912); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"StopDetector\" != nullptr"
") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__null
, 912); __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", "./../../../docshell/base/nsDocShell.cpp", 912
); 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; }
913
914NS_IMETHODIMPnsresult
915StopDetector::GetName(nsACString& aResult) {
916 aResult.AssignLiteral("about:stop-detector");
917 return NS_OK;
918}
919
920NS_IMETHODIMPnsresult
921StopDetector::IsPending(bool* aRetVal) {
922 *aRetVal = true;
923 return NS_OK;
924}
925
926NS_IMETHODIMPnsresult
927StopDetector::GetStatus(nsresult* aStatus) {
928 *aStatus = NS_OK;
929 return NS_OK;
930}
931
932NS_IMETHODIMPnsresult StopDetector::SetCanceledReason(const nsACString& aReason) {
933 return SetCanceledReasonImpl(aReason);
934}
935
936NS_IMETHODIMPnsresult StopDetector::GetCanceledReason(nsACString& aReason) {
937 return GetCanceledReasonImpl(aReason);
938}
939
940NS_IMETHODIMPnsresult StopDetector::CancelWithReason(nsresult aStatus,
941 const nsACString& aReason) {
942 return CancelWithReasonImpl(aStatus, aReason);
943}
944
945NS_IMETHODIMPnsresult
946StopDetector::Cancel(nsresult aStatus) {
947 mCanceled = true;
948 return NS_OK;
949}
950
951NS_IMETHODIMPnsresult
952StopDetector::Suspend(void) { return NS_OK; }
953NS_IMETHODIMPnsresult
954StopDetector::Resume(void) { return NS_OK; }
955
956NS_IMETHODIMPnsresult
957StopDetector::GetLoadGroup(nsILoadGroup** aLoadGroup) {
958 *aLoadGroup = nullptr;
959 return NS_OK;
960}
961
962NS_IMETHODIMPnsresult
963StopDetector::SetLoadGroup(nsILoadGroup* aLoadGroup) { return NS_OK; }
964
965NS_IMETHODIMPnsresult
966StopDetector::GetLoadFlags(nsLoadFlags* aLoadFlags) {
967 *aLoadFlags = nsIRequest::LOAD_NORMAL;
968 return NS_OK;
969}
970
971NS_IMETHODIMPnsresult
972StopDetector::GetTRRMode(nsIRequest::TRRMode* aTRRMode) {
973 return GetTRRModeImpl(aTRRMode);
974}
975
976NS_IMETHODIMPnsresult
977StopDetector::SetTRRMode(nsIRequest::TRRMode aTRRMode) {
978 return SetTRRModeImpl(aTRRMode);
979}
980
981NS_IMETHODIMPnsresult
982StopDetector::SetLoadFlags(nsLoadFlags aLoadFlags) { return NS_OK; }
983
984bool nsDocShell::MaybeHandleSubframeHistory(
985 nsDocShellLoadState* aLoadState, bool aContinueHandlingSubframeHistory) {
986 // First, verify if this is a subframe.
987 // Note, it is ok to rely on docshell here and not browsing context since when
988 // an iframe is created, it has first in-process docshell.
989 nsCOMPtr<nsIDocShellTreeItem> parentAsItem;
990 GetInProcessSameTypeParent(getter_AddRefs(parentAsItem));
991 nsCOMPtr<nsIDocShell> parentDS(do_QueryInterface(parentAsItem));
992
993 if (!parentDS || parentDS == static_cast<nsIDocShell*>(this)) {
994 if (mBrowsingContext && mBrowsingContext->IsTop() &&
995 !aLoadState->HistoryBehavior()) {
996 // This is the root docshell. If we got here while
997 // executing an onLoad Handler,this load will not go
998 // into session history.
999 // XXX Why is this code in a method which deals with iframes!
1000 if (aLoadState->IsFormSubmission()) {
1001#ifdef DEBUG1
1002 if (!mEODForCurrentDocument) {
1003 const MaybeDiscarded<BrowsingContext>& targetBC =
1004 aLoadState->TargetBrowsingContext();
1005 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", "./../../../docshell/base/nsDocShell.cpp"
, 1006); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->LoadType() == LOAD_NORMAL_REPLACE"
")"); do { MOZ_CrashSequence(__null, 1006); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
1006 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", "./../../../docshell/base/nsDocShell.cpp"
, 1006); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->LoadType() == LOAD_NORMAL_REPLACE"
")"); do { MOZ_CrashSequence(__null, 1006); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
1007 }
1008#endif
1009 } else {
1010 bool inOnLoadHandler = false;
1011 GetIsExecutingOnLoadHandler(&inOnLoadHandler);
1012 if (inOnLoadHandler) {
1013 aLoadState->SetLoadType(LOAD_NORMAL_REPLACE);
1014 }
1015 }
1016 }
1017 return false;
1018 }
1019
1020 /* OK. It is a subframe. Checkout the parent's loadtype. If the parent was
1021 * loaded through a history mechanism, then get the SH entry for the child
1022 * from the parent. This is done to restore frameset navigation while going
1023 * back/forward. If the parent was loaded through any other loadType, set the
1024 * child's loadType too accordingly, so that session history does not get
1025 * confused.
1026 */
1027
1028 // Get the parent's load type
1029 uint32_t parentLoadType;
1030 parentDS->GetLoadType(&parentLoadType);
1031
1032 if (!aContinueHandlingSubframeHistory) {
1033 if (nsDocShell::Cast(parentDS.get())->IsLoadingFromSessionHistory() &&
1034 !GetCreatedDynamically()) {
1035 if (XRE_IsContentProcess()) {
1036 dom::ContentChild* contentChild = dom::ContentChild::GetSingleton();
1037 nsCOMPtr<nsILoadGroup> loadGroup;
1038 GetLoadGroup(getter_AddRefs(loadGroup));
1039 if (contentChild && loadGroup && !GetIsAttemptingToNavigate()) {
1040 RefPtr<Document> parentDoc = parentDS->GetDocument();
1041 parentDoc->BlockOnload();
1042 RefPtr<BrowsingContext> browsingContext = mBrowsingContext;
1043 Maybe<uint64_t> currentLoadIdentifier =
1044 mBrowsingContext->GetCurrentLoadIdentifier();
1045 RefPtr<nsDocShellLoadState> loadState = aLoadState;
1046 bool isNavigating = mIsNavigating;
1047 RefPtr stopDetector = MakeRefPtr<StopDetector>();
1048 loadGroup->AddRequest(stopDetector, nullptr);
1049 // Need to set mCheckingSessionHistory so that
1050 // GetIsAttemptingToNavigate() returns true.
1051 mCheckingSessionHistory = true;
1052
1053 auto resolve =
1054 [currentLoadIdentifier, browsingContext, parentDoc, loadState,
1055 isNavigating, loadGroup, stopDetector](
1056 mozilla::Maybe<LoadingSessionHistoryInfo>&& aResult) {
1057 RefPtr<nsDocShell> docShell =
1058 static_cast<nsDocShell*>(browsingContext->GetDocShell());
1059 auto unblockParent = MakeScopeExit(
1060 [loadGroup, stopDetector, parentDoc, docShell]() {
1061 if (docShell) {
1062 docShell->mCheckingSessionHistory = false;
1063 }
1064 loadGroup->RemoveRequest(stopDetector, nullptr, NS_OK);
1065 parentDoc->UnblockOnload(false);
1066 });
1067
1068 if (!docShell || !docShell->mCheckingSessionHistory) {
1069 return;
1070 }
1071
1072 if (stopDetector->Canceled()) {
1073 return;
1074 }
1075 if (currentLoadIdentifier ==
1076 browsingContext->GetCurrentLoadIdentifier() &&
1077 aResult.isSome()) {
1078 loadState->SetLoadingSessionHistoryInfo(aResult.value());
1079 // This is an initial subframe load from the session
1080 // history, index doesn't need to be updated.
1081 loadState->SetLoadIsFromSessionHistory(0, false);
1082 }
1083
1084 // We got the results back from the parent process, call
1085 // LoadURI again with the possibly updated data.
1086 docShell->LoadURI(loadState, isNavigating, true);
1087 };
1088 auto reject = [loadGroup, stopDetector, browsingContext,
1089 parentDoc](mozilla::ipc::ResponseRejectReason) {
1090 RefPtr<nsDocShell> docShell =
1091 static_cast<nsDocShell*>(browsingContext->GetDocShell());
1092 if (docShell) {
1093 docShell->mCheckingSessionHistory = false;
1094 }
1095 // In practise reject shouldn't be called ever.
1096 loadGroup->RemoveRequest(stopDetector, nullptr, NS_OK);
1097 parentDoc->UnblockOnload(false);
1098 };
1099 contentChild->SendGetLoadingSessionHistoryInfoFromParent(
1100 mBrowsingContext, std::move(resolve), std::move(reject));
1101 return true;
1102 }
1103 } else {
1104 Maybe<LoadingSessionHistoryInfo> info;
1105 mBrowsingContext->Canonical()->GetLoadingSessionHistoryInfoFromParent(
1106 info);
1107 if (info.isSome()) {
1108 aLoadState->SetLoadingSessionHistoryInfo(info.value());
1109 // This is an initial subframe load from the session
1110 // history, index doesn't need to be updated.
1111 aLoadState->SetLoadIsFromSessionHistory(0, false);
1112 }
1113 }
1114 }
1115 }
1116
1117 // Make some decisions on the child frame's loadType based on the
1118 // parent's loadType, if the subframe hasn't loaded anything into it.
1119 //
1120 // In some cases privileged scripts may try to get the DOMWindow
1121 // reference of this docshell before the loading starts, causing the
1122 // initial about:blank content viewer being created and mCurrentURI being
1123 // set. To handle this case we check if mCurrentURI is about:blank.
1124
1125 if (mCurrentURI &&
1126 (!NS_IsAboutBlank(mCurrentURI) || mLoadingEntry || mActiveEntry) &&
1127 !aLoadState->HistoryBehavior()) {
1128 // This is a pre-existing subframe. If
1129 // 1. The load of this frame was not originally initiated by session
1130 // history directly (i.e. (!shEntry) condition succeeded, but it can
1131 // still be a history load on parent which causes this frame being
1132 // loaded), which we checked with the above assert, and
1133 // 2. mCurrentURI is not null, nor the initial about:blank,
1134 // it is possible that a parent's onLoadHandler or even self's
1135 // onLoadHandler is loading a new page in this child. Check parent's and
1136 // self's busy flag and if it is set, we don't want this onLoadHandler
1137 // load to get in to session history.
1138 BusyFlags parentBusy = parentDS->GetBusyFlags();
1139 BusyFlags selfBusy = GetBusyFlags();
1140
1141 if (parentBusy & BUSY_FLAGS_BUSY || selfBusy & BUSY_FLAGS_BUSY) {
1142 aLoadState->SetLoadType(LOAD_NORMAL_REPLACE);
1143 aLoadState->ClearLoadIsFromSessionHistory();
1144 }
1145 return false;
1146 }
1147
1148 // This is a newly created frame. Check for exception cases first.
1149 // By default the subframe will inherit the parent's loadType.
1150 if (aLoadState->LoadIsFromSessionHistory() &&
1151 (parentLoadType == LOAD_NORMAL || parentLoadType == LOAD_LINK)) {
1152 // The parent was loaded normally. In this case, this *brand new*
1153 // child really shouldn't have a SHEntry. If it does, it could be
1154 // because the parent is replacing an existing frame with a new frame,
1155 // in the onLoadHandler. We don't want this url to get into session
1156 // history. Clear off shEntry, and set load type to
1157 // LOAD_BYPASS_HISTORY.
1158 bool inOnLoadHandler = false;
1159 parentDS->GetIsExecutingOnLoadHandler(&inOnLoadHandler);
1160 if (inOnLoadHandler) {
1161 aLoadState->SetLoadType(LOAD_NORMAL_REPLACE);
1162 aLoadState->ClearLoadIsFromSessionHistory();
1163 }
1164 } else if (parentLoadType == LOAD_REFRESH) {
1165 // Clear shEntry. For refresh loads, we have to load
1166 // what comes through the pipe, not what's in history.
1167 aLoadState->ClearLoadIsFromSessionHistory();
1168 } else if ((parentLoadType == LOAD_BYPASS_HISTORY) ||
1169 (aLoadState->LoadIsFromSessionHistory() &&
1170 ((parentLoadType & LOAD_CMD_HISTORY) ||
1171 (parentLoadType == LOAD_RELOAD_NORMAL) ||
1172 (parentLoadType == LOAD_RELOAD_CHARSET_CHANGE) ||
1173 (parentLoadType == LOAD_RELOAD_CHARSET_CHANGE_BYPASS_CACHE) ||
1174 (parentLoadType ==
1175 LOAD_RELOAD_CHARSET_CHANGE_BYPASS_PROXY_AND_CACHE)))) {
1176 // If the parent url, bypassed history or was loaded from
1177 // history, pass on the parent's loadType to the new child
1178 // frame too, so that the child frame will also
1179 // avoid getting into history.
1180 aLoadState->SetLoadType(parentLoadType);
1181 } else if (parentLoadType == LOAD_ERROR_PAGE) {
1182 // If the parent document is an error page, we don't
1183 // want to update global/session history. However,
1184 // this child frame is not an error page.
1185 aLoadState->SetLoadType(LOAD_BYPASS_HISTORY);
1186 } else if ((parentLoadType == LOAD_RELOAD_BYPASS_CACHE) ||
1187 (parentLoadType == LOAD_RELOAD_BYPASS_PROXY) ||
1188 (parentLoadType == LOAD_RELOAD_BYPASS_PROXY_AND_CACHE)) {
1189 // the new frame should inherit the parent's load type so that it also
1190 // bypasses the cache and/or proxy
1191 aLoadState->SetLoadType(parentLoadType);
1192 }
1193
1194 return false;
1195}
1196
1197/*
1198 * Reset state to a new content model within the current document and the
1199 * document viewer. Called by the document before initiating an out of band
1200 * document.write().
1201 */
1202NS_IMETHODIMPnsresult
1203nsDocShell::PrepareForNewContentModel() {
1204 // Clear out our form control state, because the state of controls
1205 // in the pre-open() document should not affect the state of
1206 // controls that are now going to be written.
1207 SetLayoutHistoryState(nullptr);
1208 mEODForCurrentDocument = false;
1209 return NS_OK;
1210}
1211
1212NS_IMETHODIMPnsresult
1213nsDocShell::FirePageHideNotification() {
1214 FirePageHideNotificationInternal(false);
1215 return NS_OK;
1216}
1217
1218void nsDocShell::FirePageHideNotificationInternal(
1219 bool aSkipCheckingDynEntries) {
1220 {
1221 nsAutoMicroTask mt;
1222 SetOngoingNavigation(Nothing());
1223 }
1224
1225 if (mDocumentViewer && !mFiredUnloadEvent) {
1226 // Keep an explicit reference since calling PageHide could release
1227 // mDocumentViewer
1228 nsCOMPtr<nsIDocumentViewer> viewer(mDocumentViewer);
1229 mFiredUnloadEvent = true;
1230
1231 if (mTiming) {
1232 mTiming->NotifyUnloadEventStart();
1233 }
1234
1235 viewer->PageHide(true);
1236
1237 if (mTiming) {
1238 mTiming->NotifyUnloadEventEnd();
1239 }
1240
1241 AutoTArray<nsCOMPtr<nsIDocShell>, 8> kids;
1242 uint32_t n = mChildList.Length();
1243 kids.SetCapacity(n);
1244 for (uint32_t i = 0; i < n; i++) {
1245 kids.AppendElement(do_QueryInterface(ChildAt(i)));
1246 }
1247
1248 n = kids.Length();
1249 for (uint32_t i = 0; i < n; ++i) {
1250 RefPtr<nsDocShell> child = static_cast<nsDocShell*>(kids[i].get());
1251 if (child) {
1252 // Skip checking dynamic subframe entries in our children.
1253 child->FirePageHideNotificationInternal(true);
1254 }
1255 }
1256
1257 // If the document is unloading, remove all dynamic subframe entries.
1258 if (!aSkipCheckingDynEntries) {
1259 RefPtr<ChildSHistory> rootSH = GetRootSessionHistory();
1260 if (rootSH) {
1261 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)
1262 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)
1263 ("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)
;
1264 if (mActiveEntry) {
1265 mBrowsingContext->RemoveDynEntriesFromActiveSessionHistoryEntry();
1266 }
1267 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)
1268 ("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)
;
1269 }
1270 }
1271
1272 // Now make sure our editor, if any, is detached before we go
1273 // any farther.
1274 DetachEditorFromWindow();
1275 }
1276}
1277
1278void nsDocShell::ThawFreezeNonRecursive(bool aThaw) {
1279 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()"
, "./../../../docshell/base/nsDocShell.cpp", 1279); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "mozilla::BFCacheInParent()" ")"); do { MOZ_CrashSequence
(__null, 1279); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
1280
1281 if (!mScriptGlobal) {
1282 return;
1283 }
1284
1285 if (RefPtr<nsGlobalWindowInner> inner =
1286 nsGlobalWindowInner::Cast(mScriptGlobal->GetCurrentInnerWindow())) {
1287 if (aThaw) {
1288 inner->Thaw(false);
1289 } else {
1290 inner->Freeze(false);
1291 }
1292 }
1293}
1294
1295void nsDocShell::FirePageHideShowNonRecursive(bool aShow) {
1296 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()"
, "./../../../docshell/base/nsDocShell.cpp", 1296); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "mozilla::BFCacheInParent()" ")"); do { MOZ_CrashSequence
(__null, 1296); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
1297
1298 if (!mDocumentViewer) {
1299 return;
1300 }
1301
1302 // Emulate what non-SHIP BFCache does too. In pageshow case
1303 // add and remove a request and before that call SetCurrentURI to get
1304 // the location change notification.
1305 // For pagehide, set mFiredUnloadEvent to true, so that unload doesn't fire.
1306 nsCOMPtr<nsIDocumentViewer> viewer(mDocumentViewer);
1307 if (aShow) {
1308 viewer->SetIsHidden(false);
1309 mRefreshURIList = std::move(mBFCachedRefreshURIList);
1310 RefreshURIFromQueue();
1311 mFiredUnloadEvent = false;
1312 RefPtr<Document> doc = viewer->GetDocument();
1313 if (doc) {
1314 doc->NotifyActivityChanged();
1315 nsCOMPtr<nsPIDOMWindowInner> inner =
1316 mScriptGlobal ? mScriptGlobal->GetCurrentInnerWindow() : nullptr;
1317 if (mBrowsingContext->IsTop()) {
1318 doc->NotifyPossibleTitleChange(false);
1319 doc->SetLoadingOrRestoredFromBFCacheTimeStampToNow();
1320 if (inner) {
1321 // Now that we have found the inner window of the page restored
1322 // from the history, we have to make sure that
1323 // performance.navigation.type is 2.
1324 // Traditionally this type change has been done to the top level page
1325 // only.
1326 Performance* performance = inner->GetPerformance();
1327 if (performance) {
1328 performance->GetDOMTiming()->NotifyRestoreStart();
1329 }
1330 }
1331 }
1332
1333 nsCOMPtr<nsIChannel> channel = doc->GetChannel();
1334 if (channel) {
1335 SetLoadType(LOAD_HISTORY);
1336 mEODForCurrentDocument = false;
1337 mIsRestoringDocument = true;
1338 mLoadGroup->AddRequest(channel, nullptr);
1339 nsCOMPtr<nsIURI> uri;
1340 if (doc->FragmentDirective()) {
1341 // If we have fragment directives, then we've mutated the document
1342 // uri. Set the current URI from session history instead.
1343 uri = mActiveEntry ? mActiveEntry->GetURI() : nullptr;
1344 }
1345 if (!uri) {
1346 uri = doc->GetDocumentURI();
1347 }
1348 SetCurrentURI(uri, channel,
1349 /* aFireOnLocationChange */ true,
1350 /* aIsInitialAboutBlank */ false,
1351 /* aLocationFlags */ 0);
1352 mLoadGroup->RemoveRequest(channel, nullptr, NS_OK);
1353 mIsRestoringDocument = false;
1354 }
1355 RefPtr<PresShell> presShell = GetPresShell();
1356 if (presShell) {
1357 presShell->Thaw(false);
1358 }
1359
1360 if (inner) {
1361 inner->FireDelayedDOMEvents(false);
1362 }
1363 }
1364 } else if (!mFiredUnloadEvent) {
1365 // XXXBFCache check again that the page can enter bfcache.
1366 // XXXBFCache should mTiming->NotifyUnloadEventStart()/End() be called here?
1367
1368 if (mRefreshURIList) {
1369 RefreshURIToQueue();
1370 mBFCachedRefreshURIList = std::move(mRefreshURIList);
1371 } else {
1372 // If Stop was called, the list was moved to mSavedRefreshURIList after
1373 // calling SuspendRefreshURIs, which calls RefreshURIToQueue.
1374 mBFCachedRefreshURIList = std::move(mSavedRefreshURIList);
1375 }
1376
1377 mFiredUnloadEvent = true;
1378 viewer->PageHide(false);
1379
1380 RefPtr<PresShell> presShell = GetPresShell();
1381 if (presShell) {
1382 presShell->Freeze(false);
1383 }
1384 }
1385}
1386
1387nsresult nsDocShell::Dispatch(already_AddRefed<nsIRunnable> aRunnable) {
1388 nsCOMPtr<nsIRunnable> runnable(aRunnable);
1389 if (NS_WARN_IF(!GetWindow())NS_warn_if_impl(!GetWindow(), "!GetWindow()", "./../../../docshell/base/nsDocShell.cpp"
, 1389)
) {
1390 // Window should only be unavailable after destroyed.
1391 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"
, "./../../../docshell/base/nsDocShell.cpp", 1391); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "mIsBeingDestroyed" ")"); do { MOZ_CrashSequence
(__null, 1391); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
1392 return NS_ERROR_FAILURE;
1393 }
1394 return SchedulerGroup::Dispatch(runnable.forget());
1395}
1396
1397NS_IMETHODIMPnsresult
1398nsDocShell::DispatchLocationChangeEvent() {
1399 return Dispatch(NewRunnableMethod("nsDocShell::FireDummyOnLocationChange",
1400 this,
1401 &nsDocShell::FireDummyOnLocationChange));
1402}
1403
1404NS_IMETHODIMPnsresult
1405nsDocShell::StartDelayedAutoplayMediaComponents() {
1406 RefPtr<nsPIDOMWindowOuter> outerWindow = GetWindow();
1407 if (outerWindow) {
1408 outerWindow->ActivateMediaComponents();
1409 }
1410 return NS_OK;
1411}
1412
1413bool nsDocShell::MaybeInitTiming() {
1414 if (mTiming && !mBlankTiming) {
1415 return false;
1416 }
1417
1418 bool canBeReset = false;
1419
1420 if (mScriptGlobal && mBlankTiming) {
1421 nsPIDOMWindowInner* innerWin = mScriptGlobal->GetCurrentInnerWindow();
1422 if (innerWin && innerWin->GetPerformance()) {
1423 mTiming = innerWin->GetPerformance()->GetDOMTiming();
1424 mBlankTiming = false;
1425 }
1426 }
1427
1428 if (!mTiming) {
1429 mTiming = new nsDOMNavigationTiming(this);
1430 canBeReset = true;
1431 }
1432
1433 mTiming->NotifyNavigationStart(
1434 mBrowsingContext->IsActive()
1435 ? nsDOMNavigationTiming::DocShellState::eActive
1436 : nsDOMNavigationTiming::DocShellState::eInactive);
1437
1438 return canBeReset;
1439}
1440
1441void nsDocShell::MaybeResetInitTiming(bool aReset) {
1442 if (aReset) {
1443 mTiming = nullptr;
1444 }
1445}
1446
1447nsDOMNavigationTiming* nsDocShell::GetNavigationTiming() const {
1448 return mTiming;
1449}
1450
1451nsPresContext* nsDocShell::GetEldestPresContext() {
1452 nsIDocumentViewer* viewer = mDocumentViewer;
1453 while (viewer) {
1454 nsIDocumentViewer* prevViewer = viewer->GetPreviousViewer();
1455 if (!prevViewer) {
1456 return viewer->GetPresContext();
1457 }
1458 viewer = prevViewer;
1459 }
1460
1461 return nullptr;
1462}
1463
1464nsPresContext* nsDocShell::GetPresContext() {
1465 if (!mDocumentViewer) {
1466 return nullptr;
1467 }
1468
1469 return mDocumentViewer->GetPresContext();
1470}
1471
1472PresShell* nsDocShell::GetPresShell() {
1473 nsPresContext* presContext = GetPresContext();
1474 return presContext ? presContext->GetPresShell() : nullptr;
1475}
1476
1477PresShell* nsDocShell::GetEldestPresShell() {
1478 nsPresContext* presContext = GetEldestPresContext();
1479
1480 if (presContext) {
1481 return presContext->GetPresShell();
1482 }
1483
1484 return nullptr;
1485}
1486
1487NS_IMETHODIMPnsresult
1488nsDocShell::GetDocViewer(nsIDocumentViewer** aDocumentViewer) {
1489 NS_ENSURE_ARG_POINTER(aDocumentViewer)do { if ((__builtin_expect(!!(!(aDocumentViewer)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aDocumentViewer" ") failed"
, nullptr, "./../../../docshell/base/nsDocShell.cpp", 1489); return
NS_ERROR_INVALID_POINTER; } } while (false)
;
1490
1491 *aDocumentViewer = mDocumentViewer;
1492 NS_IF_ADDREF(*aDocumentViewer)ns_if_addref(*aDocumentViewer);
1493 return NS_OK;
1494}
1495
1496NS_IMETHODIMPnsresult
1497nsDocShell::GetOuterWindowID(uint64_t* aWindowID) {
1498 *aWindowID = mContentWindowID;
1499 return NS_OK;
1500}
1501
1502NS_IMETHODIMPnsresult
1503nsDocShell::SetChromeEventHandler(EventTarget* aChromeEventHandler) {
1504 mChromeEventHandler = aChromeEventHandler;
1505
1506 if (mScriptGlobal) {
1507 mScriptGlobal->SetChromeEventHandler(mChromeEventHandler);
1508 }
1509
1510 return NS_OK;
1511}
1512
1513NS_IMETHODIMPnsresult
1514nsDocShell::GetChromeEventHandler(EventTarget** aChromeEventHandler) {
1515 NS_ENSURE_ARG_POINTER(aChromeEventHandler)do { if ((__builtin_expect(!!(!(aChromeEventHandler)), 0))) {
NS_DebugBreak(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aChromeEventHandler"
") failed", nullptr, "./../../../docshell/base/nsDocShell.cpp"
, 1515); return NS_ERROR_INVALID_POINTER; } } while (false)
;
1516 RefPtr<EventTarget> handler = mChromeEventHandler;
1517 handler.forget(aChromeEventHandler);
1518 return NS_OK;
1519}
1520
1521NS_IMETHODIMPnsresult
1522nsDocShell::SetCurrentURIForSessionStore(nsIURI* aURI) {
1523 // Note that securityUI will set STATE_IS_INSECURE, even if
1524 // the scheme of |aURI| is "https".
1525 SetCurrentURI(aURI, nullptr,
1526 /* aFireOnLocationChange */
1527 true,
1528 /* aIsInitialAboutBlank */
1529 false,
1530 /* aLocationFlags */
1531 nsIWebProgressListener::LOCATION_CHANGE_SESSION_STORE);
1532 return NS_OK;
1533}
1534
1535bool nsDocShell::SetCurrentURI(nsIURI* aURI, nsIRequest* aRequest,
1536 bool aFireOnLocationChange,
1537 bool aIsInitialAboutBlank,
1538 uint32_t aLocationFlags) {
1539 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"
, "./../../../docshell/base/nsDocShell.cpp", 1539); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!mIsBeingDestroyed" ")"); do { MOZ_CrashSequence
(__null, 1539); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
1540
1541 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)
1542 ("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)
1543 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)
;
1544
1545 // We don't want to send a location change when we're displaying an error
1546 // page, and we don't want to change our idea of "current URI" either
1547 if (mLoadType == LOAD_ERROR_PAGE) {
1548 return false;
1549 }
1550
1551 bool uriIsEqual = false;
1552 if (!mCurrentURI || !aURI ||
1553 NS_FAILED(mCurrentURI->Equals(aURI, &uriIsEqual))((bool)(__builtin_expect(!!(NS_FAILED_impl(mCurrentURI->Equals
(aURI, &uriIsEqual))), 0)))
|| !uriIsEqual) {
1554 mTitleValidForCurrentURI = false;
1555 }
1556
1557 SetCurrentURIInternal(aURI);
1558
1559#ifdef DEBUG1
1560 mLastOpenedURI = aURI;
1561#endif
1562
1563 if (!NS_IsAboutBlankAllowQueryAndFragment(mCurrentURI)) {
1564 mHasLoadedNonBlankURI = true;
1565 }
1566
1567 // Don't fire onLocationChange when creating a the initial about:blank
1568 // document, as this can happen when it's not safe for us to run script.
1569 // Note that if this initial about:blank isn't immediately navigated
1570 // away from, the onLocationChange will be fired as part of committing
1571 // to keeping the initial about:blank as the actual first initial
1572 // navigation destination.
1573 if (aIsInitialAboutBlank) {
1574 MOZ_ASSERT(!mHasLoadedNonBlankURI && !aRequest && aLocationFlags == 0)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mHasLoadedNonBlankURI && !aRequest &&
aLocationFlags == 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mHasLoadedNonBlankURI &&
!aRequest && aLocationFlags == 0))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("!mHasLoadedNonBlankURI && !aRequest && aLocationFlags == 0"
, "./../../../docshell/base/nsDocShell.cpp", 1574); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!mHasLoadedNonBlankURI && !aRequest && aLocationFlags == 0"
")"); do { MOZ_CrashSequence(__null, 1574); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1575 return false;
1576 }
1577
1578 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()", "./../../../docshell/base/nsDocShell.cpp"
, 1578); AnnotateMozCrashReason("MOZ_ASSERT" "(" "nsContentUtils::IsSafeToRunScript()"
")"); do { MOZ_CrashSequence(__null, 1578); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1579
1580 if (aFireOnLocationChange) {
1581 FireOnLocationChange(this, aRequest, aURI, aLocationFlags);
1582 }
1583 return !aFireOnLocationChange;
1584}
1585
1586void nsDocShell::SetCurrentURIInternal(nsIURI* aURI) {
1587 mCurrentURI = aURI;
1588 if (mBrowsingContext) {
1589 mBrowsingContext->ClearCachedValuesOfLocations();
1590 }
1591}
1592
1593NS_IMETHODIMPnsresult
1594nsDocShell::GetCharset(nsACString& aCharset) {
1595 aCharset.Truncate();
1596
1597 PresShell* presShell = GetPresShell();
1598 NS_ENSURE_TRUE(presShell, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(presShell)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "presShell" ") failed", nullptr
, "./../../../docshell/base/nsDocShell.cpp", 1598); return NS_ERROR_FAILURE
; } } while (false)
;
1599 Document* doc = presShell->GetDocument();
1600 NS_ENSURE_TRUE(doc, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(doc)), 0))) { NS_DebugBreak(NS_DEBUG_WARNING
, "NS_ENSURE_TRUE(" "doc" ") failed", nullptr, "./../../../docshell/base/nsDocShell.cpp"
, 1600); return NS_ERROR_FAILURE; } } while (false)
;
1601 doc->GetDocumentCharacterSet()->Name(aCharset);
1602 return NS_OK;
1603}
1604
1605NS_IMETHODIMPnsresult
1606nsDocShell::ForceEncodingDetection() {
1607 nsCOMPtr<nsIDocumentViewer> viewer;
1608 GetDocViewer(getter_AddRefs(viewer));
1609 if (!viewer) {
1610 return NS_OK;
1611 }
1612
1613 Document* doc = viewer->GetDocument();
1614 if (!doc || doc->WillIgnoreCharsetOverride()) {
1615 return NS_OK;
1616 }
1617
1618 mForcedAutodetection = true;
1619
1620 nsIURI* uri = doc->GetOriginalURI();
1621 bool isFileURL = uri && uri->SchemeIs("file");
1622
1623 int32_t charsetSource = doc->GetDocumentCharacterSetSource();
1624 auto encoding = doc->GetDocumentCharacterSet();
1625 // AsHTMLDocument is valid, because we called
1626 // WillIgnoreCharsetOverride() above.
1627 if (doc->AsHTMLDocument()->IsPlainText()) {
1628 switch (charsetSource) {
1629 case kCharsetFromInitialAutoDetectionASCII:
1630 // Deliberately no final version
1631 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)
;
1632 break;
1633 case kCharsetFromInitialAutoDetectionWouldNotHaveBeenUTF8Generic:
1634 case kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8Generic:
1635 case kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8GenericInitialWasASCII:
1636 case kCharsetFromInitialAutoDetectionWouldNotHaveBeenUTF8Content:
1637 case kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8Content:
1638 case kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8ContentInitialWasASCII:
1639 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)
;
1640 break;
1641 case kCharsetFromInitialAutoDetectionWouldNotHaveBeenUTF8DependedOnTLD:
1642 case kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8DependedOnTLD:
1643 case kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8DependedOnTLDInitialWasASCII:
1644 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)
;
1645 break;
1646 case kCharsetFromInitialAutoDetectionWouldHaveBeenUTF8:
1647 case kCharsetFromFinalAutoDetectionWouldHaveBeenUTF8InitialWasASCII:
1648 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)
;
1649 break;
1650 case kCharsetFromChannel:
1651 if (encoding == UTF_8_ENCODING) {
1652 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)
;
1653 } else {
1654 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)
;
1655 }
1656 break;
1657 default:
1658 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)
;
1659 break;
1660 }
1661 } else {
1662 switch (charsetSource) {
1663 case kCharsetFromInitialAutoDetectionASCII:
1664 // Deliberately no final version
1665 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)
;
1666 break;
1667 case kCharsetFromInitialAutoDetectionWouldNotHaveBeenUTF8Generic:
1668 case kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8Generic:
1669 case kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8GenericInitialWasASCII:
1670 case kCharsetFromInitialAutoDetectionWouldNotHaveBeenUTF8Content:
1671 case kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8Content:
1672 case kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8ContentInitialWasASCII:
1673 LOGCHARSETMENU(("HTML:UnlabeledNonUtf8"))do { const ::mozilla::LogModule* moz_real_module = gCharsetMenuLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, "HTML:UnlabeledNonUtf8"
); } } while (0)
;
1674 break;
1675 case kCharsetFromInitialAutoDetectionWouldNotHaveBeenUTF8DependedOnTLD:
1676 case kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8DependedOnTLD:
1677 case kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8DependedOnTLDInitialWasASCII:
1678 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)
;
1679 break;
1680 case kCharsetFromInitialAutoDetectionWouldHaveBeenUTF8:
1681 case kCharsetFromFinalAutoDetectionWouldHaveBeenUTF8InitialWasASCII:
1682 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)
;
1683 break;
1684 case kCharsetFromChannel:
1685 if (encoding == UTF_8_ENCODING) {
1686 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)
;
1687 } else {
1688 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)
;
1689 }
1690 break;
1691 case kCharsetFromXmlDeclaration:
1692 case kCharsetFromMetaTag:
1693 if (isFileURL) {
1694 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)
;
1695 } else if (encoding == UTF_8_ENCODING) {
1696 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)
;
1697 } else {
1698 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)
;
1699 }
1700 break;
1701 default:
1702 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)
;
1703 break;
1704 }
1705 }
1706 return NS_OK;
1707}
1708
1709void nsDocShell::SetParentCharset(const Encoding*& aCharset,
1710 int32_t aCharsetSource,
1711 nsIPrincipal* aPrincipal) {
1712 mParentCharset = aCharset;
1713 mParentCharsetSource = aCharsetSource;
1714 mParentCharsetPrincipal = aPrincipal;
1715}
1716
1717void nsDocShell::GetParentCharset(const Encoding*& aCharset,
1718 int32_t* aCharsetSource,
1719 nsIPrincipal** aPrincipal) {
1720 aCharset = mParentCharset;
1721 *aCharsetSource = mParentCharsetSource;
1722 NS_IF_ADDREF(*aPrincipal = mParentCharsetPrincipal)ns_if_addref(*aPrincipal = mParentCharsetPrincipal);
1723}
1724
1725NS_IMETHODIMPnsresult
1726nsDocShell::GetHasTrackingContentBlocked(Promise** aPromise) {
1727 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", "./../../../docshell/base/nsDocShell.cpp"
, 1727); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPromise" ")"
); do { MOZ_CrashSequence(__null, 1727); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1728
1729 ErrorResult rv;
1730 RefPtr<Document> doc(GetDocument());
1731 RefPtr<Promise> retPromise = Promise::Create(doc->GetRelevantGlobal(), rv);
1732 if (NS_WARN_IF(rv.Failed())NS_warn_if_impl(rv.Failed(), "rv.Failed()", "./../../../docshell/base/nsDocShell.cpp"
, 1732)
) {
1733 return rv.StealNSResult();
1734 }
1735
1736 // Retrieve the document's content blocking events from the parent process.
1737 RefPtr<Document::GetContentBlockingEventsPromise> promise =
1738 doc->GetContentBlockingEvents();
1739 if (promise) {
1740 promise->Then(
1741 GetCurrentSerialEventTarget(), __func__,
1742 [retPromise](const Document::GetContentBlockingEventsPromise::
1743 ResolveOrRejectValue& aValue) {
1744 if (aValue.IsResolve()) {
1745 bool has = aValue.ResolveValue() &
1746 nsIWebProgressListener::STATE_BLOCKED_TRACKING_CONTENT;
1747 retPromise->MaybeResolve(has);
1748 } else {
1749 retPromise->MaybeResolve(false);
1750 }
1751 });
1752 } else {
1753 retPromise->MaybeResolve(false);
1754 }
1755
1756 retPromise.forget(aPromise);
1757 return NS_OK;
1758}
1759
1760NS_IMETHODIMPnsresult
1761nsDocShell::GetCssErrorReportingEnabled(bool* aEnabled) {
1762 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", "./../../../docshell/base/nsDocShell.cpp"
, 1762); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aEnabled" ")"
); do { MOZ_CrashSequence(__null, 1762); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1763 *aEnabled = mCSSErrorReportingEnabled;
1764 return NS_OK;
1765}
1766
1767NS_IMETHODIMPnsresult
1768nsDocShell::SetCssErrorReportingEnabled(bool aEnabled) {
1769 mCSSErrorReportingEnabled = aEnabled;
1770 return NS_OK;
1771}
1772
1773NS_IMETHODIMPnsresult
1774nsDocShell::GetUsePrivateBrowsing(bool* aUsePrivateBrowsing) {
1775 NS_ENSURE_ARG_POINTER(aUsePrivateBrowsing)do { if ((__builtin_expect(!!(!(aUsePrivateBrowsing)), 0))) {
NS_DebugBreak(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aUsePrivateBrowsing"
") failed", nullptr, "./../../../docshell/base/nsDocShell.cpp"
, 1775); return NS_ERROR_INVALID_POINTER; } } while (false)
;
1776 return mBrowsingContext->GetUsePrivateBrowsing(aUsePrivateBrowsing);
1777}
1778
1779void nsDocShell::NotifyPrivateBrowsingChanged() {
1780 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"
, "./../../../docshell/base/nsDocShell.cpp", 1780); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!mIsBeingDestroyed" ")"); do { MOZ_CrashSequence
(__null, 1780); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
1781
1782 nsTObserverArray<nsWeakPtr>::ForwardIterator iter(mPrivacyObservers);
1783 while (iter.HasMore()) {
1784 nsWeakPtr ref = iter.GetNext();
1785 nsCOMPtr<nsIPrivacyTransitionObserver> obs = do_QueryReferent(ref);
1786 if (!obs) {
1787 iter.Remove();
1788 } else {
1789 obs->PrivateModeChanged(UsePrivateBrowsing());
1790 }
1791 }
1792}
1793
1794NS_IMETHODIMPnsresult
1795nsDocShell::SetUsePrivateBrowsing(bool aUsePrivateBrowsing) {
1796 return mBrowsingContext->SetUsePrivateBrowsing(aUsePrivateBrowsing);
1797}
1798
1799NS_IMETHODIMPnsresult
1800nsDocShell::SetPrivateBrowsing(bool aUsePrivateBrowsing) {
1801 return mBrowsingContext->SetPrivateBrowsing(aUsePrivateBrowsing);
1802}
1803
1804NS_IMETHODIMPnsresult
1805nsDocShell::GetHasLoadedNonBlankURI(bool* aResult) {
1806 NS_ENSURE_ARG_POINTER(aResult)do { if ((__builtin_expect(!!(!(aResult)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aResult" ") failed", nullptr
, "./../../../docshell/base/nsDocShell.cpp", 1806); return NS_ERROR_INVALID_POINTER
; } } while (false)
;
1807
1808 *aResult = mHasLoadedNonBlankURI;
1809 return NS_OK;
1810}
1811
1812bool nsDocShell::HasStartedLoadingOtherThanInitialBlankURI() {
1813 return mHasStartedLoadingOtherThanInitialBlankURI;
1814}
1815
1816NS_IMETHODIMPnsresult
1817nsDocShell::GetUseRemoteTabs(bool* aUseRemoteTabs) {
1818 NS_ENSURE_ARG_POINTER(aUseRemoteTabs)do { if ((__builtin_expect(!!(!(aUseRemoteTabs)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aUseRemoteTabs" ") failed"
, nullptr, "./../../../docshell/base/nsDocShell.cpp", 1818); return
NS_ERROR_INVALID_POINTER; } } while (false)
;
1819 return mBrowsingContext->GetUseRemoteTabs(aUseRemoteTabs);
1820}
1821
1822NS_IMETHODIMPnsresult
1823nsDocShell::SetRemoteTabs(bool aUseRemoteTabs) {
1824 return mBrowsingContext->SetRemoteTabs(aUseRemoteTabs);
1825}
1826
1827NS_IMETHODIMPnsresult
1828nsDocShell::GetUseRemoteSubframes(bool* aUseRemoteSubframes) {
1829 NS_ENSURE_ARG_POINTER(aUseRemoteSubframes)do { if ((__builtin_expect(!!(!(aUseRemoteSubframes)), 0))) {
NS_DebugBreak(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aUseRemoteSubframes"
") failed", nullptr, "./../../../docshell/base/nsDocShell.cpp"
, 1829); return NS_ERROR_INVALID_POINTER; } } while (false)
;
1830 return mBrowsingContext->GetUseRemoteSubframes(aUseRemoteSubframes);
1831}
1832
1833NS_IMETHODIMPnsresult
1834nsDocShell::SetRemoteSubframes(bool aUseRemoteSubframes) {
1835 return mBrowsingContext->SetRemoteSubframes(aUseRemoteSubframes);
1836}
1837
1838NS_IMETHODIMPnsresult
1839nsDocShell::AddWeakPrivacyTransitionObserver(
1840 nsIPrivacyTransitionObserver* aObserver) {
1841 nsWeakPtr weakObs = do_GetWeakReference(aObserver);
1842 if (!weakObs) {
1843 return NS_ERROR_NOT_AVAILABLE;
1844 }
1845 mPrivacyObservers.AppendElement(weakObs);
1846 return NS_OK;
1847}
1848
1849NS_IMETHODIMPnsresult
1850nsDocShell::AddWeakReflowObserver(nsIReflowObserver* aObserver) {
1851 nsWeakPtr weakObs = do_GetWeakReference(aObserver);
1852 if (!weakObs) {
1853 return NS_ERROR_FAILURE;
1854 }
1855 mReflowObservers.AppendElement(weakObs);
1856 return NS_OK;
1857}
1858
1859NS_IMETHODIMPnsresult
1860nsDocShell::RemoveWeakReflowObserver(nsIReflowObserver* aObserver) {
1861 nsWeakPtr obs = do_GetWeakReference(aObserver);
1862 return mReflowObservers.RemoveElement(obs) ? NS_OK : NS_ERROR_FAILURE;
1863}
1864
1865NS_IMETHODIMPnsresult
1866nsDocShell::NotifyReflowObservers(bool aInterruptible,
1867 DOMHighResTimeStamp aStart,
1868 DOMHighResTimeStamp aEnd) {
1869 nsTObserverArray<nsWeakPtr>::ForwardIterator iter(mReflowObservers);
1870 while (iter.HasMore()) {
1871 nsWeakPtr ref = iter.GetNext();
1872 nsCOMPtr<nsIReflowObserver> obs = do_QueryReferent(ref);
1873 if (!obs) {
1874 iter.Remove();
1875 } else if (aInterruptible) {
1876 obs->ReflowInterruptible(aStart, aEnd);
1877 } else {
1878 obs->Reflow(aStart, aEnd);
1879 }
1880 }
1881 return NS_OK;
1882}
1883
1884NS_IMETHODIMPnsresult
1885nsDocShell::GetAllowMetaRedirects(bool* aReturn) {
1886 NS_ENSURE_ARG_POINTER(aReturn)do { if ((__builtin_expect(!!(!(aReturn)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aReturn" ") failed", nullptr
, "./../../../docshell/base/nsDocShell.cpp", 1886); return NS_ERROR_INVALID_POINTER
; } } while (false)
;
1887
1888 *aReturn = mAllowMetaRedirects;
1889 return NS_OK;
1890}
1891
1892NS_IMETHODIMPnsresult
1893nsDocShell::SetAllowMetaRedirects(bool aValue) {
1894 mAllowMetaRedirects = aValue;
1895 return NS_OK;
1896}
1897
1898NS_IMETHODIMPnsresult
1899nsDocShell::GetAllowSubframes(bool* aAllowSubframes) {
1900 NS_ENSURE_ARG_POINTER(aAllowSubframes)do { if ((__builtin_expect(!!(!(aAllowSubframes)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aAllowSubframes" ") failed"
, nullptr, "./../../../docshell/base/nsDocShell.cpp", 1900); return
NS_ERROR_INVALID_POINTER; } } while (false)
;
1901
1902 *aAllowSubframes = mAllowSubframes;
1903 return NS_OK;
1904}
1905
1906NS_IMETHODIMPnsresult
1907nsDocShell::SetAllowSubframes(bool aAllowSubframes) {
1908 mAllowSubframes = aAllowSubframes;
1909 return NS_OK;
1910}
1911
1912NS_IMETHODIMPnsresult
1913nsDocShell::GetAllowImages(bool* aAllowImages) {
1914 NS_ENSURE_ARG_POINTER(aAllowImages)do { if ((__builtin_expect(!!(!(aAllowImages)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aAllowImages" ") failed"
, nullptr, "./../../../docshell/base/nsDocShell.cpp", 1914); return
NS_ERROR_INVALID_POINTER; } } while (false)
;
1915
1916 *aAllowImages = mAllowImages;
1917 return NS_OK;
1918}
1919
1920NS_IMETHODIMPnsresult
1921nsDocShell::SetAllowImages(bool aAllowImages) {
1922 mAllowImages = aAllowImages;
1923 return NS_OK;
1924}
1925
1926NS_IMETHODIMPnsresult
1927nsDocShell::GetAllowMedia(bool* aAllowMedia) {
1928 *aAllowMedia = mAllowMedia;
1929 return NS_OK;
1930}
1931
1932NS_IMETHODIMPnsresult
1933nsDocShell::SetAllowMedia(bool aAllowMedia) {
1934 mAllowMedia = aAllowMedia;
1935
1936 // Mute or unmute audio contexts attached to the inner window.
1937 if (mScriptGlobal) {
1938 if (nsPIDOMWindowInner* innerWin = mScriptGlobal->GetCurrentInnerWindow()) {
1939 if (aAllowMedia) {
1940 innerWin->UnmuteAudioContexts();
1941 } else {
1942 innerWin->MuteAudioContexts();
1943 }
1944 }
1945 }
1946
1947 return NS_OK;
1948}
1949
1950NS_IMETHODIMPnsresult
1951nsDocShell::GetAllowDNSPrefetch(bool* aAllowDNSPrefetch) {
1952 *aAllowDNSPrefetch = mAllowDNSPrefetch;
1953 return NS_OK;
1954}
1955
1956NS_IMETHODIMPnsresult
1957nsDocShell::SetAllowDNSPrefetch(bool aAllowDNSPrefetch) {
1958 mAllowDNSPrefetch = aAllowDNSPrefetch;
1959 return NS_OK;
1960}
1961
1962NS_IMETHODIMPnsresult
1963nsDocShell::GetAllowWindowControl(bool* aAllowWindowControl) {
1964 *aAllowWindowControl = mAllowWindowControl;
1965 return NS_OK;
1966}
1967
1968NS_IMETHODIMPnsresult
1969nsDocShell::SetAllowWindowControl(bool aAllowWindowControl) {
1970 mAllowWindowControl = aAllowWindowControl;
1971 return NS_OK;
1972}
1973
1974NS_IMETHODIMPnsresult
1975nsDocShell::GetAllowContentRetargeting(bool* aAllowContentRetargeting) {
1976 *aAllowContentRetargeting = mBrowsingContext->GetAllowContentRetargeting();
1977 return NS_OK;
1978}
1979
1980NS_IMETHODIMPnsresult
1981nsDocShell::SetAllowContentRetargeting(bool aAllowContentRetargeting) {
1982 BrowsingContext::Transaction txn;
1983 txn.SetAllowContentRetargeting(aAllowContentRetargeting);
1984 txn.SetAllowContentRetargetingOnChildren(aAllowContentRetargeting);
1985 return txn.Commit(mBrowsingContext);
1986}
1987
1988NS_IMETHODIMPnsresult
1989nsDocShell::GetAllowContentRetargetingOnChildren(
1990 bool* aAllowContentRetargetingOnChildren) {
1991 *aAllowContentRetargetingOnChildren =
1992 mBrowsingContext->GetAllowContentRetargetingOnChildren();
1993 return NS_OK;
1994}
1995
1996NS_IMETHODIMPnsresult
1997nsDocShell::SetAllowContentRetargetingOnChildren(
1998 bool aAllowContentRetargetingOnChildren) {
1999 return mBrowsingContext->SetAllowContentRetargetingOnChildren(
2000 aAllowContentRetargetingOnChildren);
2001}
2002
2003NS_IMETHODIMPnsresult
2004nsDocShell::GetMayEnableCharacterEncodingMenu(
2005 bool* aMayEnableCharacterEncodingMenu) {
2006 *aMayEnableCharacterEncodingMenu = false;
2007 if (!mDocumentViewer) {
2008 return NS_OK;
2009 }
2010 Document* doc = mDocumentViewer->GetDocument();
2011 if (!doc) {
2012 return NS_OK;
2013 }
2014 if (doc->WillIgnoreCharsetOverride()) {
2015 return NS_OK;
2016 }
2017
2018 *aMayEnableCharacterEncodingMenu = true;
2019 return NS_OK;
2020}
2021
2022NS_IMETHODIMPnsresult
2023nsDocShell::GetAllDocShellsInSubtree(int32_t aItemType,
2024 DocShellEnumeratorDirection aDirection,
2025 nsTArray<RefPtr<nsIDocShell>>& aResult) {
2026 aResult.Clear();
2027
2028 nsDocShellEnumerator docShellEnum(
2029 (aDirection == ENUMERATE_FORWARDS)
2030 ? nsDocShellEnumerator::EnumerationDirection::Forwards
2031 : nsDocShellEnumerator::EnumerationDirection::Backwards,
2032 aItemType, *this);
2033
2034 nsresult rv = docShellEnum.BuildDocShellArray(aResult);
2035 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2036 return rv;
2037 }
2038
2039 return NS_OK;
2040}
2041
2042NS_IMETHODIMPnsresult
2043nsDocShell::GetAppType(AppType* aAppType) {
2044 *aAppType = mAppType;
2045 return NS_OK;
2046}
2047
2048NS_IMETHODIMPnsresult
2049nsDocShell::SetAppType(AppType aAppType) {
2050 mAppType = aAppType;
2051 return NS_OK;
2052}
2053
2054NS_IMETHODIMPnsresult
2055nsDocShell::GetAllowAuth(bool* aAllowAuth) {
2056 *aAllowAuth = mAllowAuth;
2057 return NS_OK;
2058}
2059
2060NS_IMETHODIMPnsresult
2061nsDocShell::SetAllowAuth(bool aAllowAuth) {
2062 mAllowAuth = aAllowAuth;
2063 return NS_OK;
2064}
2065
2066NS_IMETHODIMPnsresult
2067nsDocShell::GetZoom(float* aZoom) {
2068 NS_ENSURE_ARG_POINTER(aZoom)do { if ((__builtin_expect(!!(!(aZoom)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aZoom" ") failed", nullptr
, "./../../../docshell/base/nsDocShell.cpp", 2068); return NS_ERROR_INVALID_POINTER
; } } while (false)
;
2069 *aZoom = 1.0f;
2070 return NS_OK;
2071}
2072
2073NS_IMETHODIMPnsresult
2074nsDocShell::SetZoom(float aZoom) { return NS_ERROR_NOT_IMPLEMENTED; }
2075
2076NS_IMETHODIMPnsresult
2077nsDocShell::GetBusyFlags(BusyFlags* aBusyFlags) {
2078 NS_ENSURE_ARG_POINTER(aBusyFlags)do { if ((__builtin_expect(!!(!(aBusyFlags)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aBusyFlags" ") failed",
nullptr, "./../../../docshell/base/nsDocShell.cpp", 2078); return
NS_ERROR_INVALID_POINTER; } } while (false)
;
2079
2080 *aBusyFlags = mBusyFlags;
2081 return NS_OK;
2082}
2083
2084NS_IMETHODIMPnsresult
2085nsDocShell::GetLoadURIDelegate(nsILoadURIDelegate** aLoadURIDelegate) {
2086 nsCOMPtr<nsILoadURIDelegate> delegate = GetLoadURIDelegate();
2087 delegate.forget(aLoadURIDelegate);
2088 return NS_OK;
2089}
2090
2091already_AddRefed<nsILoadURIDelegate> nsDocShell::GetLoadURIDelegate() {
2092 if (nsCOMPtr<nsILoadURIDelegate> result =
2093 do_QueryActor("LoadURIDelegate", GetDocument())) {
2094 return result.forget();
2095 }
2096
2097 return nullptr;
2098}
2099
2100NS_IMETHODIMPnsresult
2101nsDocShell::GetUseErrorPages(bool* aUseErrorPages) {
2102 *aUseErrorPages = mBrowsingContext->GetUseErrorPages();
2103 return NS_OK;
2104}
2105
2106NS_IMETHODIMPnsresult
2107nsDocShell::SetUseErrorPages(bool aUseErrorPages) {
2108 return mBrowsingContext->SetUseErrorPages(aUseErrorPages);
2109}
2110
2111NS_IMETHODIMPnsresult
2112nsDocShell::GetPreviousEntryIndex(int32_t* aPreviousEntryIndex) {
2113 *aPreviousEntryIndex = mPreviousEntryIndex;
2114 return NS_OK;
2115}
2116
2117NS_IMETHODIMPnsresult
2118nsDocShell::GetLoadedEntryIndex(int32_t* aLoadedEntryIndex) {
2119 *aLoadedEntryIndex = mLoadedEntryIndex;
2120 return NS_OK;
2121}
2122
2123NS_IMETHODIMPnsresult
2124nsDocShell::HistoryPurged(int32_t aNumEntries) {
2125 // These indices are used for fastback cache eviction, to determine
2126 // which session history entries are candidates for content viewer
2127 // eviction. We need to adjust by the number of entries that we
2128 // just purged from history, so that we look at the right session history
2129 // entries during eviction.
2130 mPreviousEntryIndex = std::max(-1, mPreviousEntryIndex - aNumEntries);
2131 mLoadedEntryIndex = std::max(0, mLoadedEntryIndex - aNumEntries);
2132
2133 for (auto* child : mChildList.ForwardRange()) {
2134 nsCOMPtr<nsIDocShell> shell = do_QueryObject(child);
2135 if (shell) {
2136 shell->HistoryPurged(aNumEntries);
2137 }
2138 }
2139
2140 return NS_OK;
2141}
2142
2143nsresult nsDocShell::HistoryEntryRemoved(int32_t aIndex) {
2144 // These indices are used for fastback cache eviction, to determine
2145 // which session history entries are candidates for content viewer
2146 // eviction. We need to adjust by the number of entries that we
2147 // just purged from history, so that we look at the right session history
2148 // entries during eviction.
2149 if (aIndex == mPreviousEntryIndex) {
2150 mPreviousEntryIndex = -1;
2151 } else if (aIndex < mPreviousEntryIndex) {
2152 --mPreviousEntryIndex;
2153 }
2154 if (mLoadedEntryIndex == aIndex) {
2155 mLoadedEntryIndex = 0;
2156 } else if (aIndex < mLoadedEntryIndex) {
2157 --mLoadedEntryIndex;
2158 }
2159
2160 for (auto* child : mChildList.ForwardRange()) {
2161 nsCOMPtr<nsIDocShell> shell = do_QueryObject(child);
2162 if (shell) {
2163 static_cast<nsDocShell*>(shell.get())->HistoryEntryRemoved(aIndex);
2164 }
2165 }
2166
2167 return NS_OK;
2168}
2169
2170nsresult nsDocShell::Now(DOMHighResTimeStamp* aWhen) {
2171 *aWhen = (TimeStamp::Now() - TimeStamp::ProcessCreation()).ToMilliseconds();
2172 return NS_OK;
2173}
2174
2175NS_IMETHODIMPnsresult
2176nsDocShell::SetWindowDraggingAllowed(bool aValue) {
2177 RefPtr<nsDocShell> parent;
2178 if (!aValue && mItemType == typeChrome &&
2179 !(parent = GetInProcessParentDocshell())) {
2180 // Window dragging is always allowed for top level
2181 // chrome docshells.
2182 return NS_ERROR_FAILURE;
2183 }
2184 mWindowDraggingAllowed = aValue;
2185 return NS_OK;
2186}
2187
2188NS_IMETHODIMPnsresult
2189nsDocShell::GetWindowDraggingAllowed(bool* aValue) {
2190 // window dragging regions in CSS (-moz-window-drag:drag)
2191 // can be slow. Default behavior is to only allow it for
2192 // chrome top level windows.
2193 RefPtr<nsDocShell> parent;
2194 if (mItemType == typeChrome && !(parent = GetInProcessParentDocshell())) {
2195 // Top level chrome window
2196 *aValue = true;
2197 } else {
2198 *aValue = mWindowDraggingAllowed;
2199 }
2200 return NS_OK;
2201}
2202
2203NS_IMETHODIMPnsresult
2204nsDocShell::GetCurrentDocumentChannel(nsIChannel** aResult) {
2205 NS_IF_ADDREF(*aResult = GetCurrentDocChannel())ns_if_addref(*aResult = GetCurrentDocChannel());
2206 return NS_OK;
2207}
2208
2209nsIChannel* nsDocShell::GetCurrentDocChannel() {
2210 if (mDocumentViewer) {
2211 Document* doc = mDocumentViewer->GetDocument();
2212 if (doc) {
2213 return doc->GetChannel();
2214 }
2215 }
2216 return nullptr;
2217}
2218
2219NS_IMETHODIMPnsresult
2220nsDocShell::AddWeakScrollObserver(nsIScrollObserver* aObserver) {
2221 nsWeakPtr weakObs = do_GetWeakReference(aObserver);
2222 if (!weakObs) {
2223 return NS_ERROR_FAILURE;
2224 }
2225 mScrollObservers.AppendElement(weakObs);
2226 return NS_OK;
2227}
2228
2229NS_IMETHODIMPnsresult
2230nsDocShell::RemoveWeakScrollObserver(nsIScrollObserver* aObserver) {
2231 nsWeakPtr obs = do_GetWeakReference(aObserver);
2232 return mScrollObservers.RemoveElement(obs) ? NS_OK : NS_ERROR_FAILURE;
2233}
2234
2235void nsDocShell::NotifyAsyncPanZoomStarted() {
2236 nsTObserverArray<nsWeakPtr>::ForwardIterator iter(mScrollObservers);
2237 while (iter.HasMore()) {
2238 nsWeakPtr ref = iter.GetNext();
2239 nsCOMPtr<nsIScrollObserver> obs = do_QueryReferent(ref);
2240 if (obs) {
2241 obs->AsyncPanZoomStarted();
2242 } else {
2243 iter.Remove();
2244 }
2245 }
2246}
2247
2248void nsDocShell::NotifyAsyncPanZoomStopped() {
2249 nsTObserverArray<nsWeakPtr>::ForwardIterator iter(mScrollObservers);
2250 while (iter.HasMore()) {
2251 nsWeakPtr ref = iter.GetNext();
2252 nsCOMPtr<nsIScrollObserver> obs = do_QueryReferent(ref);
2253 if (obs) {
2254 obs->AsyncPanZoomStopped();
2255 } else {
2256 iter.Remove();
2257 }
2258 }
2259}
2260
2261NS_IMETHODIMPnsresult
2262nsDocShell::NotifyScrollObservers() {
2263 nsTObserverArray<nsWeakPtr>::ForwardIterator iter(mScrollObservers);
2264 while (iter.HasMore()) {
2265 nsWeakPtr ref = iter.GetNext();
2266 nsCOMPtr<nsIScrollObserver> obs = do_QueryReferent(ref);
2267 if (obs) {
2268 obs->ScrollPositionChanged();
2269 } else {
2270 iter.Remove();
2271 }
2272 }
2273 return NS_OK;
2274}
2275
2276//*****************************************************************************
2277// nsDocShell::nsIDocShellTreeItem
2278//*****************************************************************************
2279
2280NS_IMETHODIMPnsresult
2281nsDocShell::GetName(nsAString& aName) {
2282 aName = mBrowsingContext->Name();
2283 return NS_OK;
2284}
2285
2286NS_IMETHODIMPnsresult
2287nsDocShell::SetName(const nsAString& aName) {
2288 return mBrowsingContext->SetName(aName);
2289}
2290
2291NS_IMETHODIMPnsresult
2292nsDocShell::NameEquals(const nsAString& aName, bool* aResult) {
2293 NS_ENSURE_ARG_POINTER(aResult)do { if ((__builtin_expect(!!(!(aResult)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aResult" ") failed", nullptr
, "./../../../docshell/base/nsDocShell.cpp", 2293); return NS_ERROR_INVALID_POINTER
; } } while (false)
;
2294 *aResult = mBrowsingContext->NameEquals(aName);
2295 return NS_OK;
2296}
2297
2298NS_IMETHODIMPnsresult
2299nsDocShell::GetCustomUserAgent(nsAString& aCustomUserAgent) {
2300 mBrowsingContext->GetCustomUserAgent(aCustomUserAgent);
2301 return NS_OK;
2302}
2303
2304NS_IMETHODIMPnsresult
2305nsDocShell::SetCustomUserAgent(const nsAString& aCustomUserAgent) {
2306 if (mWillChangeProcess) {
2307 NS_WARNING("SetCustomUserAgent: Process is changing. Ignoring set")NS_DebugBreak(NS_DEBUG_WARNING, "SetCustomUserAgent: Process is changing. Ignoring set"
, nullptr, "./../../../docshell/base/nsDocShell.cpp", 2307)
;
2308 return NS_ERROR_FAILURE;
2309 }
2310
2311 return mBrowsingContext->SetCustomUserAgent(aCustomUserAgent);
2312}
2313
2314NS_IMETHODIMPnsresult
2315nsDocShell::ClearCachedPlatform() {
2316 nsCOMPtr<nsPIDOMWindowInner> win =
2317 mScriptGlobal ? mScriptGlobal->GetCurrentInnerWindow() : nullptr;
2318 if (win) {
2319 Navigator* navigator = win->Navigator();
2320 if (navigator) {
2321 navigator->ClearPlatformCache();
2322 }
2323 }
2324
2325 return NS_OK;
2326}
2327
2328NS_IMETHODIMPnsresult
2329nsDocShell::ClearCachedUserAgent() {
2330 nsCOMPtr<nsPIDOMWindowInner> win =
2331 mScriptGlobal ? mScriptGlobal->GetCurrentInnerWindow() : nullptr;
2332 if (win) {
2333 Navigator* navigator = win->Navigator();
2334 if (navigator) {
2335 navigator->ClearUserAgentCache();
2336 }
2337 }
2338
2339 return NS_OK;
2340}
2341
2342/* virtual */
2343int32_t nsDocShell::ItemType() { return mItemType; }
2344
2345NS_IMETHODIMPnsresult
2346nsDocShell::GetItemType(int32_t* aItemType) {
2347 NS_ENSURE_ARG_POINTER(aItemType)do { if ((__builtin_expect(!!(!(aItemType)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aItemType" ") failed", nullptr
, "./../../../docshell/base/nsDocShell.cpp", 2347); return NS_ERROR_INVALID_POINTER
; } } while (false)
;
2348
2349 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"
, "./../../../docshell/base/nsDocShell.cpp", 2350); AnnotateMozCrashReason
("MOZ_DIAGNOSTIC_ASSERT" "(" "(mBrowsingContext->IsContent() ? typeContent : typeChrome) == mItemType"
")"); do { MOZ_CrashSequence(__null, 2350); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2350 (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"
, "./../../../docshell/base/nsDocShell.cpp", 2350); AnnotateMozCrashReason
("MOZ_DIAGNOSTIC_ASSERT" "(" "(mBrowsingContext->IsContent() ? typeContent : typeChrome) == mItemType"
")"); do { MOZ_CrashSequence(__null, 2350); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2351 *aItemType = mItemType;
2352 return NS_OK;
2353}
2354
2355NS_IMETHODIMPnsresult
2356nsDocShell::GetInProcessParent(nsIDocShellTreeItem** aParent) {
2357 if (!mParent) {
2358 *aParent = nullptr;
2359 } else {
2360 CallQueryInterface(mParent, aParent);
2361 }
2362 // Note that in the case when the parent is not an nsIDocShellTreeItem we
2363 // don't want to throw; we just want to return null.
2364 return NS_OK;
2365}
2366
2367// With Fission, related nsDocShell objects may exist in a different process. In
2368// that case, this method will return `nullptr`, despite a parent nsDocShell
2369// object existing.
2370//
2371// Prefer using `BrowsingContext::Parent()`, which will succeed even if the
2372// parent entry is not in the current process, and handle the case where the
2373// parent nsDocShell is inaccessible.
2374already_AddRefed<nsDocShell> nsDocShell::GetInProcessParentDocshell() {
2375 nsCOMPtr<nsIDocShell> docshell = do_QueryInterface(GetAsSupports(mParent));
2376 return docshell.forget().downcast<nsDocShell>();
2377}
2378
2379void nsDocShell::MaybeCreateInitialClientSource(nsIPrincipal* aPrincipal) {
2380 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"
, "./../../../docshell/base/nsDocShell.cpp", 2380); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!mIsBeingDestroyed" ")"); do { MOZ_CrashSequence
(__null, 2380); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
2381
2382 // If there is an existing document then there is no need to create
2383 // a client for a future initial about:blank document.
2384 if (mScriptGlobal && mScriptGlobal->GetCurrentInnerWindow() &&
2385 mScriptGlobal->GetCurrentInnerWindow()->GetExtantDoc()) {
2386 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()"
, "./../../../docshell/base/nsDocShell.cpp", 2387); AnnotateMozCrashReason
("MOZ_DIAGNOSTIC_ASSERT" "(" "mScriptGlobal->GetCurrentInnerWindow()->GetClientInfo().isSome()"
")"); do { MOZ_CrashSequence(__null, 2387); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2387 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()"
, "./../../../docshell/base/nsDocShell.cpp", 2387); AnnotateMozCrashReason
("MOZ_DIAGNOSTIC_ASSERT" "(" "mScriptGlobal->GetCurrentInnerWindow()->GetClientInfo().isSome()"
")"); do { MOZ_CrashSequence(__null, 2387); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2388 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"
, "./../../../docshell/base/nsDocShell.cpp", 2388); AnnotateMozCrashReason
("MOZ_DIAGNOSTIC_ASSERT" "(" "!mInitialClientSource" ")"); do
{ MOZ_CrashSequence(__null, 2388); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
2389 return;
2390 }
2391
2392 // Don't recreate the initial client source. We call this multiple times
2393 // when DoChannelLoad() is called before CreateAboutBlankDocumentViewer.
2394 if (mInitialClientSource) {
2395 return;
2396 }
2397
2398 // Don't pre-allocate the client when we are sandboxed. The inherited
2399 // principal does not take sandboxing into account.
2400 // TODO: Refactor sandboxing principal code out so we can use it here.
2401 if (!aPrincipal && mBrowsingContext->GetSandboxFlags()) {
2402 return;
2403 }
2404
2405 // We cannot get inherited foreign partitioned principal here. Instead, we
2406 // directly check which principal we want to inherit for the service worker.
2407 nsIPrincipal* principal =
2408 aPrincipal
2409 ? aPrincipal
2410 : GetInheritedPrincipal(
2411 false, StoragePrincipalHelper::
2412 ShouldUsePartitionPrincipalForServiceWorker(this));
2413
2414 // Sometimes there is no principal available when we are called from
2415 // CreateAboutBlankDocumentViewer. For example, sometimes the principal
2416 // is only extracted from the load context after the document is created
2417 // in Document::ResetToURI(). Ideally we would do something similar
2418 // here, but for now lets just avoid the issue by not preallocating the
2419 // client.
2420 if (!principal) {
2421 return;
2422 }
2423
2424 nsCOMPtr<nsPIDOMWindowOuter> win = GetWindow();
2425 if (!win) {
2426 return;
2427 }
2428
2429 mInitialClientSource = ClientManager::CreateSource(
2430 ClientType::Window, GetMainThreadSerialEventTarget(), principal);
2431 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"
, "./../../../docshell/base/nsDocShell.cpp", 2431); AnnotateMozCrashReason
("MOZ_DIAGNOSTIC_ASSERT" "(" "mInitialClientSource" ")"); do {
MOZ_CrashSequence(__null, 2431); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
2432
2433 // Mark the initial client as execution ready, but owned by the docshell.
2434 // If the client is actually used this will cause ClientSource to force
2435 // the creation of the initial about:blank by calling
2436 // nsDocShell::GetDocument().
2437 mInitialClientSource->DocShellExecutionReady(this);
2438
2439 // Next, check to see if the parent is controlled.
2440 MaybeInheritController(mInitialClientSource.get(), principal);
2441}
2442
2443void VerifyClientPrincipalInfosMatch(
2444 const mozilla::ipc::PrincipalInfo& aLeft,
2445 const mozilla::ipc::PrincipalInfo& aRight) {
2446 // Inheriting a controller when the principals don't match would cause a
2447 // crash. Let's do the checks earlier to crash here already instead of
2448 // ClientSource::SetController. And assert each condition separately. See bug
2449 // 1880012.
2450 MOZ_RELEASE_ASSERT(aLeft.type() == aRight.type())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aLeft.type() == aRight.type())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aLeft.type() == aRight.type(
)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("aLeft.type() == aRight.type()", "./../../../docshell/base/nsDocShell.cpp"
, 2450); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "aLeft.type() == aRight.type()"
")"); do { MOZ_CrashSequence(__null, 2450); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2451
2452 switch (aLeft.type()) {
2453 case mozilla::ipc::PrincipalInfo::TContentPrincipalInfo: {
2454 const mozilla::ipc::ContentPrincipalInfo& leftContent =
2455 aLeft.get_ContentPrincipalInfo();
2456 const mozilla::ipc::ContentPrincipalInfo& rightContent =
2457 aRight.get_ContentPrincipalInfo();
2458 {
2459 // The most likely mismatch is the foreign bit in the partition key.
2460 // See bug 2006265 and 2013379.
2461 nsAutoString scheme;
2462 nsAutoString baseDomain;
2463 int32_t port;
2464 bool leftForeignBit;
2465 bool rightForeignBit;
2466 OriginAttributes::ParsePartitionKey(leftContent.attrs().mPartitionKey,
2467 scheme, baseDomain, port,
2468 leftForeignBit);
2469 OriginAttributes::ParsePartitionKey(rightContent.attrs().mPartitionKey,
2470 scheme, baseDomain, port,
2471 rightForeignBit);
2472 MOZ_RELEASE_ASSERT(leftForeignBit == rightForeignBit)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(leftForeignBit == rightForeignBit)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(leftForeignBit == rightForeignBit
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"leftForeignBit == rightForeignBit", "./../../../docshell/base/nsDocShell.cpp"
, 2472); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "leftForeignBit == rightForeignBit"
")"); do { MOZ_CrashSequence(__null, 2472); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2473 }
2474 MOZ_RELEASE_ASSERT(leftContent.attrs() == rightContent.attrs())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(leftContent.attrs() == rightContent.attrs())>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(leftContent.attrs() == rightContent.attrs()))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("leftContent.attrs() == rightContent.attrs()"
, "./../../../docshell/base/nsDocShell.cpp", 2474); AnnotateMozCrashReason
("MOZ_RELEASE_ASSERT" "(" "leftContent.attrs() == rightContent.attrs()"
")"); do { MOZ_CrashSequence(__null, 2474); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2475 MOZ_RELEASE_ASSERT(leftContent.originNoSuffix() ==do { static_assert( mozilla::detail::AssertionConditionType<
decltype(leftContent.originNoSuffix() == rightContent.originNoSuffix
())>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(leftContent.originNoSuffix() == rightContent.originNoSuffix
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("leftContent.originNoSuffix() == rightContent.originNoSuffix()"
, "./../../../docshell/base/nsDocShell.cpp", 2476); AnnotateMozCrashReason
("MOZ_RELEASE_ASSERT" "(" "leftContent.originNoSuffix() == rightContent.originNoSuffix()"
")"); do { MOZ_CrashSequence(__null, 2476); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2476 rightContent.originNoSuffix())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(leftContent.originNoSuffix() == rightContent.originNoSuffix
())>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(leftContent.originNoSuffix() == rightContent.originNoSuffix
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("leftContent.originNoSuffix() == rightContent.originNoSuffix()"
, "./../../../docshell/base/nsDocShell.cpp", 2476); AnnotateMozCrashReason
("MOZ_RELEASE_ASSERT" "(" "leftContent.originNoSuffix() == rightContent.originNoSuffix()"
")"); do { MOZ_CrashSequence(__null, 2476); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2477 return;
2478 }
2479 case mozilla::ipc::PrincipalInfo::TNullPrincipalInfo: {
2480 // null principal never matches
2481 MOZ_RELEASE_ASSERT(false, "Clients have null principals")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "Clients have null principals"
")", "./../../../docshell/base/nsDocShell.cpp", 2481); AnnotateMozCrashReason
("MOZ_RELEASE_ASSERT" "(" "false" ") (" "Clients have null principals"
")"); do { MOZ_CrashSequence(__null, 2481); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2482 return;
2483 }
2484 default: {
2485 break;
2486 }
2487 }
2488}
2489
2490void nsDocShell::MaybeInheritController(
2491 mozilla::dom::ClientSource* aClientSource, nsIPrincipal* aPrincipal) {
2492 nsCOMPtr<nsIDocShell> parent = GetInProcessParentDocshell();
2493 nsPIDOMWindowOuter* parentOuter = parent ? parent->GetWindow() : nullptr;
2494 nsPIDOMWindowInner* parentInner =
2495 parentOuter ? parentOuter->GetCurrentInnerWindow() : nullptr;
2496 if (!parentInner) {
2497 return;
2498 }
2499
2500 nsCOMPtr<nsIURI> uri;
2501 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))"
, "./../../../docshell/base/nsDocShell.cpp", 2501); AnnotateMozCrashReason
("MOZ_CRASH(" "NS_SUCCEEDED(NS_NewURI(getter_AddRefs(uri), \"about:blank\"_ns))"
")"); do { MOZ_CrashSequence(__null, 2501); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
;
2502
2503 // We're done if there is no parent controller or if this docshell
2504 // is not permitted to control for some reason.
2505 Maybe<ServiceWorkerDescriptor> controller(parentInner->GetController());
2506 if (controller.isNothing() ||
2507 !ServiceWorkerAllowedToControlWindow(aPrincipal, uri)) {
2508 return;
2509 }
2510
2511 VerifyClientPrincipalInfosMatch(aClientSource->Info().PrincipalInfo(),
2512 controller->PrincipalInfo());
2513 aClientSource->InheritController(controller.ref());
2514}
2515
2516Maybe<ClientInfo> nsDocShell::GetInitialClientInfo() const {
2517 if (mInitialClientSource) {
2518 Maybe<ClientInfo> result;
2519 result.emplace(mInitialClientSource->Info());
2520 return result;
2521 }
2522
2523 nsPIDOMWindowInner* innerWindow =
2524 mScriptGlobal ? mScriptGlobal->GetCurrentInnerWindow() : nullptr;
2525 Document* doc = innerWindow ? innerWindow->GetExtantDoc() : nullptr;
2526
2527 if (!doc || !doc->IsUncommittedInitialDocument()) {
2528 // We won't reuse the inner window so let the channel determine one
2529 return Maybe<ClientInfo>();
2530 }
2531
2532 return innerWindow->GetClientInfo();
2533}
2534
2535nsresult nsDocShell::SetDocLoaderParent(nsDocLoader* aParent) {
2536 bool wasFrame = IsSubframe();
2537
2538 nsresult rv = nsDocLoader::SetDocLoaderParent(aParent);
2539 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, "./../../../docshell/base/nsDocShell.cpp"
, 2539); return rv; } } while (false)
;
2540
2541 nsCOMPtr<nsISupportsPriority> priorityGroup = do_QueryInterface(mLoadGroup);
2542 if (wasFrame != IsSubframe() && priorityGroup) {
2543 priorityGroup->AdjustPriority(wasFrame ? -1 : 1);
2544 }
2545
2546 // Curse ambiguous nsISupports inheritance!
2547 nsISupports* parent = GetAsSupports(aParent);
2548
2549 // If parent is another docshell, we inherit all their flags for
2550 // allowing plugins, scripting etc.
2551 bool value;
2552 nsCOMPtr<nsIDocShell> parentAsDocShell(do_QueryInterface(parent));
2553
2554 if (parentAsDocShell) {
2555 if (mAllowMetaRedirects &&
2556 NS_SUCCEEDED(parentAsDocShell->GetAllowMetaRedirects(&value))((bool)(__builtin_expect(!!(!NS_FAILED_impl(parentAsDocShell->
GetAllowMetaRedirects(&value))), 1)))
) {
2557 SetAllowMetaRedirects(value);
2558 }
2559 if (mAllowSubframes &&
2560 NS_SUCCEEDED(parentAsDocShell->GetAllowSubframes(&value))((bool)(__builtin_expect(!!(!NS_FAILED_impl(parentAsDocShell->
GetAllowSubframes(&value))), 1)))
) {
2561 SetAllowSubframes(value);
2562 }
2563 if (mAllowImages &&
2564 NS_SUCCEEDED(parentAsDocShell->GetAllowImages(&value))((bool)(__builtin_expect(!!(!NS_FAILED_impl(parentAsDocShell->
GetAllowImages(&value))), 1)))
) {
2565 SetAllowImages(value);
2566 }
2567 SetAllowMedia(parentAsDocShell->GetAllowMedia() && mAllowMedia);
2568 if (mAllowWindowControl &&
2569 NS_SUCCEEDED(parentAsDocShell->GetAllowWindowControl(&value))((bool)(__builtin_expect(!!(!NS_FAILED_impl(parentAsDocShell->
GetAllowWindowControl(&value))), 1)))
) {
2570 SetAllowWindowControl(value);
2571 }
2572 if (NS_FAILED(parentAsDocShell->GetAllowDNSPrefetch(&value))((bool)(__builtin_expect(!!(NS_FAILED_impl(parentAsDocShell->
GetAllowDNSPrefetch(&value))), 0)))
) {
2573 value = false;
2574 }
2575 SetAllowDNSPrefetch(mAllowDNSPrefetch && value);
2576 }
2577
2578 nsCOMPtr<nsIURIContentListener> parentURIListener(do_GetInterface(parent));
2579 if (parentURIListener) {
2580 mContentListener->SetParentContentListener(parentURIListener);
2581 }
2582
2583 return NS_OK;
2584}
2585
2586void nsDocShell::MaybeRestoreWindowName() {
2587 if (!StaticPrefs::privacy_window_name_update_enabled()) {
2588 return;
2589 }
2590
2591 // We only restore window.name for the top-level content.
2592 if (!mBrowsingContext->IsTopContent()) {
2593 return;
2594 }
2595
2596 nsAutoString name;
2597
2598 // Following implements https://html.spec.whatwg.org/#history-traversal:
2599 // Step 4.4. Check if the loading entry has a name.
2600
2601 if (mLoadingEntry) {
2602 name = mLoadingEntry->mInfo.GetName();
2603 }
2604
2605 if (name.IsEmpty()) {
2606 return;
2607 }
2608
2609 // Step 4.4.1. Set the name to the browsing context.
2610 (void)mBrowsingContext->SetName(name);
2611
2612 // Step 4.4.2. Clear the name of all entries that are contiguous and
2613 // same-origin with the loading entry.
2614 if (mLoadingEntry) {
2615 // Clear the name of the session entry in the child side. For parent side,
2616 // the clearing will be done when we commit the history to the parent.
2617 mLoadingEntry->mInfo.SetName(EmptyString());
2618 }
2619}
2620
2621void nsDocShell::StoreWindowNameToSHEntries() {
2622 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()", "./../../../docshell/base/nsDocShell.cpp"
, 2622); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mBrowsingContext->IsTopContent()"
")"); do { MOZ_CrashSequence(__null, 2622); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2623
2624 nsAutoString name;
2625 mBrowsingContext->GetName(name);
2626
2627 if (XRE_IsParentProcess()) {
2628 SessionHistoryEntry* entry =
2629 mBrowsingContext->Canonical()->GetActiveSessionHistoryEntry();
2630 if (entry) {
2631 nsSHistory::WalkContiguousEntries(
2632 entry, [&](SessionHistoryEntry* aEntry) { aEntry->SetName(name); });
2633 }
2634 } else {
2635 // Ask parent process to store the name in entries.
2636 (void)ContentChild::GetSingleton()
2637 ->SendSessionHistoryEntryStoreWindowNameInContiguousEntries(
2638 mBrowsingContext, name);
2639 }
2640}
2641
2642NS_IMETHODIMPnsresult
2643nsDocShell::GetInProcessSameTypeParent(nsIDocShellTreeItem** aParent) {
2644 if (BrowsingContext* parentBC = mBrowsingContext->GetParent()) {
2645 *aParent = do_AddRef(parentBC->GetDocShell()).take();
2646 }
2647 return NS_OK;
2648}
2649
2650NS_IMETHODIMPnsresult
2651nsDocShell::GetInProcessRootTreeItem(nsIDocShellTreeItem** aRootTreeItem) {
2652 NS_ENSURE_ARG_POINTER(aRootTreeItem)do { if ((__builtin_expect(!!(!(aRootTreeItem)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aRootTreeItem" ") failed"
, nullptr, "./../../../docshell/base/nsDocShell.cpp", 2652); return
NS_ERROR_INVALID_POINTER; } } while (false)
;
2653
2654 RefPtr<nsDocShell> root = this;
2655 RefPtr<nsDocShell> parent = root->GetInProcessParentDocshell();
2656 while (parent) {
2657 root = parent;
2658 parent = root->GetInProcessParentDocshell();
2659 }
2660
2661 root.forget(aRootTreeItem);
2662 return NS_OK;
2663}
2664
2665NS_IMETHODIMPnsresult
2666nsDocShell::GetInProcessSameTypeRootTreeItem(
2667 nsIDocShellTreeItem** aRootTreeItem) {
2668 NS_ENSURE_ARG_POINTER(aRootTreeItem)do { if ((__builtin_expect(!!(!(aRootTreeItem)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aRootTreeItem" ") failed"
, nullptr, "./../../../docshell/base/nsDocShell.cpp", 2668); return
NS_ERROR_INVALID_POINTER; } } while (false)
;
2669 *aRootTreeItem = static_cast<nsIDocShellTreeItem*>(this);
2670
2671 nsCOMPtr<nsIDocShellTreeItem> parent;
2672 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, "./../../../docshell/base/nsDocShell.cpp"
, 2673); return NS_ERROR_FAILURE; } } while (false)
2673 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, "./../../../docshell/base/nsDocShell.cpp"
, 2673); return NS_ERROR_FAILURE; } } while (false)
;
2674 while (parent) {
2675 *aRootTreeItem = parent;
2676 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, "./../../../docshell/base/nsDocShell.cpp"
, 2678); return NS_ERROR_FAILURE; } } while (false)
2677 (*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, "./../../../docshell/base/nsDocShell.cpp"
, 2678); return NS_ERROR_FAILURE; } } while (false)
2678 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, "./../../../docshell/base/nsDocShell.cpp"
, 2678); return NS_ERROR_FAILURE; } } while (false)
;
2679 }
2680 NS_ADDREF(*aRootTreeItem)(*aRootTreeItem)->AddRef();
2681 return NS_OK;
2682}
2683
2684NS_IMETHODIMPnsresult
2685nsDocShell::GetTreeOwner(nsIDocShellTreeOwner** aTreeOwner) {
2686 NS_ENSURE_ARG_POINTER(aTreeOwner)do { if ((__builtin_expect(!!(!(aTreeOwner)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aTreeOwner" ") failed",
nullptr, "./../../../docshell/base/nsDocShell.cpp", 2686); return
NS_ERROR_INVALID_POINTER; } } while (false)
;
2687
2688 *aTreeOwner = mTreeOwner;
2689 NS_IF_ADDREF(*aTreeOwner)ns_if_addref(*aTreeOwner);
2690 return NS_OK;
2691}
2692
2693NS_IMETHODIMPnsresult
2694nsDocShell::SetTreeOwner(nsIDocShellTreeOwner* aTreeOwner) {
2695 if (mIsBeingDestroyed && aTreeOwner) {
2696 return NS_ERROR_FAILURE;
2697 }
2698
2699 // Don't automatically set the progress based on the tree owner for frames
2700 if (!IsSubframe()) {
2701 nsCOMPtr<nsIWebProgress> webProgress =
2702 do_QueryInterface(GetAsSupports(this));
2703
2704 if (webProgress) {
2705 nsCOMPtr<nsIWebProgressListener> oldListener =
2706 do_QueryInterface(mTreeOwner);
2707 nsCOMPtr<nsIWebProgressListener> newListener =
2708 do_QueryInterface(aTreeOwner);
2709
2710 if (oldListener) {
2711 webProgress->RemoveProgressListener(oldListener);
2712 }
2713
2714 if (newListener) {
2715 webProgress->AddProgressListener(newListener,
2716 nsIWebProgress::NOTIFY_ALL);
2717 }
2718 }
2719 }
2720
2721 mTreeOwner = aTreeOwner; // Weak reference per API
2722
2723 for (auto* childDocLoader : mChildList.ForwardRange()) {
2724 nsCOMPtr<nsIDocShellTreeItem> child = do_QueryObject(childDocLoader);
2725 NS_ENSURE_TRUE(child, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(child)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "child" ") failed", nullptr
, "./../../../docshell/base/nsDocShell.cpp", 2725); return NS_ERROR_FAILURE
; } } while (false)
;
2726
2727 if (child->ItemType() == mItemType) {
2728 child->SetTreeOwner(aTreeOwner);
2729 }
2730 }
2731
2732 // If we're in the content process and have had a TreeOwner set on us, extract
2733 // our BrowserChild actor. If we've already had our BrowserChild set, assert
2734 // that it hasn't changed.
2735 if (mTreeOwner && XRE_IsContentProcess()) {
2736 nsCOMPtr<nsIBrowserChild> newBrowserChild = do_GetInterface(mTreeOwner);
2737 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!" ")",
"./../../../docshell/base/nsDocShell.cpp", 2738); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "newBrowserChild" ") (" "No BrowserChild actor for tree owner in Content!"
")"); do { MOZ_CrashSequence(__null, 2738); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2738 "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!" ")",
"./../../../docshell/base/nsDocShell.cpp", 2738); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "newBrowserChild" ") (" "No BrowserChild actor for tree owner in Content!"
")"); do { MOZ_CrashSequence(__null, 2738); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2739
2740 if (mBrowserChild) {
2741 nsCOMPtr<nsIBrowserChild> oldBrowserChild =
2742 do_QueryReferent(mBrowserChild);
2743 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!"
")", "./../../../docshell/base/nsDocShell.cpp", 2745); AnnotateMozCrashReason
("MOZ_RELEASE_ASSERT" "(" "oldBrowserChild == newBrowserChild"
") (" "Cannot change BrowserChild during nsDocShell lifetime!"
")"); do { MOZ_CrashSequence(__null, 2745); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2744 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!"
")", "./../../../docshell/base/nsDocShell.cpp", 2745); AnnotateMozCrashReason
("MOZ_RELEASE_ASSERT" "(" "oldBrowserChild == newBrowserChild"
") (" "Cannot change BrowserChild during nsDocShell lifetime!"
")"); do { MOZ_CrashSequence(__null, 2745); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2745 "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!"
")", "./../../../docshell/base/nsDocShell.cpp", 2745); AnnotateMozCrashReason
("MOZ_RELEASE_ASSERT" "(" "oldBrowserChild == newBrowserChild"
") (" "Cannot change BrowserChild during nsDocShell lifetime!"
")"); do { MOZ_CrashSequence(__null, 2745); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2746 } else {
2747 mBrowserChild = do_GetWeakReference(newBrowserChild);
2748 }
2749 }
2750
2751 return NS_OK;
2752}
2753
2754NS_IMETHODIMPnsresult
2755nsDocShell::GetHistoryID(nsID& aID) {
2756 aID = mBrowsingContext->GetHistoryID();
2757 return NS_OK;
2758}
2759
2760const nsID& nsDocShell::HistoryID() { return mBrowsingContext->GetHistoryID(); }
2761
2762NS_IMETHODIMPnsresult
2763nsDocShell::GetIsInUnload(bool* aIsInUnload) {
2764 *aIsInUnload = mFiredUnloadEvent;
2765 return NS_OK;
2766}
2767
2768NS_IMETHODIMPnsresult
2769nsDocShell::GetInProcessChildCount(int32_t* aChildCount) {
2770 NS_ENSURE_ARG_POINTER(aChildCount)do { if ((__builtin_expect(!!(!(aChildCount)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aChildCount" ") failed"
, nullptr, "./../../../docshell/base/nsDocShell.cpp", 2770); return
NS_ERROR_INVALID_POINTER; } } while (false)
;
2771 *aChildCount = mChildList.Length();
2772 return NS_OK;
2773}
2774
2775NS_IMETHODIMPnsresult
2776nsDocShell::AddChild(nsIDocShellTreeItem* aChild) {
2777 NS_ENSURE_ARG_POINTER(aChild)do { if ((__builtin_expect(!!(!(aChild)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aChild" ") failed", nullptr
, "./../../../docshell/base/nsDocShell.cpp", 2777); return NS_ERROR_INVALID_POINTER
; } } while (false)
;
2778
2779 RefPtr<nsDocLoader> childAsDocLoader = GetAsDocLoader(aChild);
2780 NS_ENSURE_TRUE(childAsDocLoader, NS_ERROR_UNEXPECTED)do { if ((__builtin_expect(!!(!(childAsDocLoader)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "childAsDocLoader" ") failed"
, nullptr, "./../../../docshell/base/nsDocShell.cpp", 2780); return
NS_ERROR_UNEXPECTED; } } while (false)
;
2781
2782 // Make sure we're not creating a loop in the docshell tree
2783 nsDocLoader* ancestor = this;
2784 do {
2785 if (childAsDocLoader == ancestor) {
2786 return NS_ERROR_ILLEGAL_VALUE;
2787 }
2788 ancestor = ancestor->GetParent();
2789 } while (ancestor);
2790
2791 // Make sure to remove the child from its current parent.
2792 nsDocLoader* childsParent = childAsDocLoader->GetParent();
2793 if (childsParent) {
2794 nsresult rv = childsParent->RemoveChildLoader(childAsDocLoader);
2795 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, "./../../../docshell/base/nsDocShell.cpp"
, 2795); return rv; } } while (false)
;
2796 }
2797
2798 // Make sure to clear the treeowner in case this child is a different type
2799 // from us.
2800 aChild->SetTreeOwner(nullptr);
2801
2802 nsresult res = AddChildLoader(childAsDocLoader);
2803 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, "./../../../docshell/base/nsDocShell.cpp"
, 2803); return res; } } while (false)
;
2804 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()"
, "./../../../docshell/base/nsDocShell.cpp", 2805); MOZ_PretendNoReturn
(); } } while (0)
2805 "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()"
, "./../../../docshell/base/nsDocShell.cpp", 2805); MOZ_PretendNoReturn
(); } } while (0)
;
2806
2807 /* Set the child's global history if the parent has one */
2808 if (mBrowsingContext->GetUseGlobalHistory()) {
2809 // childDocShell->SetUseGlobalHistory(true);
2810 // this should be set through BC inherit
2811 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()",
"./../../../docshell/base/nsDocShell.cpp", 2811); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aChild->GetBrowsingContext()->GetUseGlobalHistory()"
")"); do { MOZ_CrashSequence(__null, 2811); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2812 }
2813
2814 if (aChild->ItemType() != mItemType) {
2815 return NS_OK;
2816 }
2817
2818 aChild->SetTreeOwner(mTreeOwner);
2819
2820 nsCOMPtr<nsIDocShell> childAsDocShell(do_QueryInterface(aChild));
2821 if (!childAsDocShell) {
2822 return NS_OK;
2823 }
2824
2825 // charset, style-disabling, and zoom will be inherited in SetupNewViewer()
2826
2827 // Now take this document's charset and set the child's parentCharset field
2828 // to it. We'll later use that field, in the loading process, for the
2829 // charset choosing algorithm.
2830 // If we fail, at any point, we just return NS_OK.
2831 // This code has some performance impact. But this will be reduced when
2832 // the current charset will finally be stored as an Atom, avoiding the
2833 // alias resolution extra look-up.
2834
2835 // we are NOT going to propagate the charset is this Chrome's docshell
2836 if (mItemType == nsIDocShellTreeItem::typeChrome) {
2837 return NS_OK;
2838 }
2839
2840 // get the parent's current charset
2841 if (!mDocumentViewer) {
2842 return NS_OK;
2843 }
2844 Document* doc = mDocumentViewer->GetDocument();
2845 if (!doc) {
2846 return NS_OK;
2847 }
2848
2849 const Encoding* parentCS = doc->GetDocumentCharacterSet();
2850 int32_t charsetSource = doc->GetDocumentCharacterSetSource();
2851 // set the child's parentCharset
2852 childAsDocShell->SetParentCharset(parentCS, charsetSource,
2853 doc->NodePrincipal());
2854
2855 // printf("### 1 >>> Adding child. Parent CS = %s. ItemType = %d.\n",
2856 // NS_LossyConvertUTF16toASCII(parentCS).get(), mItemType);
2857
2858 return NS_OK;
2859}
2860
2861NS_IMETHODIMPnsresult
2862nsDocShell::RemoveChild(nsIDocShellTreeItem* aChild) {
2863 NS_ENSURE_ARG_POINTER(aChild)do { if ((__builtin_expect(!!(!(aChild)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aChild" ") failed", nullptr
, "./../../../docshell/base/nsDocShell.cpp", 2863); return NS_ERROR_INVALID_POINTER
; } } while (false)
;
2864
2865 RefPtr<nsDocLoader> childAsDocLoader = GetAsDocLoader(aChild);
2866 NS_ENSURE_TRUE(childAsDocLoader, NS_ERROR_UNEXPECTED)do { if ((__builtin_expect(!!(!(childAsDocLoader)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "childAsDocLoader" ") failed"
, nullptr, "./../../../docshell/base/nsDocShell.cpp", 2866); return
NS_ERROR_UNEXPECTED; } } while (false)
;
2867
2868 nsresult rv = RemoveChildLoader(childAsDocLoader);
2869 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, "./../../../docshell/base/nsDocShell.cpp"
, 2869); return rv; } } while (false)
;
2870
2871 aChild->SetTreeOwner(nullptr);
2872
2873 return nsDocLoader::AddDocLoaderAsChildOfRoot(childAsDocLoader);
2874}
2875
2876NS_IMETHODIMPnsresult
2877nsDocShell::GetInProcessChildAt(int32_t aIndex, nsIDocShellTreeItem** aChild) {
2878 NS_ENSURE_ARG_POINTER(aChild)do { if ((__builtin_expect(!!(!(aChild)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aChild" ") failed", nullptr
, "./../../../docshell/base/nsDocShell.cpp", 2878); return NS_ERROR_INVALID_POINTER
; } } while (false)
;
2879
2880 RefPtr<nsDocShell> child = GetInProcessChildAt(aIndex);
2881 NS_ENSURE_TRUE(child, NS_ERROR_UNEXPECTED)do { if ((__builtin_expect(!!(!(child)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "child" ") failed", nullptr
, "./../../../docshell/base/nsDocShell.cpp", 2881); return NS_ERROR_UNEXPECTED
; } } while (false)
;
2882
2883 child.forget(aChild);
2884
2885 return NS_OK;
2886}
2887
2888nsDocShell* nsDocShell::GetInProcessChildAt(int32_t aIndex) {
2889#ifdef DEBUG1
2890 if (aIndex < 0) {
2891 NS_WARNING("Negative index passed to GetChildAt")NS_DebugBreak(NS_DEBUG_WARNING, "Negative index passed to GetChildAt"
, nullptr, "./../../../docshell/base/nsDocShell.cpp", 2891)
;
2892 } else if (static_cast<uint32_t>(aIndex) >= mChildList.Length()) {
2893 NS_WARNING("Too large an index passed to GetChildAt")NS_DebugBreak(NS_DEBUG_WARNING, "Too large an index passed to GetChildAt"
, nullptr, "./../../../docshell/base/nsDocShell.cpp", 2893)
;
2894 }
2895#endif
2896
2897 nsIDocumentLoader* child = ChildAt(aIndex);
2898
2899 // child may be nullptr here.
2900 return static_cast<nsDocShell*>(child);
2901}
2902
2903NS_IMETHODIMPnsresult nsDocShell::SynchronizeLayoutHistoryState() {
2904 if (mActiveEntry && mActiveEntry->GetLayoutHistoryState() &&
2905 mBrowsingContext) {
2906 if (XRE_IsContentProcess()) {
2907 dom::ContentChild* contentChild = dom::ContentChild::GetSingleton();
2908 if (contentChild) {
2909 contentChild->SendSynchronizeLayoutHistoryState(
2910 mBrowsingContext, mActiveEntry->GetLayoutHistoryState());
2911 }
2912 } else {
2913 SessionHistoryEntry* entry =
2914 mBrowsingContext->Canonical()->GetActiveSessionHistoryEntry();
2915 if (entry) {
2916 entry->SetLayoutHistoryState(mActiveEntry->GetLayoutHistoryState());
2917 }
2918 }
2919 if (mLoadingEntry &&
2920 mLoadingEntry->mInfo.SharedId() == mActiveEntry->SharedId()) {
2921 mLoadingEntry->mInfo.SetLayoutHistoryState(
2922 mActiveEntry->GetLayoutHistoryState());
2923 }
2924 }
2925
2926 return NS_OK;
2927}
2928
2929void nsDocShell::SetLoadGroupDefaultLoadFlags(nsLoadFlags aLoadFlags) {
2930 if (mLoadGroup) {
2931 mLoadGroup->SetDefaultLoadFlags(aLoadFlags);
2932 } else {
2933 NS_WARNING(NS_DebugBreak(NS_DEBUG_WARNING, "nsDocShell::SetLoadGroupDefaultLoadFlags has no loadGroup to "
"propagate the mode to", nullptr, "./../../../docshell/base/nsDocShell.cpp"
, 2935)
2934 "nsDocShell::SetLoadGroupDefaultLoadFlags has no loadGroup to "NS_DebugBreak(NS_DEBUG_WARNING, "nsDocShell::SetLoadGroupDefaultLoadFlags has no loadGroup to "
"propagate the mode to", nullptr, "./../../../docshell/base/nsDocShell.cpp"
, 2935)
2935 "propagate the mode to")NS_DebugBreak(NS_DEBUG_WARNING, "nsDocShell::SetLoadGroupDefaultLoadFlags has no loadGroup to "
"propagate the mode to", nullptr, "./../../../docshell/base/nsDocShell.cpp"
, 2935)
;
2936 }
2937}
2938
2939nsIScriptGlobalObject* nsDocShell::GetScriptGlobalObject() {
2940 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
, "./../../../docshell/base/nsDocShell.cpp", 2940); return nullptr
; } } while (false)
;
2941 return mScriptGlobal;
2942}
2943
2944Document* nsDocShell::GetDocument() {
2945 NS_ENSURE_TRUE(VerifyDocumentViewer(), nullptr)do { if ((__builtin_expect(!!(!(VerifyDocumentViewer())), 0))
) { NS_DebugBreak(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "VerifyDocumentViewer()"
") failed", nullptr, "./../../../docshell/base/nsDocShell.cpp"
, 2945); return nullptr; } } while (false)
;
2946 return mDocumentViewer->GetDocument();
2947}
2948
2949Document* nsDocShell::GetExtantDocument() {
2950 return mDocumentViewer ? mDocumentViewer->GetDocument() : nullptr;
2951}
2952
2953nsPIDOMWindowOuter* nsDocShell::GetWindow() {
2954 if (NS_FAILED(EnsureScriptEnvironment())((bool)(__builtin_expect(!!(NS_FAILED_impl(EnsureScriptEnvironment
())), 0)))
) {
2955 return nullptr;
2956 }
2957 return mScriptGlobal;
2958}
2959
2960NS_IMETHODIMPnsresult
2961nsDocShell::GetDomWindow(mozIDOMWindowProxy** aWindow) {
2962 NS_ENSURE_ARG_POINTER(aWindow)do { if ((__builtin_expect(!!(!(aWindow)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aWindow" ") failed", nullptr
, "./../../../docshell/base/nsDocShell.cpp", 2962); return NS_ERROR_INVALID_POINTER
; } } while (false)
;
2963
2964 nsresult rv = EnsureScriptEnvironment();
2965 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, "./../../../docshell/base/nsDocShell.cpp"
, 2965); return rv; } } while (false)
;
2966
2967 RefPtr<nsGlobalWindowOuter> window = mScriptGlobal;
2968 window.forget(aWindow);
2969 return NS_OK;
2970}
2971
2972NS_IMETHODIMPnsresult
2973nsDocShell::GetMessageManager(ContentFrameMessageManager** aMessageManager) {
2974 RefPtr<ContentFrameMessageManager> mm;
2975 if (RefPtr<BrowserChild> browserChild = BrowserChild::GetFrom(this)) {
2976 mm = browserChild->GetMessageManager();
2977 } else if (nsPIDOMWindowOuter* win = GetWindow()) {
2978 mm = win->GetMessageManager();
2979 }
2980 mm.forget(aMessageManager);
2981 return NS_OK;
2982}
2983
2984NS_IMETHODIMPnsresult
2985nsDocShell::GetIsNavigating(bool* aOut) {
2986 *aOut = mIsNavigating;
2987 return NS_OK;
2988}
2989
2990//-------------------------------------
2991//-- Helper Method for Print discovery
2992//-------------------------------------
2993bool nsDocShell::NavigationBlockedByPrinting(bool aDisplayErrorDialog) {
2994 if (!mBrowsingContext->Top()->GetIsPrinting()) {
2995 return false;
2996 }
2997 if (aDisplayErrorDialog) {
2998 DisplayLoadError(NS_ERROR_DOCUMENT_IS_PRINTMODE, nullptr, nullptr, nullptr);
2999 }
3000 return true;
3001}
3002
3003bool nsDocShell::IsNavigationAllowed(bool aDisplayPrintErrorDialog,
3004 bool aCheckIfUnloadFired) {
3005 bool isAllowed = !NavigationBlockedByPrinting(aDisplayPrintErrorDialog) &&
3006 (!aCheckIfUnloadFired || !mFiredUnloadEvent);
3007 if (!isAllowed) {
3008 return false;
3009 }
3010 if (!mDocumentViewer) {
3011 return true;
3012 }
3013 bool firingBeforeUnload;
3014 mDocumentViewer->GetBeforeUnloadFiring(&firingBeforeUnload);
3015 return !firingBeforeUnload;
3016}
3017
3018//*****************************************************************************
3019// nsDocShell::nsIWebNavigation
3020//*****************************************************************************
3021
3022NS_IMETHODIMPnsresult
3023nsDocShell::GetCanGoBack(bool* aCanGoBack) {
3024 *aCanGoBack = false;
3025 if (!IsNavigationAllowed(false)) {
3026 return NS_OK; // JS may not handle returning of an error code
3027 }
3028 RefPtr<ChildSHistory> rootSH = GetRootSessionHistory();
3029 if (rootSH) {
3030 *aCanGoBack = rootSH->CanGo(
3031 -1, StaticPrefs::browser_navigation_requireUserInteraction());
3032 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)
3033 ("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)
;
3034
3035 return NS_OK;
3036 }
3037 return NS_ERROR_FAILURE;
3038}
3039
3040NS_IMETHODIMPnsresult
3041nsDocShell::GetCanGoBackIgnoringUserInteraction(bool* aCanGoBack) {
3042 *aCanGoBack = false;
3043 if (!IsNavigationAllowed(false)) {
3044 return NS_OK; // JS may not handle returning of an error code
3045 }
3046 RefPtr<ChildSHistory> rootSH = GetRootSessionHistory();
3047 if (rootSH) {
3048 *aCanGoBack = rootSH->CanGo(-1, false);
3049 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)
3050 ("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)
3051 *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)
;
3052
3053 return NS_OK;
3054 }
3055 return NS_ERROR_FAILURE;
3056}
3057
3058NS_IMETHODIMPnsresult
3059nsDocShell::GetCanGoForward(bool* aCanGoForward) {
3060 *aCanGoForward = false;
3061 if (!IsNavigationAllowed(false)) {
3062 return NS_OK; // JS may not handle returning of an error code
3063 }
3064 RefPtr<ChildSHistory> rootSH = GetRootSessionHistory();
3065 if (rootSH) {
3066 *aCanGoForward = rootSH->CanGo(
3067 1, StaticPrefs::browser_navigation_requireUserInteraction());
3068 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)
3069 ("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)
;
3070 return NS_OK;
3071 }
3072 return NS_ERROR_FAILURE;
3073}
3074
3075NS_IMETHODIMPnsresult
3076nsDocShell::GoBack(bool aRequireUserInteraction, bool aUserActivation) {
3077 if (!IsNavigationAllowed()) {
3078 return NS_OK; // JS may not handle returning of an error code
3079 }
3080
3081 auto cleanupIsNavigating = MakeScopeExit([&]() { mIsNavigating = false; });
3082 mIsNavigating = true;
3083
3084 RefPtr<ChildSHistory> rootSH = GetRootSessionHistory();
3085 NS_ENSURE_TRUE(rootSH, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(rootSH)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "rootSH" ") failed", nullptr
, "./../../../docshell/base/nsDocShell.cpp", 3085); return NS_ERROR_FAILURE
; } } while (false)
;
3086 ErrorResult rv;
3087 rootSH->Go(-1, aRequireUserInteraction, aUserActivation, rv);
3088 return rv.StealNSResult();
3089}
3090
3091NS_IMETHODIMPnsresult
3092nsDocShell::GoForward(bool aRequireUserInteraction, bool aUserActivation) {
3093 if (!IsNavigationAllowed()) {
3094 return NS_OK; // JS may not handle returning of an error code
3095 }
3096
3097 auto cleanupIsNavigating = MakeScopeExit([&]() { mIsNavigating = false; });
3098 mIsNavigating = true;
3099
3100 RefPtr<ChildSHistory> rootSH = GetRootSessionHistory();
3101 NS_ENSURE_TRUE(rootSH, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(rootSH)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "rootSH" ") failed", nullptr
, "./../../../docshell/base/nsDocShell.cpp", 3101); return NS_ERROR_FAILURE
; } } while (false)
;
3102 ErrorResult rv;
3103 rootSH->Go(1, aRequireUserInteraction, aUserActivation, rv);
3104 return rv.StealNSResult();
3105}
3106
3107// XXX(nika): We may want to stop exposing this API in the child process? Going
3108// to a specific index from multiple different processes could definitely race.
3109NS_IMETHODIMPnsresult
3110nsDocShell::GotoIndex(int32_t aIndex, bool aUserActivation) {
3111 if (!IsNavigationAllowed()) {
3112 return NS_OK; // JS may not handle returning of an error code
3113 }
3114
3115 auto cleanupIsNavigating = MakeScopeExit([&]() { mIsNavigating = false; });
3116 mIsNavigating = true;
3117
3118 RefPtr<ChildSHistory> rootSH = GetRootSessionHistory();
3119 NS_ENSURE_TRUE(rootSH, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(rootSH)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "rootSH" ") failed", nullptr
, "./../../../docshell/base/nsDocShell.cpp", 3119); return NS_ERROR_FAILURE
; } } while (false)
;
3120
3121 ErrorResult rv;
3122 rootSH->GotoIndex(aIndex, aIndex - rootSH->Index(), false, aUserActivation,
3123 rv);
3124 return rv.StealNSResult();
3125}
3126
3127nsresult nsDocShell::LoadURI(nsIURI* aURI,
3128 const LoadURIOptions& aLoadURIOptions) {
3129 if (!IsNavigationAllowed()) {
3130 return NS_OK; // JS may not handle returning of an error code
3131 }
3132 RefPtr<nsDocShellLoadState> loadState;
3133 nsresult rv = nsDocShellLoadState::CreateFromLoadURIOptions(
3134 mBrowsingContext, aURI, aLoadURIOptions, getter_AddRefs(loadState));
3135 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", "./../../../docshell/base/nsDocShell.cpp"
, 3135); AnnotateMozCrashReason("MOZ_ASSERT" "(" "rv != NS_ERROR_MALFORMED_URI"
")"); do { MOZ_CrashSequence(__null, 3135); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3136 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) || !loadState) {
3137 return NS_ERROR_FAILURE;
3138 }
3139
3140 // Set the captive portal tab flag on the browsing context if requested
3141 if (loadState->GetIsCaptivePortalTab()) {
3142 (void)mBrowsingContext->SetIsCaptivePortalTab(true);
3143 }
3144
3145 return LoadURI(loadState, true);
3146}
3147
3148NS_IMETHODIMPnsresult
3149nsDocShell::LoadURIFromScript(nsIURI* aURI,
3150 JS::Handle<JS::Value> aLoadURIOptions,
3151 JSContext* aCx) {
3152 // generate dictionary for aLoadURIOptions and forward call
3153 LoadURIOptions loadURIOptions;
3154 if (!loadURIOptions.Init(aCx, aLoadURIOptions)) {
3155 return NS_ERROR_INVALID_ARG;
3156 }
3157 return LoadURI(aURI, loadURIOptions);
3158}
3159
3160nsresult nsDocShell::FixupAndLoadURIString(
3161 const nsAString& aURIString, const LoadURIOptions& aLoadURIOptions) {
3162 if (!IsNavigationAllowed()) {
3163 return NS_OK; // JS may not handle returning of an error code
3164 }
3165
3166 RefPtr<nsDocShellLoadState> loadState;
3167 nsresult rv = nsDocShellLoadState::CreateFromLoadURIOptions(
3168 mBrowsingContext, aURIString, aLoadURIOptions, getter_AddRefs(loadState));
3169
3170 uint32_t loadFlags = aLoadURIOptions.mLoadFlags;
3171 if (NS_ERROR_MALFORMED_URI == rv) {
3172 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)
3173 ("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)
3174 "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)
3175 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)
;
3176
3177 // We need to store a session history entry. We don't have a valid URI, so
3178 // we use about:blank instead.
3179 nsCOMPtr<nsIURI> uri;
3180 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))"
, "./../../../docshell/base/nsDocShell.cpp", 3180); AnnotateMozCrashReason
("MOZ_CRASH(" "NS_SUCCEEDED(NS_NewURI(getter_AddRefs(uri), \"about:blank\"_ns))"
")"); do { MOZ_CrashSequence(__null, 3180); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
;
3181 nsCOMPtr<nsIPrincipal> triggeringPrincipal;
3182 if (aLoadURIOptions.mTriggeringPrincipal) {
3183 triggeringPrincipal = aLoadURIOptions.mTriggeringPrincipal;
3184 } else {
3185 triggeringPrincipal = nsContentUtils::GetSystemPrincipal();
3186 }
3187 UniquePtr<SessionHistoryInfo> previousActiveEntry(mActiveEntry.release());
3188 mActiveEntry = MakeUnique<SessionHistoryInfo>(
3189 uri, triggeringPrincipal, nullptr, nullptr, nullptr,
3190 nsLiteralCString("text/html"));
3191 mBrowsingContext->SetActiveSessionHistoryEntry(
3192 Nothing(), mActiveEntry.get(), previousActiveEntry.get(),
3193 MAKE_LOAD_TYPE(LOAD_NORMAL, loadFlags)((LOAD_NORMAL) | ((loadFlags) << 16)),
3194 /* aUpdatedCacheKey = */ 0);
3195 if (DisplayLoadError(rv, nullptr, PromiseFlatStringTPromiseFlatString<char16_t>(aURIString).get(),
3196 nullptr) &&
3197 (loadFlags & LOAD_FLAGS_ERROR_LOAD_CHANGES_RV) != 0) {
3198 return NS_ERROR_LOAD_SHOWED_ERRORPAGE;
3199 }
3200 }
3201
3202 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) || !loadState) {
3203 return NS_ERROR_FAILURE;
3204 }
3205
3206 // Set the captive portal tab flag on the browsing context if requested
3207 if (loadState->GetIsCaptivePortalTab()) {
3208 (void)mBrowsingContext->SetIsCaptivePortalTab(true);
3209 }
3210
3211 return LoadURI(loadState, true);
3212}
3213
3214NS_IMETHODIMPnsresult
3215nsDocShell::FixupAndLoadURIStringFromScript(
3216 const nsAString& aURIString, JS::Handle<JS::Value> aLoadURIOptions,
3217 JSContext* aCx) {
3218 // generate dictionary for aLoadURIOptions and forward call
3219 LoadURIOptions loadURIOptions;
3220 if (!loadURIOptions.Init(aCx, aLoadURIOptions)) {
3221 return NS_ERROR_INVALID_ARG;
3222 }
3223 return FixupAndLoadURIString(aURIString, loadURIOptions);
3224}
3225
3226void nsDocShell::UnblockEmbedderLoadEventForFailure(bool aFireFrameErrorEvent) {
3227 // If we're not in a content frame, or are at a BrowsingContext tree boundary,
3228 // such as the content-chrome boundary, don't fire the error event.
3229 if (mBrowsingContext->IsTopContent() || mBrowsingContext->IsChrome()) {
3230 return;
3231 }
3232
3233 // If embedder is same-process, then unblocking the load event is already
3234 // handled by nsDocLoader. Fire the error event on our embedder element if
3235 // requested.
3236 //
3237 // XXX: Bug 1440212 is looking into potentially changing this behaviour to act
3238 // more like the remote case when in-process.
3239 RefPtr<Element> element = mBrowsingContext->GetEmbedderElement();
3240 if (element) {
3241 if (aFireFrameErrorEvent) {
3242 if (RefPtr<nsFrameLoaderOwner> flo = do_QueryObject(element)) {
3243 if (RefPtr<nsFrameLoader> fl = flo->GetFrameLoader()) {
3244 fl->FireErrorEvent();
3245 }
3246 }
3247 }
3248 return;
3249 }
3250
3251 // If we have a cross-process parent document, we must notify it that we no
3252 // longer block its load event. This is necessary for OOP sub-documents
3253 // because error documents do not result in a call to
3254 // SendMaybeFireEmbedderLoadEvents via any of the normal call paths.
3255 // (Obviously, we must do this before any of the returns below.)
3256 RefPtr<BrowserChild> browserChild = BrowserChild::GetFrom(this);
3257 if (browserChild &&
3258 !mBrowsingContext->GetParentWindowContext()->IsInProcess()) {
3259 (void)browserChild->SendMaybeFireEmbedderLoadEvents(
3260 aFireFrameErrorEvent ? EmbedderElementEventType::ErrorEvent
3261 : EmbedderElementEventType::NoEvent);
3262 }
3263}
3264
3265NS_IMETHODIMPnsresult
3266nsDocShell::DisplayLoadError(nsresult aError, nsIURI* aURI,
3267 const char16_t* aURL, nsIChannel* aFailedChannel,
3268 bool* aDisplayedErrorPage) {
3269 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
)
3270 ("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
)
3271 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
)
;
3272
3273 *aDisplayedErrorPage = false;
3274 // Get prompt and string bundle services
3275 nsCOMPtr<nsIPrompt> prompter;
3276 nsCOMPtr<nsIStringBundle> stringBundle;
3277 GetPromptAndStringBundle(getter_AddRefs(prompter),
3278 getter_AddRefs(stringBundle));
3279
3280 NS_ENSURE_TRUE(stringBundle, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(stringBundle)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "stringBundle" ") failed"
, nullptr, "./../../../docshell/base/nsDocShell.cpp", 3280); return
NS_ERROR_FAILURE; } } while (false)
;
3281 NS_ENSURE_TRUE(prompter, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(prompter)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "prompter" ") failed", nullptr
, "./../../../docshell/base/nsDocShell.cpp", 3281); return NS_ERROR_FAILURE
; } } while (false)
;
3282
3283 const char* error = nullptr;
3284 // The key used to select the appropriate error message from the properties
3285 // file.
3286 const char* errorDescriptionID = nullptr;
3287 AutoTArray<nsString, 3> formatStrs;
3288 bool addHostPort = false;
3289 bool isBadStsCertError = false;
3290 nsresult rv = NS_OK;
3291 nsAutoString messageStr;
3292 nsAutoCString cssClass;
3293 nsAutoCString errorPage;
3294
3295 errorPage.AssignLiteral("neterror");
3296
3297 // Turn the error code into a human readable error message.
3298 if (NS_ERROR_UNKNOWN_PROTOCOL == aError) {
3299 NS_ENSURE_ARG_POINTER(aURI)do { if ((__builtin_expect(!!(!(aURI)), 0))) { NS_DebugBreak(
NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aURI" ") failed", nullptr
, "./../../../docshell/base/nsDocShell.cpp", 3299); return NS_ERROR_INVALID_POINTER
; } } while (false)
;
3300
3301 // Extract the schemes into a comma delimited list.
3302 nsAutoCString scheme;
3303 aURI->GetScheme(scheme);
3304 CopyASCIItoUTF16(scheme, *formatStrs.AppendElement());
3305 nsCOMPtr<nsINestedURI> nestedURI = do_QueryInterface(aURI);
3306 while (nestedURI) {
3307 nsCOMPtr<nsIURI> tempURI;
3308 nsresult rv2;
3309 rv2 = nestedURI->GetInnerURI(getter_AddRefs(tempURI));
3310 if (NS_SUCCEEDED(rv2)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv2)), 1))) && tempURI) {
3311 tempURI->GetScheme(scheme);
3312 formatStrs[0].AppendLiteral(", ");
3313 AppendASCIItoUTF16(scheme, formatStrs[0]);
3314 }
3315 nestedURI = do_QueryInterface(tempURI);
3316 }
3317 error = "unknownProtocolFound";
3318 } else if (NS_ERROR_NET_EMPTY_RESPONSE == aError) {
3319 NS_ENSURE_ARG_POINTER(aURI)do { if ((__builtin_expect(!!(!(aURI)), 0))) { NS_DebugBreak(
NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aURI" ") failed", nullptr
, "./../../../docshell/base/nsDocShell.cpp", 3319); return NS_ERROR_INVALID_POINTER
; } } while (false)
;
3320 error = "httpErrorPage";
3321 } else if (NS_ERROR_NET_ERROR_RESPONSE == aError) {
3322 NS_ENSURE_ARG_POINTER(aURI)do { if ((__builtin_expect(!!(!(aURI)), 0))) { NS_DebugBreak(
NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aURI" ") failed", nullptr
, "./../../../docshell/base/nsDocShell.cpp", 3322); return NS_ERROR_INVALID_POINTER
; } } while (false)
;
3323 error = "serverError";
3324 } else if (NS_ERROR_FILE_NOT_FOUND == aError) {
3325 NS_ENSURE_ARG_POINTER(aURI)do { if ((__builtin_expect(!!(!(aURI)), 0))) { NS_DebugBreak(
NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aURI" ") failed", nullptr
, "./../../../docshell/base/nsDocShell.cpp", 3325); return NS_ERROR_INVALID_POINTER
; } } while (false)
;
3326 error = "fileNotFound";
3327 } else if (NS_ERROR_FILE_ACCESS_DENIED == aError) {
3328 NS_ENSURE_ARG_POINTER(aURI)do { if ((__builtin_expect(!!(!(aURI)), 0))) { NS_DebugBreak(
NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aURI" ") failed", nullptr
, "./../../../docshell/base/nsDocShell.cpp", 3328); return NS_ERROR_INVALID_POINTER
; } } while (false)
;
3329 error = "fileAccessDenied";
3330 } else if (NS_ERROR_UNKNOWN_HOST == aError) {
3331 NS_ENSURE_ARG_POINTER(aURI)do { if ((__builtin_expect(!!(!(aURI)), 0))) { NS_DebugBreak(
NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aURI" ") failed", nullptr
, "./../../../docshell/base/nsDocShell.cpp", 3331); return NS_ERROR_INVALID_POINTER
; } } while (false)
;
3332 // Get the host
3333 nsAutoCString host;
3334 nsCOMPtr<nsIURI> innermostURI = NS_GetInnermostURI(aURI);
3335 innermostURI->GetHost(host);
3336 CopyUTF8toUTF16(host, *formatStrs.AppendElement());
3337 errorDescriptionID = "dnsNotFound2";
3338 error = "dnsNotFound";
3339 } else if (NS_ERROR_CONNECTION_REFUSED == aError ||
3340 NS_ERROR_PROXY_BAD_GATEWAY == aError) {
3341 NS_ENSURE_ARG_POINTER(aURI)do { if ((__builtin_expect(!!(!(aURI)), 0))) { NS_DebugBreak(
NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aURI" ") failed", nullptr
, "./../../../docshell/base/nsDocShell.cpp", 3341); return NS_ERROR_INVALID_POINTER
; } } while (false)
;
3342 addHostPort = true;
3343 error = "connectionFailure";
3344 } else if (NS_ERROR_NET_INTERRUPT == aError) {
3345 NS_ENSURE_ARG_POINTER(aURI)do { if ((__builtin_expect(!!(!(aURI)), 0))) { NS_DebugBreak(
NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aURI" ") failed", nullptr
, "./../../../docshell/base/nsDocShell.cpp", 3345); return NS_ERROR_INVALID_POINTER
; } } while (false)
;
3346 addHostPort = true;
3347 error = "netInterrupt";
3348 } else if (NS_ERROR_NET_TIMEOUT == aError ||
3349 NS_ERROR_PROXY_GATEWAY_TIMEOUT == aError ||
3350 NS_ERROR_NET_TIMEOUT_EXTERNAL == aError) {
3351 NS_ENSURE_ARG_POINTER(aURI)do { if ((__builtin_expect(!!(!(aURI)), 0))) { NS_DebugBreak(
NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aURI" ") failed", nullptr
, "./../../../docshell/base/nsDocShell.cpp", 3351); return NS_ERROR_INVALID_POINTER
; } } while (false)
;
3352 // Get the host
3353 nsAutoCString host;
3354 aURI->GetHost(host);
3355 CopyUTF8toUTF16(host, *formatStrs.AppendElement());
3356 error = "netTimeout";
3357 } else if (NS_ERROR_CSP_FRAME_ANCESTOR_VIOLATION == aError ||
3358 NS_ERROR_CSP_FORM_ACTION_VIOLATION == aError) {
3359 // CSP error
3360 cssClass.AssignLiteral("neterror");
3361 error = "cspBlocked";
3362 } else if (NS_ERROR_XFO_VIOLATION == aError) {
3363 // XFO error
3364 cssClass.AssignLiteral("neterror");
3365 error = "xfoBlocked";
3366 } else if (NS_ERROR_GET_MODULE(aError) == NS_ERROR_MODULE_SECURITY21) {
3367 nsCOMPtr<nsINSSErrorsService> nsserr =
3368 do_GetService(NS_NSS_ERRORS_SERVICE_CONTRACTID"@mozilla.org/nss_errors_service;1");
3369
3370 uint32_t errorClass;
3371 if (!nsserr || NS_FAILED(nsserr->GetErrorClass(aError, &errorClass))((bool)(__builtin_expect(!!(NS_FAILED_impl(nsserr->GetErrorClass
(aError, &errorClass))), 0)))
) {
3372 errorClass = nsINSSErrorsService::ERROR_CLASS_SSL_PROTOCOL;
3373 }
3374
3375 nsCOMPtr<nsITransportSecurityInfo> tsi;
3376 if (aFailedChannel) {
3377 aFailedChannel->GetSecurityInfo(getter_AddRefs(tsi));
3378 }
3379 if (tsi) {
3380 uint32_t securityState;
3381 tsi->GetSecurityState(&securityState);
3382 if (securityState & nsIWebProgressListener::STATE_USES_SSL_3) {
3383 error = "sslv3Used";
3384 addHostPort = true;
3385 } else if (securityState &
3386 nsIWebProgressListener::STATE_USES_WEAK_CRYPTO) {
3387 error = "weakCryptoUsed";
Value stored to 'error' is never read
3388 addHostPort = true;
3389 }
3390 } else {
3391 // No channel, let's obtain the generic error message
3392 if (nsserr) {
3393 nsserr->GetErrorMessage(aError, messageStr);
3394 }
3395 }
3396 // We don't have a message string here anymore but DisplayLoadError
3397 // requires a non-empty messageStr.
3398 messageStr.Truncate();
3399 messageStr.AssignLiteral(u" ");
3400 if (errorClass == nsINSSErrorsService::ERROR_CLASS_BAD_CERT) {
3401 error = "nssBadCert";
3402
3403 // If this is an HTTP Strict Transport Security host or a pinned host
3404 // and the certificate is bad, don't allow overrides (RFC 6797 section
3405 // 12.1).
3406 bool isStsHost = false;
3407 bool isPinnedHost = false;
3408 OriginAttributes attrsForHSTS;
3409 if (aFailedChannel) {
3410 StoragePrincipalHelper::GetOriginAttributesForHSTS(aFailedChannel,
3411 attrsForHSTS);
3412 } else {
3413 attrsForHSTS = GetOriginAttributes();
3414 }
3415
3416 if (XRE_IsParentProcess()) {
3417 nsCOMPtr<nsISiteSecurityService> sss =
3418 do_GetService(NS_SSSERVICE_CONTRACTID"@mozilla.org/ssservice;1", &rv);
3419 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, "./../../../docshell/base/nsDocShell.cpp"
, 3419); return rv; } } while (false)
;
3420 rv = sss->IsSecureURI(aURI, attrsForHSTS, &isStsHost);
3421 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, "./../../../docshell/base/nsDocShell.cpp"
, 3421); return rv; } } while (false)
;
3422 } else {
3423 mozilla::dom::ContentChild* cc =
3424 mozilla::dom::ContentChild::GetSingleton();
3425 cc->SendIsSecureURI(aURI, attrsForHSTS, &isStsHost);
3426 }
3427 nsCOMPtr<nsIPublicKeyPinningService> pkps =
3428 do_GetService(NS_PKPSERVICE_CONTRACTID"@mozilla.org/security/publickeypinningservice;1", &rv);
3429 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, "./../../../docshell/base/nsDocShell.cpp"
, 3429); return rv; } } while (false)
;
3430 rv = pkps->HostHasPins(aURI, &isPinnedHost);
3431
3432 if (Preferences::GetBool("browser.xul.error_pages.expert_bad_cert",
3433 false)) {
3434 cssClass.AssignLiteral("expertBadCert");
3435 }
3436
3437 // HSTS/pinning takes precedence over the expert bad cert pref. We
3438 // never want to show the "Add Exception" button for these sites.
3439 // In the future we should differentiate between an HSTS host and a
3440 // pinned host and display a more informative message to the user.
3441 if (isStsHost || isPinnedHost) {
3442 isBadStsCertError = true;
3443 cssClass.AssignLiteral("badStsCert");
3444 }
3445
3446 errorPage.Assign("certerror");
3447 } else {
3448 error = "nssFailure2";
3449 }
3450 } else if (NS_ERROR_PHISHING_URI == aError ||
3451 NS_ERROR_MALWARE_URI == aError ||
3452 NS_ERROR_UNWANTED_URI == aError ||
3453 NS_ERROR_HARMFULADDON_URI == aError ||
3454 NS_ERROR_HARMFUL_URI == aError) {
3455 nsAutoCString host;
3456 aURI->GetHost(host);
3457 CopyUTF8toUTF16(host, *formatStrs.AppendElement());
3458
3459 // Malware and phishing detectors may want to use an alternate error
3460 // page, but if the pref's not set, we'll fall back on the standard page
3461 nsAutoCString alternateErrorPage;
3462 nsresult rv = Preferences::GetCString("urlclassifier.alternate_error_page",
3463 alternateErrorPage);
3464 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
3465 errorPage.Assign(alternateErrorPage);
3466 }
3467
3468 if (NS_ERROR_PHISHING_URI == aError) {
3469 error = "deceptiveBlocked";
3470 } else if (NS_ERROR_MALWARE_URI == aError) {
3471 error = "malwareBlocked";
3472 } else if (NS_ERROR_UNWANTED_URI == aError) {
3473 error = "unwantedBlocked";
3474 } else if (NS_ERROR_HARMFUL_URI == aError) {
3475 error = "harmfulBlocked";
3476 } else if (NS_ERROR_HARMFULADDON_URI == aError) {
3477 error = "addonBlocked";
3478 }
3479
3480 cssClass.AssignLiteral("blacklist");
3481 } else if (NS_ERROR_CONTENT_CRASHED == aError) {
3482 errorPage.AssignLiteral("tabcrashed");
3483 error = "tabcrashed";
3484
3485 RefPtr<EventTarget> handler = mChromeEventHandler;
3486 if (handler) {
3487 nsCOMPtr<Element> element = do_QueryInterface(handler);
3488 element->GetAttribute(u"crashedPageTitle"_ns, messageStr);
3489 }
3490
3491 // DisplayLoadError requires a non-empty messageStr to proceed and call
3492 // LoadErrorPage. If the page doesn't have a title, we will use a blank
3493 // space which will be trimmed and thus treated as empty by the front-end.
3494 if (messageStr.IsEmpty()) {
3495 messageStr.AssignLiteral(u" ");
3496 }
3497 } else if (NS_ERROR_FRAME_CRASHED == aError) {
3498 errorPage.AssignLiteral("framecrashed");
3499 error = "framecrashed";
3500 messageStr.AssignLiteral(u" ");
3501 } else if (NS_ERROR_BUILDID_MISMATCH == aError) {
3502 errorPage.AssignLiteral("restartrequired");
3503 error = "restartrequired";
3504
3505 // DisplayLoadError requires a non-empty messageStr to proceed and call
3506 // LoadErrorPage. If the page doesn't have a title, we will use a blank
3507 // space which will be trimmed and thus treated as empty by the front-end.
3508 if (messageStr.IsEmpty()) {
3509 messageStr.AssignLiteral(u" ");
3510 }
3511 } else if (aError == NS_ERROR_RESTRICTED_CONTENT) {
3512 errorPage.AssignLiteral("restricted");
3513 error = "restrictedcontent";
3514 if (messageStr.IsEmpty()) {
3515 messageStr.AssignLiteral(u" ");
3516 }
3517 } else {
3518 // Errors requiring simple formatting
3519 switch (aError) {
3520 case NS_ERROR_MALFORMED_URI:
3521 // URI is malformed
3522 error = "malformedURI";
3523 errorDescriptionID = "malformedURI2";
3524 break;
3525 case NS_ERROR_REDIRECT_LOOP:
3526 // Doc failed to load because the server generated too many redirects
3527 error = "redirectLoop";
3528 break;
3529 case NS_ERROR_UNKNOWN_SOCKET_TYPE:
3530 // Doc failed to load because the client is misconfigured
3531 error = "clientSocketMisconfiguration";
3532 break;
3533 case NS_ERROR_NET_RESET:
3534 case NS_ERROR_OS_LOCAL_NETWORK_ACCESS_DENIED:
3535 // Doc failed to load because the server kept reseting the connection
3536 // before we could read any data from it
3537 // NS_ERROR_OS_LOCAL_NETWORK_ACCESS_DENIED is temporarily grouped
3538 // with netReset; it will get its own dedicated error page in
3539 // bug 2060188.
3540 error = "netReset";
3541 break;
3542 case NS_ERROR_DOCUMENT_NOT_CACHED:
3543 // Doc failed to load because the cache does not contain a copy of
3544 // the document.
3545 error = "notCached";
3546 break;
3547 case NS_ERROR_OFFLINE:
3548 // Doc failed to load because we are offline.
3549 error = "netOffline";
3550 break;
3551 case NS_ERROR_DOCUMENT_IS_PRINTMODE:
3552 // Doc navigation attempted while Printing or Print Preview
3553 error = "isprinting";
3554 break;
3555 case NS_ERROR_PORT_ACCESS_NOT_ALLOWED:
3556 // Port blocked for security reasons
3557 addHostPort = true;
3558 error = "deniedPortAccess";
3559 break;
3560 case NS_ERROR_UNKNOWN_PROXY_HOST:
3561 // Proxy hostname could not be resolved.
3562 error = "proxyResolveFailure";
3563 break;
3564 case NS_ERROR_PROXY_CONNECTION_REFUSED:
3565 case NS_ERROR_PROXY_FORBIDDEN:
3566 case NS_ERROR_PROXY_NOT_IMPLEMENTED:
3567 case NS_ERROR_PROXY_AUTHENTICATION_FAILED:
3568 case NS_ERROR_PROXY_TOO_MANY_REQUESTS:
3569 // Proxy connection was refused.
3570 error = "proxyConnectFailure";
3571 break;
3572 case NS_ERROR_INVALID_CONTENT_ENCODING:
3573 // Bad Content Encoding.
3574 error = "contentEncodingError";
3575 break;
3576 case NS_ERROR_UNSAFE_CONTENT_TYPE:
3577 // Channel refused to load from an unrecognized content type.
3578 error = "unsafeContentType";
3579 break;
3580 case NS_ERROR_CORRUPTED_CONTENT:
3581 // Broken Content Detected. e.g. Content-MD5 check failure.
3582 error = "corruptedContentErrorv2";
3583 break;
3584 case NS_ERROR_INTERCEPTION_FAILED:
3585 // ServiceWorker intercepted request, but something went wrong.
3586 error = "corruptedContentErrorv2";
3587 break;
3588 case NS_ERROR_NET_INADEQUATE_SECURITY:
3589 // Server negotiated bad TLS for HTTP/2.
3590 error = "inadequateSecurityError";
3591 addHostPort = true;
3592 break;
3593 case NS_ERROR_BLOCKED_BY_POLICY:
3594 // Page blocked by policy
3595 error = "blockedByPolicy";
3596 break;
3597 case NS_ERROR_DOM_COOP_FAILED:
3598 error = "blockedByCOOP";
3599 errorDescriptionID = "blockedByCORP";
3600 break;
3601 case NS_ERROR_DOM_COEP_FAILED:
3602 error = "blockedByCOEP";
3603 errorDescriptionID = "blockedByCORP";
3604 break;
3605 case NS_ERROR_DOM_INVALID_HEADER_VALUE:
3606 error = "invalidHeaderValue";
3607 break;
3608 case NS_ERROR_NET_HTTP2_SENT_GOAWAY:
3609 case NS_ERROR_NET_HTTP3_PROTOCOL_ERROR:
3610 // HTTP/2 or HTTP/3 stack detected a protocol error
3611 error = "networkProtocolError";
3612 break;
3613 case NS_ERROR_BASIC_HTTP_AUTH_DISABLED:
3614 error = "basicHttpAuthDisabled";
3615 break;
3616 default:
3617 break;
3618 }
3619 }
3620
3621 nsresult delegateErrorCode = aError;
3622 // If the HTTPS-Only Mode upgraded this request and the upgrade might have
3623 // caused this error, we replace the error-page with about:httpsonlyerror
3624 if (nsHTTPSOnlyUtils::CouldBeHttpsOnlyError(aFailedChannel, aError)) {
3625 errorPage.AssignLiteral("httpsonlyerror");
3626 delegateErrorCode = NS_ERROR_HTTPS_ONLY;
3627 } else if (isBadStsCertError) {
3628 delegateErrorCode = NS_ERROR_BAD_HSTS_CERT;
3629 }
3630
3631 if (nsCOMPtr<nsILoadURIDelegate> loadURIDelegate = GetLoadURIDelegate()) {
3632 nsCOMPtr<nsIURI> errorPageURI;
3633 rv = loadURIDelegate->HandleLoadError(
3634 aURI, delegateErrorCode, NS_ERROR_GET_MODULE(delegateErrorCode),
3635 getter_AddRefs(errorPageURI));
3636 // If the docshell is going away there's no point in showing an error page.
3637 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) || mIsBeingDestroyed) {
3638 *aDisplayedErrorPage = false;
3639 return NS_OK;
3640 }
3641
3642 if (errorPageURI) {
3643 *aDisplayedErrorPage =
3644 NS_SUCCEEDED(LoadErrorPage(errorPageURI, aURI, aFailedChannel))((bool)(__builtin_expect(!!(!NS_FAILED_impl(LoadErrorPage(errorPageURI
, aURI, aFailedChannel))), 1)))
;
3645 return NS_OK;
3646 }
3647 }
3648
3649 // Test if the error should be displayed
3650 if (!error) {
3651 return NS_OK;
3652 }
3653
3654 if (!errorDescriptionID) {
3655 errorDescriptionID = error;
3656 }
3657
3658 glean::page::load_error
3659 .Get(IsSubframe() ? "frame"_ns : "top"_ns,
3660 mozilla::dom::LoadErrorToTelemetryLabel(aError))
3661 .Add();
3662
3663 // Test if the error needs to be formatted
3664 if (!messageStr.IsEmpty()) {
3665 // already obtained message
3666 } else {
3667 if (addHostPort) {
3668 // Build up the host:port string.
3669 nsAutoCString hostport;
3670 if (aURI) {
3671 aURI->GetHostPort(hostport);
3672 } else {
3673 hostport.Assign('?');
3674 }
3675 CopyUTF8toUTF16(hostport, *formatStrs.AppendElement());
3676 }
3677
3678 nsAutoCString spec;
3679 rv = NS_ERROR_NOT_AVAILABLE;
3680 auto& nextFormatStr = *formatStrs.AppendElement();
3681 if (aURI) {
3682 // displaying "file://" is aesthetically unpleasing and could even be
3683 // confusing to the user
3684 if (aURI->SchemeIs("file")) {
3685 aURI->GetPathQueryRef(spec);
3686 } else {
3687 aURI->GetSpec(spec);
3688 }
3689
3690 nsCOMPtr<nsITextToSubURI> textToSubURI(
3691 do_GetService(NS_ITEXTTOSUBURI_CONTRACTID"@mozilla.org/intl/texttosuburi;1", &rv));
3692 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
3693 rv = textToSubURI->UnEscapeURIForUI(spec, nextFormatStr);
3694 }
3695 } else {
3696 spec.Assign('?');
3697 }
3698 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3699 CopyUTF8toUTF16(spec, nextFormatStr);
3700 }
3701 rv = NS_OK;
3702
3703 nsAutoString str;
3704 rv =
3705 stringBundle->FormatStringFromName(errorDescriptionID, formatStrs, str);
3706 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, "./../../../docshell/base/nsDocShell.cpp"
, 3706); return rv; } } while (false)
;
3707 messageStr.Assign(str);
3708 }
3709
3710 // Display the error as a page or an alert prompt
3711 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, "./../../../docshell/base/nsDocShell.cpp"
, 3711); return NS_ERROR_FAILURE; } } while (false)
;
3712
3713 if ((NS_ERROR_NET_INTERRUPT == aError || NS_ERROR_NET_RESET == aError) &&
3714 aURI->SchemeIs("https")) {
3715 // Maybe TLS intolerant. Treat this as an SSL error.
3716 error = "nssFailure2";
3717 }
3718
3719 if (mBrowsingContext->GetUseErrorPages()) {
3720 // Display an error page
3721 nsresult loadedPage =
3722 LoadErrorPage(aURI, aURL, errorPage.get(), error, messageStr.get(),
3723 cssClass.get(), aFailedChannel);
3724 *aDisplayedErrorPage = NS_SUCCEEDED(loadedPage)((bool)(__builtin_expect(!!(!NS_FAILED_impl(loadedPage)), 1))
)
;
3725 } else {
3726 // The prompter reqires that our private window has a document (or it
3727 // asserts). Satisfy that assertion now since GetDoc will force
3728 // creation of one if it hasn't already been created.
3729 if (mScriptGlobal) {
3730 (void)mScriptGlobal->GetDoc();
3731 }
3732
3733 // Display a message box
3734 prompter->Alert(nullptr, messageStr.get());
3735 }
3736
3737 return NS_OK;
3738}
3739
3740#define PREF_SAFEBROWSING_ALLOWOVERRIDE"browser.safebrowsing.allowOverride" "browser.safebrowsing.allowOverride"
3741
3742nsresult nsDocShell::LoadErrorPage(nsIURI* aURI, const char16_t* aURL,
3743 const char* aErrorPage,
3744 const char* aErrorType,
3745 const char16_t* aDescription,
3746 const char* aCSSClass,
3747 nsIChannel* aFailedChannel) {
3748 if (mIsBeingDestroyed) {
3749 return NS_ERROR_NOT_AVAILABLE;
3750 }
3751
3752#if defined(DEBUG1)
3753 if (MOZ_LOG_TEST(gDocShellLog, LogLevel::Debug)(__builtin_expect(!!(mozilla::detail::log_test(gDocShellLog, LogLevel
::Debug)), 0))
) {
3754 nsAutoCString chanName;
3755 if (aFailedChannel) {
3756 aFailedChannel->GetName(chanName);
3757 } else {
3758 chanName.AssignLiteral("<no channel>");
3759 }
3760
3761 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)
3762 ("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)
3763 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)
3764 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)
;
3765 }
3766#endif
3767
3768 nsAutoCString url;
3769 if (aURI) {
3770 nsresult rv = aURI->GetSpec(url);
3771 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, "./../../../docshell/base/nsDocShell.cpp"
, 3771); return rv; } } while (false)
;
3772 } else if (aURL) {
3773 CopyUTF16toUTF8(MakeStringSpan(aURL), url);
3774 } else {
3775 return NS_ERROR_INVALID_POINTER;
3776 }
3777
3778 // Create a URL to pass all the error information through to the page.
3779
3780#undef SAFE_ESCAPE
3781#define SAFE_ESCAPE(output, input, params)if (NS_warn_if_impl(!NS_Escape(input, output, params), "!NS_Escape(input, output, params)"
, "./../../../docshell/base/nsDocShell.cpp", 3781)) { return NS_ERROR_OUT_OF_MEMORY
; }
\
3782 if (NS_WARN_IF(!NS_Escape(input, output, params))NS_warn_if_impl(!NS_Escape(input, output, params), "!NS_Escape(input, output, params)"
, "./../../../docshell/base/nsDocShell.cpp", 3782)
) { \
3783 return NS_ERROR_OUT_OF_MEMORY; \
3784 }
3785
3786 nsCString escapedUrl, escapedError, escapedDescription, escapedCSSClass;
3787 SAFE_ESCAPE(escapedUrl, url, url_Path)if (NS_warn_if_impl(!NS_Escape(url, escapedUrl, url_Path), "!NS_Escape(url, escapedUrl, url_Path)"
, "./../../../docshell/base/nsDocShell.cpp", 3787)) { return NS_ERROR_OUT_OF_MEMORY
; }
;
3788 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)"
, "./../../../docshell/base/nsDocShell.cpp", 3788)) { return NS_ERROR_OUT_OF_MEMORY
; }
;
3789 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)"
, "./../../../docshell/base/nsDocShell.cpp", 3790)) { return NS_ERROR_OUT_OF_MEMORY
; }
3790 url_Path)if (NS_warn_if_impl(!NS_Escape(NS_ConvertUTF16toUTF8(aDescription
), escapedDescription, url_Path), "!NS_Escape(NS_ConvertUTF16toUTF8(aDescription), escapedDescription, url_Path)"
, "./../../../docshell/base/nsDocShell.cpp", 3790)) { return NS_ERROR_OUT_OF_MEMORY
; }
;
3791 if (aCSSClass) {
3792 nsCString cssClass(aCSSClass);
3793 SAFE_ESCAPE(escapedCSSClass, cssClass, url_Path)if (NS_warn_if_impl(!NS_Escape(cssClass, escapedCSSClass, url_Path
), "!NS_Escape(cssClass, escapedCSSClass, url_Path)", "./../../../docshell/base/nsDocShell.cpp"
, 3793)) { return NS_ERROR_OUT_OF_MEMORY; }
;
3794 }
3795 nsCString errorPageUrl("about:");
3796 errorPageUrl.AppendASCII(aErrorPage);
3797 errorPageUrl.AppendLiteral("?e=");
3798
3799 errorPageUrl.AppendASCII(escapedError.get());
3800 errorPageUrl.AppendLiteral("&u=");
3801 errorPageUrl.AppendASCII(escapedUrl.get());
3802 if ((strcmp(aErrorPage, "blocked") == 0) &&
3803 Preferences::GetBool(PREF_SAFEBROWSING_ALLOWOVERRIDE"browser.safebrowsing.allowOverride", true)) {
3804 errorPageUrl.AppendLiteral("&o=1");
3805 }
3806 if (!escapedCSSClass.IsEmpty()) {
3807 errorPageUrl.AppendLiteral("&s=");
3808 errorPageUrl.AppendASCII(escapedCSSClass.get());
3809 }
3810 errorPageUrl.AppendLiteral("&c=UTF-8");
3811
3812 nsCOMPtr<nsICaptivePortalService> cps = do_GetService(NS_CAPTIVEPORTAL_CID{ 0xbdbe0555, 0xfc3d, 0x4f7b, {0x92, 0x05, 0xc3, 0x09, 0xce, 0xb2
, 0xd6, 0x41}}
);
3813 int32_t cpsState;
3814 if (cps && NS_SUCCEEDED(cps->GetState(&cpsState))((bool)(__builtin_expect(!!(!NS_FAILED_impl(cps->GetState(
&cpsState))), 1)))
) {
3815 if (cpsState == nsICaptivePortalService::LOCKED_PORTAL) {
3816 errorPageUrl.AppendLiteral("&captive=true");
3817 }
3818 if (strcmp(aErrorPage, "neterror") == 0) {
3819 static const char* const kCaptivePortalStateNames[] = {
3820 "unknown", "not_captive", "unlocked_portal", "locked_portal"};
3821 if (cpsState >= 0 &&
3822 size_t(cpsState) < std::size(kCaptivePortalStateNames)) {
3823 errorPageUrl.AppendLiteral("&captivePortalState=");
3824 errorPageUrl.AppendASCII(kCaptivePortalStateNames[cpsState]);
3825 }
3826 }
3827 }
3828
3829 errorPageUrl.AppendLiteral("&d=");
3830 errorPageUrl.AppendASCII(escapedDescription.get());
3831
3832 nsCOMPtr<nsIWritablePropertyBag2> props(do_QueryInterface(aFailedChannel));
3833 if (props) {
3834 nsAutoCString addonName;
3835 props->GetPropertyAsACString(u"blockedExtension"_ns, addonName);
3836
3837 nsCString escapedAddonName;
3838 SAFE_ESCAPE(escapedAddonName, addonName, url_Path)if (NS_warn_if_impl(!NS_Escape(addonName, escapedAddonName, url_Path
), "!NS_Escape(addonName, escapedAddonName, url_Path)", "./../../../docshell/base/nsDocShell.cpp"
, 3838)) { return NS_ERROR_OUT_OF_MEMORY; }
;
3839
3840 errorPageUrl.AppendLiteral("&a=");
3841 errorPageUrl.AppendASCII(escapedAddonName.get());
3842 }
3843
3844 nsCOMPtr<nsIURI> errorPageURI;
3845 nsresult rv = NS_NewURI(getter_AddRefs(errorPageURI), errorPageUrl);
3846 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, "./../../../docshell/base/nsDocShell.cpp"
, 3846); return rv; } } while (false)
;
3847
3848 return LoadErrorPage(errorPageURI, aURI, aFailedChannel);
3849}
3850
3851nsresult nsDocShell::LoadErrorPage(nsIURI* aErrorURI, nsIURI* aFailedURI,
3852 nsIChannel* aFailedChannel) {
3853 mFailedChannel = aFailedChannel;
3854 mFailedURI = aFailedURI;
3855 mFailedLoadType = mLoadType;
3856
3857 RefPtr loadState = MakeRefPtr<nsDocShellLoadState>(aErrorURI);
3858 loadState->SetTriggeringPrincipal(nsContentUtils::GetSystemPrincipal());
3859 if (mBrowsingContext) {
3860 loadState->SetTriggeringSandboxFlags(mBrowsingContext->GetSandboxFlags());
3861 loadState->SetTriggeringWindowId(
3862 mBrowsingContext->GetCurrentInnerWindowId());
3863 nsPIDOMWindowInner* innerWin = mScriptGlobal->GetCurrentInnerWindow();
3864 if (innerWin) {
3865 loadState->SetTriggeringStorageAccess(innerWin->UsingStorageAccess());
3866 }
3867 }
3868 loadState->SetLoadType(LOAD_ERROR_PAGE);
3869 loadState->SetFirstParty(true);
3870 loadState->SetSourceBrowsingContext(mBrowsingContext);
3871 if (mLoadingEntry) {
3872 // We keep the loading entry for the load that failed here. If the user
3873 // reloads we want to try to reload the original load, not the error page.
3874 loadState->SetLoadingSessionHistoryInfo(
3875 MakeUnique<LoadingSessionHistoryInfo>(*mLoadingEntry));
3876 }
3877
3878 // Prevent initial about:blank handling, as it's likely irrelevant and
3879 // keeps us from needing to change GeckoView / NavigationDelegateTest.
3880 // It also makes the load more consistent with non-about-blank cases.
3881 loadState->ProhibitInitialAboutBlankHandling();
3882
3883 return InternalLoad(loadState);
3884}
3885
3886MOZ_CAN_RUN_SCRIPT_BOUNDARY NS_IMETHODIMPnsresult
3887nsDocShell::Reload(uint32_t aReloadFlags) {
3888 return ReloadNavigable(Nothing(), aReloadFlags, nullptr,
3889 UserNavigationInvolvement::BrowserUI);
3890}
3891
3892// https://html.spec.whatwg.org/#reload
3893// To reload a navigable navigable given an optional serialized state-or-null
3894// navigationAPIState (default null) and an optional user navigation
3895// involvement userInvolvement (default "none"):
3896nsresult nsDocShell::ReloadNavigable(
3897 mozilla::Maybe<NotNull<JSContext*>> aCx, uint32_t aReloadFlags,
3898 nsIStructuredCloneContainer* aNavigationAPIState,
3899 UserNavigationInvolvement aUserInvolvement,
3900 NavigationAPIMethodTracker* aNavigationAPIMethodTracker) {
3901 AUTO_PROFILER_MARKER_UNTYPED(AutoProfilerUntypedMarker raiiObject3904( "nsDocShell:ReloadNavigable"
, ::mozilla::baseprofiler::category::DOM, MarkerOptions(MarkerStack
::Capture(), MarkerInnerWindowIdFromDocShell(this)))
3902 "nsDocShell:ReloadNavigable", DOM,AutoProfilerUntypedMarker raiiObject3904( "nsDocShell:ReloadNavigable"
, ::mozilla::baseprofiler::category::DOM, MarkerOptions(MarkerStack
::Capture(), MarkerInnerWindowIdFromDocShell(this)))
3903 MarkerOptions(MarkerStack::Capture(),AutoProfilerUntypedMarker raiiObject3904( "nsDocShell:ReloadNavigable"
, ::mozilla::baseprofiler::category::DOM, MarkerOptions(MarkerStack
::Capture(), MarkerInnerWindowIdFromDocShell(this)))
3904 MarkerInnerWindowIdFromDocShell(this)))AutoProfilerUntypedMarker raiiObject3904( "nsDocShell:ReloadNavigable"
, ::mozilla::baseprofiler::category::DOM, MarkerOptions(MarkerStack
::Capture(), MarkerInnerWindowIdFromDocShell(this)))
;
3905
3906 if (!IsNavigationAllowed()) {
3907 return NS_OK; // JS may not handle returning of an error code
3908 }
3909
3910 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)"
, "./../../../docshell/base/nsDocShell.cpp", 3911); MOZ_PretendNoReturn
(); } } while (0)
3911 "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)"
, "./../../../docshell/base/nsDocShell.cpp", 3911); MOZ_PretendNoReturn
(); } } while (0)
;
3912 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"
, "./../../../docshell/base/nsDocShell.cpp", 3913); MOZ_PretendNoReturn
(); } } while (0)
3913 "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"
, "./../../../docshell/base/nsDocShell.cpp", 3913); MOZ_PretendNoReturn
(); } } while (0)
;
3914
3915 uint32_t loadType = MAKE_LOAD_TYPE(LOAD_RELOAD_NORMAL, aReloadFlags)((LOAD_RELOAD_NORMAL) | ((aReloadFlags) << 16));
3916 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, "./../../../docshell/base/nsDocShell.cpp"
, 3916); return NS_ERROR_INVALID_ARG; } } while (false)
;
3917 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, "./../../../docshell/base/nsDocShell.cpp"
, 3919); return NS_ERROR_INVALID_ARG; } } while (false)
3918 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, "./../../../docshell/base/nsDocShell.cpp"
, 3919); return NS_ERROR_INVALID_ARG; } } while (false)
3919 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, "./../../../docshell/base/nsDocShell.cpp"
, 3919); return NS_ERROR_INVALID_ARG; } } while (false)
;
3920
3921 RefPtr<nsDocShell> docShell(this);
3922
3923 // 1. If userInvolvement is not "browser UI", then:
3924 if (aUserInvolvement != UserNavigationInvolvement::BrowserUI) {
3925 // 1.1 Let navigation be navigable's active window's navigation API.
3926 nsPIDOMWindowOuter* windowOuter = GetWindow();
3927 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", "./../../../docshell/base/nsDocShell.cpp"
, 3927); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "windowOuter"
")"); do { MOZ_CrashSequence(__null, 3927); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3928 nsPIDOMWindowInner* windowInner = windowOuter->GetCurrentInnerWindow();
3929 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", "./../../../docshell/base/nsDocShell.cpp"
, 3929); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "windowInner"
")"); do { MOZ_CrashSequence(__null, 3929); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3930 RefPtr navigation = windowInner->Navigation();
3931
3932 // 1.2 Let destinationNavigationAPIState be navigable's active session
3933 // history entry's navigation API state.
3934 // 1.3 If navigationAPIState is not null, then set
3935 // destinationNavigationAPIState to navigationAPIState.
3936 RefPtr<nsIStructuredCloneContainer> destinationNavigationAPIState =
3937 aNavigationAPIState;
3938 if (!destinationNavigationAPIState) {
3939 destinationNavigationAPIState =
3940 mActiveEntry ? mActiveEntry->GetNavigationAPIState() : nullptr;
3941 }
3942
3943 // 1.4 Let continue be the result of firing a push/replace/reload navigate
3944 // event at navigation with navigationType set to "reload",
3945 // isSameDocument set to false, userInvolvement set to userInvolvement,
3946 // destinationURL set to navigable's active session history entry's URL,
3947 // and navigationAPIState set to destinationNavigationAPIState.
3948 // 1.5 If continue is false, then return.
3949 RefPtr destinationURL = mActiveEntry ? mActiveEntry->GetURI() : nullptr;
3950 if (navigation &&
3951 !navigation->FirePushReplaceReloadNavigateEvent(
3952 *aCx, NavigationType::Reload, destinationURL,
3953 /* aIsSameDocument */ false, Some(aUserInvolvement),
3954 /* aSourceElement*/ nullptr, /* aFormDataEntryList */ nullptr,
3955 destinationNavigationAPIState,
3956 /* aClassiCHistoryAPIState */ nullptr,
3957 aNavigationAPIMethodTracker)) {
3958 return NS_OK;
3959 }
3960 }
3961
3962 // The following steps are implemented by the remainder of ReloadNavigable.
3963
3964 // Send notifications to the HistoryListener if any, about the impending
3965 // reload
3966 RefPtr<ChildSHistory> rootSH = GetRootSessionHistory();
3967 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)
;
3968 bool forceReload = IsForceReloadType(loadType);
3969 if (!XRE_IsParentProcess()) {
3970 ++mPendingReloadCount;
3971 nsCOMPtr<nsIDocumentViewer> viewer(mDocumentViewer);
3972 NS_ENSURE_STATE(viewer)do { if ((__builtin_expect(!!(!(viewer)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "viewer" ") failed", nullptr
, "./../../../docshell/base/nsDocShell.cpp", 3972); return NS_ERROR_UNEXPECTED
; } } while (false)
;
3973
3974 bool okToUnload = true;
3975 MOZ_TRY(viewer->PermitUnload(&okToUnload))__extension__({ auto mozTryVarTempResult = ::mozilla::ToResult
(viewer->PermitUnload(&okToUnload)); if ((__builtin_expect
(!!(mozTryVarTempResult.isErr()), 0))) { return mozTryVarTempResult
.propagateErr(); } mozTryVarTempResult.unwrap(); })
;
3976 if (mIsBeingDestroyed) {
3977 // unload handler destroyed this docshell.
3978 return NS_ERROR_NOT_AVAILABLE;
3979 }
3980 if (!okToUnload) {
3981 return NS_OK;
3982 }
3983
3984 RefPtr<Document> doc(GetDocument());
3985 RefPtr<BrowsingContext> browsingContext(mBrowsingContext);
3986 nsCOMPtr<nsIURI> currentURI(mCurrentURI);
3987 nsCOMPtr<nsIReferrerInfo> referrerInfo(mReferrerInfo);
3988 RefPtr stopDetector = MakeRefPtr<StopDetector>();
3989 nsCOMPtr<nsILoadGroup> loadGroup;
3990 GetLoadGroup(getter_AddRefs(loadGroup));
3991 if (loadGroup) {
3992 // loadGroup may be null in theory. In that case stopDetector just
3993 // doesn't do anything.
3994 loadGroup->AddRequest(stopDetector, nullptr);
3995 }
3996
3997 ContentChild::GetSingleton()->SendNotifyOnHistoryReload(
3998 mBrowsingContext, forceReload,
3999 [docShell, doc, loadType, browsingContext, currentURI, referrerInfo,
4000 loadGroup, stopDetector](
4001 std::tuple<bool, Maybe<NotNull<RefPtr<nsDocShellLoadState>>>,
4002 Maybe<bool>>&& aResult) {
4003 auto scopeExit = MakeScopeExit([loadGroup, stopDetector]() {
4004 if (loadGroup) {
4005 loadGroup->RemoveRequest(stopDetector, nullptr, NS_OK);
4006 }
4007 });
4008
4009 // Decrease mPendingReloadCount before any other early returns!
4010 if (--(docShell->mPendingReloadCount) > 0) {
4011 return;
4012 }
4013
4014 if (stopDetector->Canceled()) {
4015 return;
4016 }
4017 bool canReload;
4018 Maybe<NotNull<RefPtr<nsDocShellLoadState>>> loadState;
4019 Maybe<bool> reloadingActiveEntry;
4020
4021 std::tie(canReload, loadState, reloadingActiveEntry) = aResult;
4022
4023 if (!canReload) {
4024 return;
4025 }
4026
4027 if (loadState.isSome()) {
4028 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)
4029 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)
4030 ("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)
;
4031 loadState.ref()->SetNotifiedBeforeUnloadListeners(true);
4032 docShell->LoadHistoryEntry(loadState.ref(), loadType,
4033 reloadingActiveEntry.ref());
4034 } else {
4035 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)
4036 ("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)
;
4037 ReloadDocument(docShell, doc, loadType, browsingContext, currentURI,
4038 referrerInfo,
4039 /* aNotifiedBeforeUnloadListeners */ true);
4040 }
4041 },
4042 [](mozilla::ipc::ResponseRejectReason) {});
4043 } else {
4044 // Parent process
4045 bool canReload = false;
4046 Maybe<NotNull<RefPtr<nsDocShellLoadState>>> loadState;
4047 Maybe<bool> reloadingActiveEntry;
4048 if (!mBrowsingContext->IsDiscarded()) {
4049 mBrowsingContext->Canonical()->NotifyOnHistoryReload(
4050 forceReload, canReload, loadState, reloadingActiveEntry);
4051 }
4052 if (canReload) {
4053 if (loadState.isSome()) {
4054 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)
4055 ("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)
;
4056 LoadHistoryEntry(loadState.ref(), loadType, reloadingActiveEntry.ref());
4057 } else {
4058 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)
4059 ("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)
;
4060 RefPtr<Document> doc = GetDocument();
4061 RefPtr<BrowsingContext> bc = mBrowsingContext;
4062 nsCOMPtr<nsIURI> currentURI = mCurrentURI;
4063 nsCOMPtr<nsIReferrerInfo> referrerInfo = mReferrerInfo;
4064 ReloadDocument(this, doc, loadType, bc, currentURI, referrerInfo);
4065 }
4066 }
4067 }
4068 return NS_OK;
4069}
4070
4071void nsDocShell::DisplayRestrictedContentError() {
4072 bool didDisplayLoadError = false;
4073 RefPtr<mozilla::dom::Document> doc = GetDocument();
4074 if (!doc) {
4075 return;
4076 }
4077 doc->TerminateParserAndDisableScripts();
4078 DisplayLoadError(NS_ERROR_RESTRICTED_CONTENT, doc->GetDocumentURI(), nullptr,
4079 nullptr, &didDisplayLoadError);
4080}
4081
4082/* static */
4083nsresult nsDocShell::ReloadDocument(nsDocShell* aDocShell, Document* aDocument,
4084 uint32_t aLoadType,
4085 BrowsingContext* aBrowsingContext,
4086 nsIURI* aCurrentURI,
4087 nsIReferrerInfo* aReferrerInfo,
4088 bool aNotifiedBeforeUnloadListeners) {
4089 if (!aDocument) {
4090 return NS_OK;
4091 }
4092
4093 // Do not inherit owner from document
4094 uint32_t flags = INTERNAL_LOAD_FLAGS_NONE;
4095 nsAutoString srcdoc;
4096 nsIURI* baseURI = nullptr;
4097 nsCOMPtr<nsIURI> originalURI;
4098 nsCOMPtr<nsIURI> resultPrincipalURI;
4099 bool loadReplace = false;
4100
4101 nsIPrincipal* triggeringPrincipal = aDocument->NodePrincipal();
4102 nsCOMPtr<nsIPolicyContainer> policyContainer =
4103 aDocument->GetPolicyContainer();
4104 uint32_t triggeringSandboxFlags = aDocument->GetSandboxFlags();
4105 uint64_t triggeringWindowId = aDocument->InnerWindowID();
4106 bool triggeringStorageAccess = aDocument->UsingStorageAccess();
4107 net::ClassificationFlags triggeringClassificationFlags =
4108 aDocument->GetScriptTrackingFlags();
4109
4110 nsAutoString contentTypeHint;
4111 aDocument->GetContentType(contentTypeHint);
4112
4113 if (aDocument->IsSrcdocDocument()) {
4114 aDocument->GetSrcdocData(srcdoc);
4115 flags |= INTERNAL_LOAD_FLAGS_IS_SRCDOC;
4116 baseURI = aDocument->GetBaseURI();
4117 } else {
4118 srcdoc = VoidString();
4119 }
4120 nsCOMPtr<nsIChannel> chan = aDocument->GetChannel();
4121 if (chan) {
4122 uint32_t loadFlags;
4123 chan->GetLoadFlags(&loadFlags);
4124 loadReplace = loadFlags & nsIChannel::LOAD_REPLACE;
4125 nsCOMPtr<nsIHttpChannel> httpChan(do_QueryInterface(chan));
4126 if (httpChan) {
4127 httpChan->GetOriginalURI(getter_AddRefs(originalURI));
4128 }
4129
4130 nsCOMPtr<nsILoadInfo> loadInfo = chan->LoadInfo();
4131 loadInfo->GetResultPrincipalURI(getter_AddRefs(resultPrincipalURI));
4132 }
4133
4134 if (!triggeringPrincipal) {
4135 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"
")", "./../../../docshell/base/nsDocShell.cpp", 4135); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "false" ") (" "Reload needs a valid triggeringPrincipal"
")"); do { MOZ_CrashSequence(__null, 4135); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4136 return NS_ERROR_FAILURE;
4137 }
4138
4139 // Stack variables to ensure changes to the member variables don't affect to
4140 // the call.
4141 nsCOMPtr<nsIURI> currentURI = aCurrentURI;
4142
4143 // Reload always rewrites result principal URI.
4144 Maybe<nsCOMPtr<nsIURI>> emplacedResultPrincipalURI;
4145 emplacedResultPrincipalURI.emplace(std::move(resultPrincipalURI));
4146
4147 RefPtr<WindowContext> context = aBrowsingContext->GetCurrentWindowContext();
4148 RefPtr loadState = MakeRefPtr<nsDocShellLoadState>(currentURI);
4149 loadState->SetReferrerInfo(aReferrerInfo);
4150 loadState->SetOriginalURI(originalURI);
4151 loadState->SetMaybeResultPrincipalURI(emplacedResultPrincipalURI);
4152 loadState->SetLoadReplace(loadReplace);
4153 loadState->SetTriggeringPrincipal(triggeringPrincipal);
4154 loadState->SetTriggeringSandboxFlags(triggeringSandboxFlags);
4155 loadState->SetTriggeringWindowId(triggeringWindowId);
4156 loadState->SetTriggeringStorageAccess(triggeringStorageAccess);
4157 loadState->SetTriggeringClassificationFlags(triggeringClassificationFlags);
4158 loadState->SetPrincipalToInherit(triggeringPrincipal);
4159 loadState->SetPolicyContainer(policyContainer);
4160 loadState->SetInternalLoadFlags(flags);
4161 loadState->SetTypeHint(NS_ConvertUTF16toUTF8(contentTypeHint));
4162 loadState->SetLoadType(aLoadType);
4163 loadState->SetFirstParty(true);
4164 loadState->SetSrcdocData(srcdoc);
4165 loadState->SetSourceBrowsingContext(aBrowsingContext);
4166 loadState->SetBaseURI(baseURI);
4167 loadState->SetHasValidUserGestureActivation(
4168 context && context->HasValidTransientUserGestureActivation());
4169
4170 loadState->SetTextDirectiveUserActivation(
4171 aDocument->ConsumeTextDirectiveUserActivation() ||
4172 loadState->HasValidUserGestureActivation());
4173
4174 loadState->SetNotifiedBeforeUnloadListeners(aNotifiedBeforeUnloadListeners);
4175 return aDocShell->InternalLoad(loadState);
4176}
4177
4178// TODO: Convert this to MOZ_CAN_RUN_SCRIPT (bug 1415230)
4179MOZ_CAN_RUN_SCRIPT_BOUNDARY NS_IMETHODIMPnsresult
4180nsDocShell::Stop(uint32_t aStopFlags) {
4181 return StopInternal(aStopFlags, UnsetOngoingNavigation::Yes);
4182}
4183
4184nsresult nsDocShell::StopInternal(
4185 uint32_t aStopFlags, UnsetOngoingNavigation aUnsetOngoingNavigation) {
4186 RefPtr kungFuDeathGrip = this;
4187 if (RefPtr<Document> doc = GetExtantDocument();
4188 aUnsetOngoingNavigation == UnsetOngoingNavigation::Yes && doc &&
4189 !doc->ShouldIgnoreOpens() &&
4190 mOngoingNavigation == Some(OngoingNavigation::NavigationID)) {
4191 SetOngoingNavigation(Nothing());
4192 }
4193
4194 if (mLoadType == LOAD_ERROR_PAGE) {
4195 mActiveEntryIsLoadingFromSessionHistory = false;
4196
4197 mFailedChannel = nullptr;
4198 mFailedURI = nullptr;
4199 }
4200
4201 if (nsIWebNavigation::STOP_CONTENT & aStopFlags) {
4202 // Stop the document loading and animations
4203 if (mDocumentViewer) {
4204 nsCOMPtr<nsIDocumentViewer> viewer = mDocumentViewer;
4205 viewer->Stop();
4206 }
4207 } else if (nsIWebNavigation::STOP_NETWORK & aStopFlags) {
4208 // Stop the document loading only
4209 if (mDocumentViewer) {
4210 RefPtr<Document> doc = mDocumentViewer->GetDocument();
4211 if (doc) {
4212 doc->StopDocumentLoad();
4213 }
4214 }
4215 }
4216
4217 if (nsIWebNavigation::STOP_NETWORK & aStopFlags) {
4218 // Suspend any timers that were set for this loader. We'll clear
4219 // them out for good in CreateDocumentViewer.
4220 if (mRefreshURIList) {
4221 SuspendRefreshURIs();
4222 mSavedRefreshURIList.swap(mRefreshURIList);
4223 mRefreshURIList = nullptr;
4224 }
4225
4226 // XXXbz We could also pass |this| to nsIURILoader::Stop. That will
4227 // just call Stop() on us as an nsIDocumentLoader... We need fewer
4228 // redundant apis!
4229 if (aUnsetOngoingNavigation == UnsetOngoingNavigation::No && mLoadGroup) {
4230 // Tag load group cancellation as navigation-caused so that XHR can
4231 // suppress abort events (bug 1505389). SetCanceledReason is
4232 // first-write-wins, so nsDocLoader::Stop's reason won't overwrite.
4233
4234 // XXX Consider using a flag on LoadGroup instead of CanceledReason
4235 mLoadGroup->SetCanceledReason("navigation"_ns);
4236 }
4237 // Cancel <form> planned navigations.
4238 // Not currently in the spec, but it follows other browsers' behaviour:
4239 // https://github.com/whatwg/html/issues/12609
4240 CancelPlannedFormNavigation();
4241 Stop();
4242
4243 // Clear out mChannelToDisconnectOnPageHide. This page won't go in the
4244 // BFCache now, and the Stop above will have removed the DocumentChannel
4245 // from the loadgroup.
4246 mChannelToDisconnectOnPageHide = 0;
4247 }
4248
4249 for (auto* child : mChildList.ForwardRange()) {
4250 nsCOMPtr<nsIWebNavigation> shellAsNav(do_QueryObject(child));
4251 if (shellAsNav) {
4252 shellAsNav->Stop(aStopFlags);
4253 }
4254 }
4255
4256 return NS_OK;
4257}
4258
4259NS_IMETHODIMPnsresult
4260nsDocShell::GetDocument(Document** aDocument) {
4261 NS_ENSURE_ARG_POINTER(aDocument)do { if ((__builtin_expect(!!(!(aDocument)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aDocument" ") failed", nullptr
, "./../../../docshell/base/nsDocShell.cpp", 4261); return NS_ERROR_INVALID_POINTER
; } } while (false)
;
4262 NS_ENSURE_TRUE(VerifyDocumentViewer(), NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(VerifyDocumentViewer())), 0))
) { NS_DebugBreak(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "VerifyDocumentViewer()"
") failed", nullptr, "./../../../docshell/base/nsDocShell.cpp"
, 4262); return NS_ERROR_FAILURE; } } while (false)
;
4263
4264 RefPtr<Document> doc = mDocumentViewer->GetDocument();
4265 if (!doc) {
4266 return NS_ERROR_NOT_AVAILABLE;
4267 }
4268
4269 doc.forget(aDocument);
4270 return NS_OK;
4271}
4272
4273NS_IMETHODIMPnsresult
4274nsDocShell::GetCurrentURI(nsIURI** aURI) {
4275 NS_ENSURE_ARG_POINTER(aURI)do { if ((__builtin_expect(!!(!(aURI)), 0))) { NS_DebugBreak(
NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aURI" ") failed", nullptr
, "./../../../docshell/base/nsDocShell.cpp", 4275); return NS_ERROR_INVALID_POINTER
; } } while (false)
;
4276
4277 nsCOMPtr<nsIURI> uri = mCurrentURI;
4278 uri.forget(aURI);
4279 return NS_OK;
4280}
4281
4282NS_IMETHODIMPnsresult
4283nsDocShell::GetSessionHistoryXPCOM(nsISupports** aSessionHistory) {
4284 NS_ENSURE_ARG_POINTER(aSessionHistory)do { if ((__builtin_expect(!!(!(aSessionHistory)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aSessionHistory" ") failed"
, nullptr, "./../../../docshell/base/nsDocShell.cpp", 4284); return
NS_ERROR_INVALID_POINTER; } } while (false)
;
4285 RefPtr<ChildSHistory> shistory = GetSessionHistory();
4286 shistory.forget(aSessionHistory);
4287 return NS_OK;
4288}
4289
4290//*****************************************************************************
4291// nsDocShell::nsIWebPageDescriptor
4292//*****************************************************************************
4293
4294NS_IMETHODIMPnsresult
4295nsDocShell::LoadPageAsViewSource(nsIDocShell* aOtherDocShell,
4296 const nsAString& aURI) {
4297 if (!aOtherDocShell) {
4298 return NS_ERROR_INVALID_POINTER;
4299 }
4300 auto* otherDocShell = nsDocShell::Cast(aOtherDocShell);
4301
4302 Document* otherDoc = otherDocShell->GetDocument();
4303 NS_ENSURE_TRUE(otherDoc, NS_ERROR_UNEXPECTED)do { if ((__builtin_expect(!!(!(otherDoc)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "otherDoc" ") failed", nullptr
, "./../../../docshell/base/nsDocShell.cpp", 4303); return NS_ERROR_UNEXPECTED
; } } while (false)
;
4304
4305 nsCOMPtr<nsIURI> newURI;
4306 nsresult rv = NS_NewURI(getter_AddRefs(newURI), aURI);
4307 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
4308 return rv;
4309 }
4310
4311 RefPtr loadState = MakeRefPtr<nsDocShellLoadState>(newURI);
4312 if (!otherDocShell->FillLoadStateFromCurrentEntry(*loadState)) {
4313 return NS_ERROR_INVALID_POINTER;
4314 }
4315 uint32_t cacheKey = otherDocShell->GetCacheKeyFromCurrentEntry().valueOr(0);
4316
4317 // We're doing a load of the page, via an API that
4318 // is only exposed to system code. The triggering principal for this load
4319 // should be the system principal.
4320 loadState->SetTriggeringPrincipal(nsContentUtils::GetSystemPrincipal());
4321 RefPtr<nsIPrincipal> nullPrincipal =
4322 NullPrincipal::CreateWithInheritedAttributes(otherDoc->NodePrincipal());
4323 loadState->SetPrincipalToInherit(nullPrincipal);
4324 loadState->SetPartitionedPrincipalToInherit(nullPrincipal);
4325 loadState->SetOriginalURI(nullptr);
4326 loadState->SetResultPrincipalURI(nullptr);
4327
4328 // Initial about:blank handling is probably irrelevant, but newURI shouldn't
4329 // anyway be about:blank. Otherwise we should prohibit initial about blank
4330 // handling.
4331 MOZ_ASSERT(!NS_IsAboutBlankAllowQueryAndFragment(newURI),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!NS_IsAboutBlankAllowQueryAndFragment(newURI))>::
isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!NS_IsAboutBlankAllowQueryAndFragment(newURI)))), 0)
)) { do { } while (false); MOZ_ReportAssertionFailure("!NS_IsAboutBlankAllowQueryAndFragment(newURI)"
" (" "We only expect view-source:// URIs" ")", "./../../../docshell/base/nsDocShell.cpp"
, 4332); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!NS_IsAboutBlankAllowQueryAndFragment(newURI)"
") (" "We only expect view-source:// URIs" ")"); do { MOZ_CrashSequence
(__null, 4332); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
4332 "We only expect view-source:// URIs")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!NS_IsAboutBlankAllowQueryAndFragment(newURI))>::
isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!NS_IsAboutBlankAllowQueryAndFragment(newURI)))), 0)
)) { do { } while (false); MOZ_ReportAssertionFailure("!NS_IsAboutBlankAllowQueryAndFragment(newURI)"
" (" "We only expect view-source:// URIs" ")", "./../../../docshell/base/nsDocShell.cpp"
, 4332); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!NS_IsAboutBlankAllowQueryAndFragment(newURI)"
") (" "We only expect view-source:// URIs" ")"); do { MOZ_CrashSequence
(__null, 4332); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
4333
4334 return InternalLoad(loadState, Some(cacheKey));
4335}
4336
4337already_AddRefed<nsIInputStream> nsDocShell::GetPostDataFromCurrentEntry()
4338 const {
4339 nsCOMPtr<nsIInputStream> postData;
4340 if (mActiveEntry) {
4341 postData = mActiveEntry->GetPostData();
4342 } else if (mLoadingEntry) {
4343 postData = mLoadingEntry->mInfo.GetPostData();
4344 }
4345
4346 return postData.forget();
4347}
4348
4349Maybe<uint32_t> nsDocShell::GetCacheKeyFromCurrentEntry() const {
4350 if (mActiveEntry) {
4351 return Some(mActiveEntry->GetCacheKey());
4352 }
4353
4354 if (mLoadingEntry) {
4355 return Some(mLoadingEntry->mInfo.GetCacheKey());
4356 }
4357
4358 return Nothing();
4359}
4360
4361bool nsDocShell::FillLoadStateFromCurrentEntry(
4362 nsDocShellLoadState& aLoadState) {
4363 if (mLoadingEntry) {
4364 mLoadingEntry->mInfo.FillLoadInfo(aLoadState);
4365 return true;
4366 }
4367 if (mActiveEntry) {
4368 mActiveEntry->FillLoadInfo(aLoadState);
4369 return true;
4370 }
4371 return false;
4372}
4373
4374//*****************************************************************************
4375// nsDocShell::nsIBaseWindow
4376//*****************************************************************************
4377
4378NS_IMETHODIMPnsresult
4379nsDocShell::Destroy() {
4380 // XXX: We allow this function to be called just once. If you are going to
4381 // reset new variables in this function, please make sure the variables will
4382 // never be re-initialized. Adding assertions to check |mIsBeingDestroyed|
4383 // in the setter functions for the variables would be enough.
4384 if (mIsBeingDestroyed) {
4385 return NS_ERROR_DOCSHELL_DYING;
4386 }
4387
4388 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", "./../../../docshell/base/nsDocShell.cpp"
, 4389); MOZ_PretendNoReturn(); } } while (0)
4389 "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", "./../../../docshell/base/nsDocShell.cpp"
, 4389); MOZ_PretendNoReturn(); } } while (0)
;
4390
4391 nsCOMPtr<nsIObserverService> serv = services::GetObserverService();
4392 if (serv) {
4393 const char* msg = mItemType == typeContent
4394 ? NS_WEBNAVIGATION_DESTROY"webnavigation-destroy"
4395 : NS_CHROME_WEBNAVIGATION_DESTROY"chrome-webnavigation-destroy";
4396 serv->NotifyObservers(GetAsSupports(this), msg, nullptr);
4397 }
4398
4399 mIsBeingDestroyed = true;
4400
4401 // Brak the cycle with the initial client, if present.
4402 mInitialClientSource.reset();
4403
4404 // Make sure to blow away our mLoadingURI just in case. No loads
4405 // from inside this pagehide.
4406 mLoadingURI = nullptr;
4407
4408 // Fire unload event before we blow anything away.
4409 (void)FirePageHideNotification();
4410
4411 // Note: mContentListener can be null if Init() failed and we're being
4412 // called from the destructor.
4413 if (mContentListener) {
4414 mContentListener->DropDocShellReference();
4415 mContentListener->SetParentContentListener(nullptr);
4416 // Note that we do NOT set mContentListener to null here; that
4417 // way if someone tries to do a load in us after this point
4418 // the nsDSURIContentListener will block it. All of which
4419 // means that we should do this before calling Stop(), of
4420 // course.
4421 }
4422
4423 if (BrowsingContext* browsingContext = GetBrowsingContext();
4424 browsingContext && !browsingContext->IsTop()) {
4425 InformNavigationAPIAboutChildNavigableDestruction();
4426 }
4427
4428 // Stop any URLs that are currently being loaded...
4429 Stop(nsIWebNavigation::STOP_ALL);
4430
4431 mEditorData = nullptr;
4432
4433 // Save the state of the current document, before destroying the window.
4434 // This is needed to capture the state of a frameset when the new document
4435 // causes the frameset to be destroyed...
4436 PersistLayoutHistoryState();
4437
4438 // Remove this docshell from its parent's child list
4439 nsCOMPtr<nsIDocShellTreeItem> docShellParentAsItem =
4440 do_QueryInterface(GetAsSupports(mParent));
4441 if (docShellParentAsItem) {
4442 docShellParentAsItem->RemoveChild(this);
4443 }
4444
4445 DestroyDocumentViewer();
4446
4447 nsDocLoader::Destroy();
4448
4449 mParentWidget = nullptr;
4450 SetCurrentURIInternal(nullptr);
4451
4452 if (mScriptGlobal) {
4453 mScriptGlobal->DetachFromDocShell(!mWillChangeProcess);
4454 mScriptGlobal = nullptr;
4455 }
4456
4457 if (mWillChangeProcess && !mBrowsingContext->IsDiscarded()) {
4458 mBrowsingContext->PrepareForProcessChange();
4459 }
4460
4461 SetTreeOwner(nullptr);
4462
4463 mBrowserChild = nullptr;
4464
4465 mChromeEventHandler = nullptr;
4466
4467 mBCWebProgressStatusFilter = nullptr;
4468
4469 // Cancel any timers that were set for this docshell; this is needed
4470 // to break the cycle between us and the timers.
4471 CancelRefreshURITimers();
4472
4473 return NS_OK;
4474}
4475
4476double nsDocShell::GetWidgetCSSToDeviceScale() {
4477 if (mParentWidget) {
4478 return mParentWidget->GetDefaultScale().scale;
4479 }
4480 if (nsCOMPtr<nsIBaseWindow> ownerWindow = do_QueryInterface(mTreeOwner)) {
4481 return ownerWindow->GetWidgetCSSToDeviceScale();
4482 }
4483 return 1.0;
4484}
4485
4486NS_IMETHODIMPnsresult
4487nsDocShell::GetDevicePixelsPerDesktopPixel(double* aScale) {
4488 if (mParentWidget) {
4489 *aScale = mParentWidget->GetDesktopToDeviceScale().scale;
4490 return NS_OK;
4491 }
4492
4493 nsCOMPtr<nsIBaseWindow> ownerWindow(do_QueryInterface(mTreeOwner));
4494 if (ownerWindow) {
4495 return ownerWindow->GetDevicePixelsPerDesktopPixel(aScale);
4496 }
4497
4498 *aScale = 1.0;
4499 return NS_OK;
4500}
4501
4502NS_IMETHODIMPnsresult
4503nsDocShell::SetPosition(int32_t aX, int32_t aY) {
4504 mBounds.MoveTo(aX, aY);
4505
4506 if (mDocumentViewer) {
4507 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, "./../../../docshell/base/nsDocShell.cpp"
, 4507); return NS_ERROR_FAILURE; } } while (false)
;
4508 }
4509
4510 return NS_OK;
4511}
4512
4513NS_IMETHODIMPnsresult
4514nsDocShell::SetPositionDesktopPix(int32_t aX, int32_t aY) {
4515 nsCOMPtr<nsIBaseWindow> ownerWindow(do_QueryInterface(mTreeOwner));
4516 if (ownerWindow) {
4517 return ownerWindow->SetPositionDesktopPix(aX, aY);
4518 }
4519
4520 double scale = 1.0;
4521 GetDevicePixelsPerDesktopPixel(&scale);
4522 return SetPosition(NSToIntRound(aX * scale), NSToIntRound(aY * scale));
4523}
4524
4525NS_IMETHODIMPnsresult
4526nsDocShell::GetPosition(int32_t* aX, int32_t* aY) {
4527 return GetPositionAndSize(aX, aY, nullptr, nullptr);
4528}
4529
4530NS_IMETHODIMPnsresult
4531nsDocShell::SetSize(int32_t aWidth, int32_t aHeight, bool aRepaint) {
4532 int32_t x = 0, y = 0;
4533 GetPosition(&x, &y);
4534 return SetPositionAndSize(x, y, aWidth, aHeight,
4535 aRepaint ? nsIBaseWindow::eRepaint : 0);
4536}
4537
4538NS_IMETHODIMPnsresult
4539nsDocShell::GetSize(int32_t* aWidth, int32_t* aHeight) {
4540 return GetPositionAndSize(nullptr, nullptr, aWidth, aHeight);
4541}
4542
4543NS_IMETHODIMPnsresult
4544nsDocShell::SetPositionAndSize(int32_t aX, int32_t aY, int32_t aWidth,
4545 int32_t aHeight, uint32_t aFlags) {
4546 mBounds.SetRect(aX, aY, aWidth, aHeight);
4547
4548 // Hold strong ref, since SetBounds can make us null out mDocumentViewer
4549 nsCOMPtr<nsIDocumentViewer> viewer = mDocumentViewer;
4550 if (viewer) {
4551 uint32_t cvflags = (aFlags & nsIBaseWindow::eDelayResize)
4552 ? nsIDocumentViewer::eDelayResize
4553 : 0;
4554 // XXX Border figured in here or is that handled elsewhere?
4555 nsresult rv = viewer->SetBoundsWithFlags(mBounds, cvflags);
4556 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
, "./../../../docshell/base/nsDocShell.cpp", 4556); return NS_ERROR_FAILURE
; } } while (false)
;
4557 }
4558
4559 if (nsCOMPtr<nsIObserverService> obs = services::GetObserverService()) {
4560 obs->NotifyObservers(GetAsSupports(this), "docshell-position-size-changed",
4561 nullptr);
4562 }
4563
4564 return NS_OK;
4565}
4566
4567NS_IMETHODIMPnsresult
4568nsDocShell::GetPositionAndSize(int32_t* aX, int32_t* aY, int32_t* aWidth,
4569 int32_t* aHeight) {
4570 if (mParentWidget) {
4571 // ensure size is up-to-date if window has changed resolution
4572 LayoutDeviceIntRect r = mParentWidget->GetClientBounds();
4573 SetPositionAndSize(mBounds.X(), mBounds.Y(), r.Width(), r.Height(), 0);
4574 }
4575
4576 // We should really consider just getting this information from
4577 // our window instead of duplicating the storage and code...
4578 if (aWidth || aHeight) {
4579 // Caller wants to know our size; make sure to give them up to
4580 // date information.
4581 RefPtr<Document> doc(do_GetInterface(GetAsSupports(mParent)));
4582 if (doc) {
4583 doc->FlushPendingNotifications(FlushType::Layout);
4584 }
4585 }
4586
4587 DoGetPositionAndSize(aX, aY, aWidth, aHeight);
4588 return NS_OK;
4589}
4590
4591void nsDocShell::DoGetPositionAndSize(int32_t* aX, int32_t* aY, int32_t* aWidth,
4592 int32_t* aHeight) {
4593 if (aX) {
4594 *aX = mBounds.X();
4595 }
4596 if (aY) {
4597 *aY = mBounds.Y();
4598 }
4599 if (aWidth) {
4600 *aWidth = mBounds.Width();
4601 }
4602 if (aHeight) {
4603 *aHeight = mBounds.Height();
4604 }
4605}
4606
4607NS_IMETHODIMPnsresult
4608nsDocShell::SetDimensions(DimensionRequest&& aRequest) {
4609 return NS_ERROR_NOT_IMPLEMENTED;
4610}
4611
4612NS_IMETHODIMPnsresult
4613nsDocShell::GetDimensions(DimensionKind aDimensionKind, int32_t* aX,
4614 int32_t* aY, int32_t* aCX, int32_t* aCY) {
4615 return NS_ERROR_NOT_IMPLEMENTED;
4616}
4617
4618NS_IMETHODIMPnsresult
4619nsDocShell::GetParentWidget(nsIWidget** aParentWidget) {
4620 NS_ENSURE_ARG_POINTER(aParentWidget)do { if ((__builtin_expect(!!(!(aParentWidget)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aParentWidget" ") failed"
, nullptr, "./../../../docshell/base/nsDocShell.cpp", 4620); return
NS_ERROR_INVALID_POINTER; } } while (false)
;
4621
4622 *aParentWidget = mParentWidget;
4623 NS_IF_ADDREF(*aParentWidget)ns_if_addref(*aParentWidget);
4624
4625 return NS_OK;
4626}
4627
4628NS_IMETHODIMPnsresult
4629nsDocShell::SetParentWidget(nsIWidget* aParentWidget) {
4630 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"
, "./../../../docshell/base/nsDocShell.cpp", 4630); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!mIsBeingDestroyed" ")"); do { MOZ_CrashSequence
(__null, 4630); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
4631 mParentWidget = aParentWidget;
4632
4633 return NS_OK;
4634}
4635
4636NS_IMETHODIMPnsresult
4637nsDocShell::GetNativeHandle(nsAString& aNativeHandle) {
4638 // the nativeHandle should be accessed from nsIAppWindow
4639 return NS_ERROR_NOT_IMPLEMENTED;
4640}
4641
4642NS_IMETHODIMPnsresult
4643nsDocShell::GetVisibility(bool* aVisibility) {
4644 NS_ENSURE_ARG_POINTER(aVisibility)do { if ((__builtin_expect(!!(!(aVisibility)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aVisibility" ") failed"
, nullptr, "./../../../docshell/base/nsDocShell.cpp", 4644); return
NS_ERROR_INVALID_POINTER; } } while (false)
;
4645
4646 *aVisibility = false;
4647
4648 if (!mDocumentViewer) {
4649 return NS_OK;
4650 }
4651
4652 PresShell* presShell = GetPresShell();
4653 if (!presShell || presShell->IsUnderHiddenEmbedderElement()) {
4654 // NOTE(emilio): IsUnderHiddenEmbedderElement() accounts for ancestors as
4655 // well.
4656 return NS_OK;
4657 }
4658
4659 nsCOMPtr<nsIBaseWindow> treeOwnerAsWin(do_QueryInterface(mTreeOwner));
4660 if (!treeOwnerAsWin) {
4661 *aVisibility = true;
4662 return NS_OK;
4663 }
4664
4665 // Check with the tree owner as well to give embedders a chance to
4666 // expose visibility as well.
4667 nsresult rv = treeOwnerAsWin->GetVisibility(aVisibility);
4668 if (rv == NS_ERROR_NOT_IMPLEMENTED) {
4669 // The tree owner had no opinion on our visibility.
4670 *aVisibility = true;
4671 return NS_OK;
4672 }
4673 return rv;
4674}
4675
4676void nsDocShell::ActivenessMaybeChanged() {
4677 const bool isActive = mBrowsingContext->IsActive();
4678 if (RefPtr<PresShell> presShell = GetPresShell()) {
4679 presShell->ActivenessMaybeChanged();
4680 }
4681
4682 // Tell the window about it
4683 if (mScriptGlobal) {
4684 mScriptGlobal->SetIsBackground(!isActive);
4685 if (RefPtr<Document> doc = mScriptGlobal->GetExtantDoc()) {
4686 // Update orientation when the top-level browsing context becomes active.
4687 if (isActive && mBrowsingContext->IsTop() &&
4688 !mBrowsingContext->Windowless()) {
4689 // We only care about the top-level browsing context.
4690 auto orientation = mBrowsingContext->GetOrientationLock();
4691 ScreenOrientation::UpdateActiveOrientationLock(orientation);
4692 }
4693
4694 doc->PostVisibilityUpdateEvent();
4695 }
4696 }
4697
4698 // Tell the nsDOMNavigationTiming about it
4699 RefPtr<nsDOMNavigationTiming> timing = mTiming;
4700 if (!timing && mDocumentViewer) {
4701 if (Document* doc = mDocumentViewer->GetDocument()) {
4702 timing = doc->GetNavigationTiming();
4703 }
4704 }
4705 if (timing) {
4706 timing->NotifyDocShellStateChanged(
4707 isActive ? nsDOMNavigationTiming::DocShellState::eActive
4708 : nsDOMNavigationTiming::DocShellState::eInactive);
4709 }
4710
4711 // Restart or stop meta refresh timers if necessary
4712 if (mDisableMetaRefreshWhenInactive) {
4713 if (isActive) {
4714 ResumeRefreshURIs();
4715 } else {
4716 SuspendRefreshURIs();
4717 }
4718 }
4719
4720 if (InputTaskManager::CanSuspendInputEvent()) {
4721 mBrowsingContext->Group()->UpdateInputTaskManagerIfNeeded(isActive);
4722 }
4723}
4724
4725NS_IMETHODIMPnsresult
4726nsDocShell::SetDefaultLoadFlags(uint32_t aDefaultLoadFlags) {
4727 if (!mWillChangeProcess) {
4728 // Intentionally ignoring handling discarded browsing contexts.
4729 (void)mBrowsingContext->SetDefaultLoadFlags(aDefaultLoadFlags);
4730 } else {
4731 // Bug 1623565: DevTools tries to clean up defaultLoadFlags on
4732 // shutdown. Sorry DevTools, your DocShell is in another process.
4733 NS_WARNING("nsDocShell::SetDefaultLoadFlags called on Zombie DocShell")NS_DebugBreak(NS_DEBUG_WARNING, "nsDocShell::SetDefaultLoadFlags called on Zombie DocShell"
, nullptr, "./../../../docshell/base/nsDocShell.cpp", 4733)
;
4734 }
4735 return NS_OK;
4736}
4737
4738NS_IMETHODIMPnsresult
4739nsDocShell::GetDefaultLoadFlags(uint32_t* aDefaultLoadFlags) {
4740 *aDefaultLoadFlags = mBrowsingContext->GetDefaultLoadFlags();
4741 return NS_OK;
4742}
4743
4744NS_IMETHODIMPnsresult
4745nsDocShell::GetFailedChannel(nsIChannel** aFailedChannel) {
4746 NS_ENSURE_ARG_POINTER(aFailedChannel)do { if ((__builtin_expect(!!(!(aFailedChannel)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aFailedChannel" ") failed"
, nullptr, "./../../../docshell/base/nsDocShell.cpp", 4746); return
NS_ERROR_INVALID_POINTER; } } while (false)
;
4747 Document* doc = GetDocument();
4748 if (!doc) {
4749 *aFailedChannel = nullptr;
4750 return NS_OK;
4751 }
4752 NS_IF_ADDREF(*aFailedChannel = doc->GetFailedChannel())ns_if_addref(*aFailedChannel = doc->GetFailedChannel());
4753 return NS_OK;
4754}
4755
4756NS_IMETHODIMPnsresult
4757nsDocShell::SetVisibility(bool aVisibility) {
4758 // Show()/Hide() may change mDocumentViewer.
4759 nsCOMPtr<nsIDocumentViewer> viewer = mDocumentViewer;
4760 if (!viewer) {
4761 return NS_OK;
4762 }
4763 if (aVisibility) {
4764 viewer->Show();
4765 } else {
4766 viewer->Hide();
4767 }
4768
4769 return NS_OK;
4770}
4771
4772NS_IMETHODIMPnsresult
4773nsDocShell::GetEnabled(bool* aEnabled) {
4774 NS_ENSURE_ARG_POINTER(aEnabled)do { if ((__builtin_expect(!!(!(aEnabled)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aEnabled" ") failed", nullptr
, "./../../../docshell/base/nsDocShell.cpp", 4774); return NS_ERROR_INVALID_POINTER
; } } while (false)
;
4775 *aEnabled = true;
4776 return NS_ERROR_NOT_IMPLEMENTED;
4777}
4778
4779NS_IMETHODIMPnsresult
4780nsDocShell::SetEnabled(bool aEnabled) { return NS_ERROR_NOT_IMPLEMENTED; }
4781
4782NS_IMETHODIMPnsresult
4783nsDocShell::GetMainWidget(nsIWidget** aMainWidget) {
4784 // We don't create our own widget, so simply return the parent one.
4785 return GetParentWidget(aMainWidget);
4786}
4787
4788NS_IMETHODIMPnsresult
4789nsDocShell::GetTitle(nsAString& aTitle) {
4790 aTitle = mTitle;
4791 return NS_OK;
4792}
4793
4794NS_IMETHODIMPnsresult
4795nsDocShell::SetTitle(const nsAString& aTitle) {
4796 // Avoid unnecessary updates of the title if the URI and the title haven't
4797 // changed.
4798 if (mTitleValidForCurrentURI && mTitle == aTitle) {
4799 return NS_OK;
4800 }
4801
4802 // Store local title
4803 mTitle = aTitle;
4804 mTitleValidForCurrentURI = true;
4805
4806 // When title is set on the top object it should then be passed to the
4807 // tree owner.
4808 if (mBrowsingContext->IsTop()) {
4809 nsCOMPtr<nsIBaseWindow> treeOwnerAsWin(do_QueryInterface(mTreeOwner));
4810 if (treeOwnerAsWin) {
4811 treeOwnerAsWin->SetTitle(aTitle);
4812 }
4813 }
4814
4815 if (mCurrentURI && mLoadType != LOAD_ERROR_PAGE) {
4816 UpdateGlobalHistoryTitle(mCurrentURI);
4817 }
4818
4819 // Update SessionHistory with the document's title.
4820 if (mLoadType != LOAD_BYPASS_HISTORY && mLoadType != LOAD_ERROR_PAGE) {
4821 SetTitleOnHistoryEntry(true);
4822 }
4823
4824 return NS_OK;
4825}
4826
4827void nsDocShell::SetTitleOnHistoryEntry(bool aUpdateEntryInSessionHistory) {
4828 if (mActiveEntry && mBrowsingContext) {
4829 mActiveEntry->SetTitle(mTitle);
4830 if (aUpdateEntryInSessionHistory) {
4831 if (XRE_IsParentProcess()) {
4832 SessionHistoryEntry* entry =
4833 mBrowsingContext->Canonical()->GetActiveSessionHistoryEntry();
4834 if (entry) {
4835 entry->SetTitle(mTitle);
4836 }
4837 } else {
4838 (void)ContentChild::GetSingleton()->SendSessionHistoryEntryTitle(
4839 mBrowsingContext, mTitle);
4840 }
4841 }
4842 }
4843}
4844
4845nsPoint nsDocShell::GetCurScrollPos() {
4846 nsPoint scrollPos;
4847 if (ScrollContainerFrame* sf = GetRootScrollContainerFrame()) {
4848 scrollPos = sf->GetVisualViewportOffset();
4849 }
4850 return scrollPos;
4851}
4852
4853nsresult nsDocShell::SetCurScrollPosEx(int32_t aCurHorizontalPos,
4854 int32_t aCurVerticalPos) {
4855 ScrollContainerFrame* sf = GetRootScrollContainerFrame();
4856 NS_ENSURE_TRUE(sf, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(sf)), 0))) { NS_DebugBreak(NS_DEBUG_WARNING
, "NS_ENSURE_TRUE(" "sf" ") failed", nullptr, "./../../../docshell/base/nsDocShell.cpp"
, 4856); return NS_ERROR_FAILURE; } } while (false)
;
4857
4858 ScrollMode scrollMode = sf->ScrollModeForScrollBehavior();
4859
4860 nsPoint targetPos(aCurHorizontalPos, aCurVerticalPos);
4861 sf->ScrollTo(targetPos, scrollMode);
4862
4863 // Set the visual viewport offset as well.
4864
4865 RefPtr<PresShell> presShell = GetPresShell();
4866 NS_ENSURE_TRUE(presShell, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(presShell)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "presShell" ") failed", nullptr
, "./../../../docshell/base/nsDocShell.cpp", 4866); return NS_ERROR_FAILURE
; } } while (false)
;
4867
4868 nsPresContext* presContext = presShell->GetPresContext();
4869 NS_ENSURE_TRUE(presContext, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(presContext)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "presContext" ") failed"
, nullptr, "./../../../docshell/base/nsDocShell.cpp", 4869); return
NS_ERROR_FAILURE; } } while (false)
;
4870
4871 // Only the root content document can have a distinct visual viewport offset.
4872 if (!presContext->IsRootContentDocumentCrossProcess()) {
4873 return NS_OK;
4874 }
4875
4876 // Not on a platform with a distinct visual viewport - don't bother setting
4877 // the visual viewport offset.
4878 if (!presShell->IsVisualViewportSizeSet()) {
4879 return NS_OK;
4880 }
4881
4882 presShell->ScrollToVisual(
4883 targetPos, layers::ScrollOffsetUpdateType::MainThread, scrollMode);
4884
4885 return NS_OK;
4886}
4887
4888void nsDocShell::RestoreScrollPositionFromTargetSessionHistoryInfo(
4889 SessionHistoryInfo* aTarget) {
4890 nscoord bx = 0;
4891 nscoord by = 0;
4892 if (aTarget) {
4893 aTarget->GetScrollPosition(&bx, &by);
4894 }
4895 SetCurScrollPosEx(bx, by);
4896}
4897
4898void nsDocShell::SetScrollbarPreference(mozilla::ScrollbarPreference aPref) {
4899 if (mScrollbarPref == aPref) {
4900 return;
4901 }
4902 mScrollbarPref = aPref;
4903 auto* ps = GetPresShell();
4904 if (!ps) {
4905 return;
4906 }
4907 nsIFrame* rootScrollContainerFrame = ps->GetRootScrollContainerFrame();
4908 if (!rootScrollContainerFrame) {
4909 return;
4910 }
4911 ps->FrameNeedsReflow(rootScrollContainerFrame,
4912 IntrinsicDirty::FrameAncestorsAndDescendants,
4913 NS_FRAME_IS_DIRTY);
4914}
4915
4916//*****************************************************************************
4917// nsDocShell::nsIRefreshURI
4918//*****************************************************************************
4919
4920NS_IMETHODIMPnsresult
4921nsDocShell::RefreshURI(nsIURI* aURI, nsIPrincipal* aPrincipal,
4922 uint32_t aDelay) {
4923 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"
, "./../../../docshell/base/nsDocShell.cpp", 4923); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!mIsBeingDestroyed" ")"); do { MOZ_CrashSequence
(__null, 4923); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
4924
4925 NS_ENSURE_ARG(aURI)do { if ((__builtin_expect(!!(!(aURI)), 0))) { NS_DebugBreak(
NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aURI" ") failed", nullptr
, "./../../../docshell/base/nsDocShell.cpp", 4925); return NS_ERROR_INVALID_ARG
; } } while (false)
;
4926
4927 /* Check if Meta refresh/redirects are permitted. Some
4928 * embedded applications may not want to do this.
4929 * Must do this before sending out NOTIFY_REFRESH events
4930 * because listeners may have side effects (e.g. displaying a
4931 * button to manually trigger the refresh later).
4932 */
4933 bool allowRedirects = true;
4934 GetAllowMetaRedirects(&allowRedirects);
4935 if (!allowRedirects) {
4936 return NS_OK;
4937 }
4938
4939 // If any web progress listeners are listening for NOTIFY_REFRESH events,
4940 // give them a chance to block this refresh.
4941 bool sameURI;
4942 nsresult rv = aURI->Equals(mCurrentURI, &sameURI);
4943 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
4944 sameURI = false;
4945 }
4946 if (!RefreshAttempted(this, aURI, aDelay, sameURI)) {
4947 return NS_OK;
4948 }
4949
4950 nsCOMPtr<nsITimerCallback> refreshTimer =
4951 MakeRefPtr<nsRefreshTimer>(this, aURI, aPrincipal, aDelay);
4952
4953 BusyFlags busyFlags = GetBusyFlags();
4954
4955 if (!mRefreshURIList) {
4956 mRefreshURIList = nsArray::Create();
4957 }
4958
4959 if (busyFlags & BUSY_FLAGS_BUSY ||
4960 (!mBrowsingContext->IsActive() && mDisableMetaRefreshWhenInactive)) {
4961 // We don't want to create the timer right now. Instead queue up the
4962 // request and trigger the timer in EndPageLoad() or whenever we become
4963 // active.
4964 mRefreshURIList->AppendElement(refreshTimer);
4965 } else {
4966 // There is no page loading going on right now. Create the
4967 // timer and fire it right away.
4968 nsCOMPtr<nsPIDOMWindowOuter> win = GetWindow();
4969 NS_ENSURE_TRUE(win, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(win)), 0))) { NS_DebugBreak(NS_DEBUG_WARNING
, "NS_ENSURE_TRUE(" "win" ") failed", nullptr, "./../../../docshell/base/nsDocShell.cpp"
, 4969); return NS_ERROR_FAILURE; } } while (false)
;
4970
4971 nsCOMPtr<nsITimer> timer = MOZ_TRY(__extension__({ auto mozTryVarTempResult = ::mozilla::ToResult
(NS_NewTimerWithCallback(refreshTimer, aDelay, nsITimer::TYPE_ONE_SHOT
)); if ((__builtin_expect(!!(mozTryVarTempResult.isErr()), 0)
)) { return mozTryVarTempResult.propagateErr(); } mozTryVarTempResult
.unwrap(); })
4972 NS_NewTimerWithCallback(refreshTimer, aDelay, nsITimer::TYPE_ONE_SHOT))__extension__({ auto mozTryVarTempResult = ::mozilla::ToResult
(NS_NewTimerWithCallback(refreshTimer, aDelay, nsITimer::TYPE_ONE_SHOT
)); if ((__builtin_expect(!!(mozTryVarTempResult.isErr()), 0)
)) { return mozTryVarTempResult.propagateErr(); } mozTryVarTempResult
.unwrap(); })
;
4973
4974 mRefreshURIList->AppendElement(timer); // owning timer ref
4975 }
4976 return NS_OK;
4977}
4978
4979nsresult nsDocShell::ForceRefreshURIFromTimer(nsIURI* aURI,
4980 nsIPrincipal* aPrincipal,
4981 uint32_t aDelay,
4982 nsITimer* aTimer) {
4983 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"
")", "./../../../docshell/base/nsDocShell.cpp", 4983); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aTimer" ") (" "Must have a timer here" ")"
); do { MOZ_CrashSequence(__null, 4983); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4984
4985 // Remove aTimer from mRefreshURIList if needed
4986 if (mRefreshURIList) {
4987 uint32_t n = 0;
4988 mRefreshURIList->GetLength(&n);
4989
4990 for (uint32_t i = 0; i < n; ++i) {
4991 nsCOMPtr<nsITimer> timer = do_QueryElementAt(mRefreshURIList, i);
4992 if (timer == aTimer) {
4993 mRefreshURIList->RemoveElementAt(i);
4994 break;
4995 }
4996 }
4997 }
4998
4999 return ForceRefreshURI(aURI, aPrincipal, aDelay);
5000}
5001
5002NS_IMETHODIMPnsresult
5003nsDocShell::ForceRefreshURI(nsIURI* aURI, nsIPrincipal* aPrincipal,
5004 uint32_t aDelay) {
5005 NS_ENSURE_ARG(aURI)do { if ((__builtin_expect(!!(!(aURI)), 0))) { NS_DebugBreak(
NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aURI" ") failed", nullptr
, "./../../../docshell/base/nsDocShell.cpp", 5005); return NS_ERROR_INVALID_ARG
; } } while (false)
;
5006
5007 RefPtr loadState = MakeRefPtr<nsDocShellLoadState>(aURI);
5008 loadState->SetOriginalURI(mCurrentURI);
5009 loadState->SetResultPrincipalURI(aURI);
5010 loadState->SetResultPrincipalURIIsSome(true);
5011 loadState->SetKeepResultPrincipalURIIfSet(true);
5012 loadState->SetIsMetaRefresh(true);
5013
5014 RefPtr<Document> doc = GetDocument();
5015 NS_ENSURE_STATE(doc)do { if ((__builtin_expect(!!(!(doc)), 0))) { NS_DebugBreak(NS_DEBUG_WARNING
, "NS_ENSURE_TRUE(" "doc" ") failed", nullptr, "./../../../docshell/base/nsDocShell.cpp"
, 5015); return NS_ERROR_UNEXPECTED; } } while (false)
;
5016
5017 // Set the triggering pricipal to aPrincipal if available, or current
5018 // document's principal otherwise.
5019 nsCOMPtr<nsIPrincipal> principal = aPrincipal;
5020 if (!principal) {
5021 principal = doc->NodePrincipal();
5022 }
5023 loadState->SetTriggeringPrincipal(principal);
5024 loadState->SetPolicyContainer(doc->GetPolicyContainer());
5025 loadState->SetHasValidUserGestureActivation(
5026 doc->HasValidTransientUserGestureActivation());
5027
5028 loadState->SetTextDirectiveUserActivation(
5029 doc->ConsumeTextDirectiveUserActivation() ||
5030 loadState->HasValidUserGestureActivation());
5031 loadState->SetTriggeringSandboxFlags(doc->GetSandboxFlags());
5032 loadState->SetTriggeringWindowId(doc->InnerWindowID());
5033 loadState->SetTriggeringStorageAccess(doc->UsingStorageAccess());
5034 loadState->SetTriggeringClassificationFlags(doc->GetScriptTrackingFlags());
5035
5036 loadState->SetPrincipalIsExplicit(true);
5037
5038 /* Check if this META refresh causes a redirection
5039 * to another site.
5040 */
5041 bool equalUri = false;
5042 nsresult rv = aURI->Equals(mCurrentURI, &equalUri);
5043
5044 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && !equalUri && aDelay <= REFRESH_REDIRECT_TIMER15000) {
5045 /* It is a META refresh based redirection within the threshold time
5046 * we have in mind (15000 ms as defined by REFRESH_REDIRECT_TIMER).
5047 * Pass a REPLACE flag to LoadURI().
5048 */
5049 loadState->SetLoadType(LOAD_REFRESH_REPLACE);
5050 } else {
5051 loadState->SetLoadType(LOAD_REFRESH);
5052 }
5053
5054 const bool sendReferrer = StaticPrefs::network_http_referer_sendFromRefresh();
5055 /* The document's referrer policy is needed instead of mReferrerInfo's
5056 * referrer policy.
5057 */
5058 const RefPtr referrerInfo = MakeRefPtr<ReferrerInfo>(*doc, sendReferrer);
5059 /* We mimic HTTP, which passes the original referrer. See step 3 of
5060 * <https://html.spec.whatwg.org/multipage/browsing-the-web.html#create-navigation-params-by-fetching>.
5061 */
5062 loadState->SetReferrerInfo(referrerInfo);
5063
5064 loadState->SetLoadFlags(
5065 nsIWebNavigation::LOAD_FLAGS_DISALLOW_INHERIT_PRINCIPAL);
5066 loadState->SetFirstParty(true);
5067
5068 /*
5069 * LoadURI(...) will cancel all refresh timers... This causes the
5070 * Timer and its refreshData instance to be released...
5071 */
5072 LoadURI(loadState, false);
5073
5074 return NS_OK;
5075}
5076
5077static const char16_t* SkipASCIIWhitespace(const char16_t* aStart,
5078 const char16_t* aEnd) {
5079 const char16_t* iter = aStart;
5080 while (iter != aEnd && mozilla::IsAsciiWhitespace(*iter)) {
5081 ++iter;
5082 }
5083 return iter;
5084}
5085
5086static std::tuple<const char16_t*, const char16_t*> ExtractURLString(
5087 const char16_t* aPosition, const char16_t* aEnd) {
5088 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"
, "./../../../docshell/base/nsDocShell.cpp", 5088); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aPosition != aEnd" ")"); do { MOZ_CrashSequence
(__null, 5088); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
5089
5090 // 1. Let urlString be the substring of input from the code point at
5091 // position to the end of the string.
5092 const char16_t* urlStart = aPosition;
5093 const char16_t* urlEnd = aEnd;
5094
5095 // 2. If the code point in input pointed to by position is U+0055 (U) or
5096 // U+0075 (u), then advance position to the next code point.
5097 // Otherwise, jump to the step labeled skip quotes.
5098 if (*aPosition == 'U' || *aPosition == 'u') {
5099 ++aPosition;
5100
5101 // 3. If the code point in input pointed to by position is U+0052 (R) or
5102 // U+0072 (r), then advance position to the next code point.
5103 // Otherwise, jump to the step labeled parse.
5104 if (aPosition == aEnd || (*aPosition != 'R' && *aPosition != 'r')) {
5105 return std::make_tuple(urlStart, urlEnd);
5106 }
5107
5108 ++aPosition;
5109
5110 // 4. If the code point in input pointed to by position is U+004C (L) or
5111 // U+006C (l), then advance position to the next code point.
5112 // Otherwise, jump to the step labeled parse.
5113 if (aPosition == aEnd || (*aPosition != 'L' && *aPosition != 'l')) {
5114 return std::make_tuple(urlStart, urlEnd);
5115 }
5116
5117 ++aPosition;
5118
5119 // 5. Skip ASCII whitespace within input given position.
5120 aPosition = SkipASCIIWhitespace(aPosition, aEnd);
5121
5122 // 6. If the code point in input pointed to by position is U+003D (=),
5123 // then advance position to the next code point. Otherwise, jump to
5124 // the step labeled parse.
5125 if (aPosition == aEnd || *aPosition != '=') {
5126 return std::make_tuple(urlStart, urlEnd);
5127 }
5128
5129 ++aPosition;
5130
5131 // 7. Skip ASCII whitespace within input given position.
5132 aPosition = SkipASCIIWhitespace(aPosition, aEnd);
5133 }
5134
5135 // 8. Skip quotes: If the code point in input pointed to by position is
5136 // U+0027 (') or U+0022 ("), then let quote be that code point, and
5137 // advance position to the next code point. Otherwise, let quote be
5138 // the empty string.
5139 Maybe<char> quote;
5140 if (aPosition != aEnd && (*aPosition == '\'' || *aPosition == '"')) {
5141 quote.emplace(*aPosition);
5142 ++aPosition;
5143 }
5144
5145 // 9. Set urlString to the substring of input from the code point at
5146 // position to the end of the string.
5147 urlStart = aPosition;
5148 urlEnd = aEnd;
5149
5150 // 10. If quote is not the empty string, and there is a code point in
5151 // urlString equal to quote, then truncate urlString at that code
5152 // point, so that it and all subsequent code points are removed.
5153 const char16_t* quotePos;
5154 if (quote.isSome() &&
5155 (quotePos = nsCharTraits<char16_t>::find(
5156 urlStart, std::distance(urlStart, aEnd), quote.value()))) {
5157 urlEnd = quotePos;
5158 }
5159
5160 return std::make_tuple(urlStart, urlEnd);
5161}
5162
5163void nsDocShell::SetupRefreshURIFromHeader(Document* aDocument,
5164 const nsAString& aHeader) {
5165 if (mIsBeingDestroyed) {
5166 return;
5167 }
5168
5169 const char16_t* position = aHeader.BeginReading();
5170 const char16_t* end = aHeader.EndReading();
5171
5172 // See https://html.spec.whatwg.org/#shared-declarative-refresh-steps.
5173
5174 // 3. Skip ASCII whitespace
5175 position = SkipASCIIWhitespace(position, end);
5176
5177 // 4. Let time be 0.
5178 CheckedInt<uint32_t> milliSeconds;
5179
5180 // 5. Collect a sequence of code points that are ASCII digits
5181 const char16_t* digitsStart = position;
5182 while (position != end && mozilla::IsAsciiDigit(*position)) {
5183 ++position;
5184 }
5185
5186 if (position == digitsStart) {
5187 // 6. If timeString is the empty string, then:
5188 // 1. If the code point in input pointed to by position is not U+002E
5189 // (.), then return.
5190 if (position == end || *position != '.') {
5191 return;
5192 }
5193 } else {
5194 // 7. Otherwise, set time to the result of parsing timeString using the
5195 // rules for parsing non-negative integers.
5196 nsContentUtils::ParseHTMLIntegerResultFlags result;
5197 uint32_t seconds =
5198 nsContentUtils::ParseHTMLInteger(digitsStart, position, &result);
5199 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)"
, "./../../../docshell/base/nsDocShell.cpp", 5199); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!(result & nsContentUtils::eParseHTMLInteger_Negative)"
")"); do { MOZ_CrashSequence(__null, 5199); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5200 if (result & nsContentUtils::eParseHTMLInteger_Error) {
5201 // The spec assumes no errors here (since we only pass ASCII digits in),
5202 // but we can still overflow, so this block should deal with that (and
5203 // only that).
5204 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))"
, "./../../../docshell/base/nsDocShell.cpp", 5207); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!(result & ~(nsContentUtils::eParseHTMLInteger_DidNotConsumeAllInput | nsContentUtils::eParseHTMLInteger_Error | nsContentUtils::eParseHTMLInteger_ErrorOverflow))"
")"); do { MOZ_CrashSequence(__null, 5207); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
5205 !(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))"
, "./../../../docshell/base/nsDocShell.cpp", 5207); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!(result & ~(nsContentUtils::eParseHTMLInteger_DidNotConsumeAllInput | nsContentUtils::eParseHTMLInteger_Error | nsContentUtils::eParseHTMLInteger_ErrorOverflow))"
")"); do { MOZ_CrashSequence(__null, 5207); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
5206 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))"
, "./../../../docshell/base/nsDocShell.cpp", 5207); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!(result & ~(nsContentUtils::eParseHTMLInteger_DidNotConsumeAllInput | nsContentUtils::eParseHTMLInteger_Error | nsContentUtils::eParseHTMLInteger_ErrorOverflow))"
")"); do { MOZ_CrashSequence(__null, 5207); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
5207 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))"
, "./../../../docshell/base/nsDocShell.cpp", 5207); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!(result & ~(nsContentUtils::eParseHTMLInteger_DidNotConsumeAllInput | nsContentUtils::eParseHTMLInteger_Error | nsContentUtils::eParseHTMLInteger_ErrorOverflow))"
")"); do { MOZ_CrashSequence(__null, 5207); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5208 return;
5209 }
5210 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)"
, "./../../../docshell/base/nsDocShell.cpp", 5211); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!(result & nsContentUtils::eParseHTMLInteger_DidNotConsumeAllInput)"
")"); do { MOZ_CrashSequence(__null, 5211); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
5211 !(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)"
, "./../../../docshell/base/nsDocShell.cpp", 5211); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!(result & nsContentUtils::eParseHTMLInteger_DidNotConsumeAllInput)"
")"); do { MOZ_CrashSequence(__null, 5211); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5212
5213 milliSeconds = seconds;
5214 milliSeconds *= 1000;
5215 if (!milliSeconds.isValid()) {
5216 return;
5217 }
5218 }
5219
5220 // 8. Collect a sequence of code points that are ASCII digits and U+002E FULL
5221 // STOP characters (.) from input given position. Ignore any collected
5222 // characters.
5223 while (position != end &&
5224 (mozilla::IsAsciiDigit(*position) || *position == '.')) {
5225 ++position;
5226 }
5227
5228 // 9. Let urlRecord be document's URL.
5229 nsCOMPtr<nsIURI> urlRecord(aDocument->GetDocumentURI());
5230
5231 // 10. If position is not past the end of input
5232 if (position != end) {
5233 // 1. If the code point in input pointed to by position is not U+003B (;),
5234 // U+002C (,), or ASCII whitespace, then return.
5235 if (*position != ';' && *position != ',' &&
5236 !mozilla::IsAsciiWhitespace(*position)) {
5237 return;
5238 }
5239
5240 // 2. Skip ASCII whitespace within input given position.
5241 position = SkipASCIIWhitespace(position, end);
5242
5243 // 3. If the code point in input pointed to by position is U+003B (;) or
5244 // U+002C (,), then advance position to the next code point.
5245 if (position != end && (*position == ';' || *position == ',')) {
5246 ++position;
5247
5248 // 4. Skip ASCII whitespace within input given position.
5249 position = SkipASCIIWhitespace(position, end);
5250 }
5251
5252 // 11. If position is not past the end of input, then:
5253 if (position != end) {
5254 const char16_t* urlStart;
5255 const char16_t* urlEnd;
5256
5257 // 1-10. See ExtractURLString.
5258 std::tie(urlStart, urlEnd) = ExtractURLString(position, end);
5259
5260 // 11. Parse: Parse urlString relative to document. If that fails, return.
5261 // Otherwise, set urlRecord to the resulting URL record.
5262 nsresult rv =
5263 NS_NewURI(getter_AddRefs(urlRecord),
5264 Substring(urlStart, std::distance(urlStart, urlEnd)),
5265 /* charset = */ nullptr, aDocument->GetDocBaseURI());
5266 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, "./../../../docshell/base/nsDocShell.cpp"
, 5266); return; } } while (false)
;
5267 }
5268 }
5269
5270 nsIPrincipal* principal = aDocument->NodePrincipal();
5271 nsCOMPtr<nsIScriptSecurityManager> securityManager =
5272 nsContentUtils::GetSecurityManager();
5273 nsresult rv = securityManager->CheckLoadURIWithPrincipal(
5274 principal, urlRecord,
5275 nsIScriptSecurityManager::LOAD_IS_AUTOMATIC_DOCUMENT_REPLACEMENT,
5276 aDocument->InnerWindowID());
5277 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, "./../../../docshell/base/nsDocShell.cpp"
, 5277); return; } } while (false)
;
5278
5279 bool isjs = true;
5280 rv = NS_URIChainHasFlags(
5281 urlRecord, nsIProtocolHandler::URI_OPENING_EXECUTES_SCRIPT, &isjs);
5282 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, "./../../../docshell/base/nsDocShell.cpp"
, 5282); return; } } while (false)
;
5283
5284 if (isjs) {
5285 return;
5286 }
5287
5288 RefreshURI(urlRecord, principal, milliSeconds.value());
5289}
5290
5291static void DoCancelRefreshURITimers(nsIMutableArray* aTimerList) {
5292 if (!aTimerList) {
5293 return;
5294 }
5295
5296 uint32_t n = 0;
5297 aTimerList->GetLength(&n);
5298
5299 while (n) {
5300 nsCOMPtr<nsITimer> timer(do_QueryElementAt(aTimerList, --n));
5301
5302 aTimerList->RemoveElementAt(n); // bye bye owning timer ref
5303
5304 if (timer) {
5305 timer->Cancel();
5306 }
5307 }
5308}
5309
5310NS_IMETHODIMPnsresult
5311nsDocShell::CancelRefreshURITimers() {
5312 DoCancelRefreshURITimers(mRefreshURIList);
5313 DoCancelRefreshURITimers(mSavedRefreshURIList);
5314 DoCancelRefreshURITimers(mBFCachedRefreshURIList);
5315 mRefreshURIList = nullptr;
5316 mSavedRefreshURIList = nullptr;
5317 mBFCachedRefreshURIList = nullptr;
5318
5319 return NS_OK;
5320}
5321
5322NS_IMETHODIMPnsresult
5323nsDocShell::GetRefreshPending(bool* aResult) {
5324 if (!mRefreshURIList) {
5325 *aResult = false;
5326 return NS_OK;
5327 }
5328
5329 uint32_t count;
5330 nsresult rv = mRefreshURIList->GetLength(&count);
5331 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
5332 *aResult = (count != 0);
5333 }
5334 return rv;
5335}
5336
5337void nsDocShell::RefreshURIToQueue() {
5338 if (mRefreshURIList) {
5339 uint32_t n = 0;
5340 mRefreshURIList->GetLength(&n);
5341
5342 for (uint32_t i = 0; i < n; ++i) {
5343 nsCOMPtr<nsITimer> timer = do_QueryElementAt(mRefreshURIList, i);
5344 if (!timer) {
5345 continue; // this must be a nsRefreshURI already
5346 }
5347
5348 // Replace this timer object with a nsRefreshTimer object.
5349 nsCOMPtr<nsITimerCallback> callback;
5350 timer->GetCallback(getter_AddRefs(callback));
5351
5352 timer->Cancel();
5353
5354 mRefreshURIList->ReplaceElementAt(callback, i);
5355 }
5356 }
5357}
5358
5359NS_IMETHODIMPnsresult
5360nsDocShell::SuspendRefreshURIs() {
5361 RefreshURIToQueue();
5362
5363 // Suspend refresh URIs for our child shells as well.
5364 for (auto* child : mChildList.ForwardRange()) {
5365 nsCOMPtr<nsIDocShell> shell = do_QueryObject(child);
5366 if (shell) {
5367 shell->SuspendRefreshURIs();
5368 }
5369 }
5370
5371 return NS_OK;
5372}
5373
5374NS_IMETHODIMPnsresult
5375nsDocShell::ResumeRefreshURIs() {
5376 RefreshURIFromQueue();
5377
5378 // Resume refresh URIs for our child shells as well.
5379 for (auto* child : mChildList.ForwardRange()) {
5380 nsCOMPtr<nsIDocShell> shell = do_QueryObject(child);
5381 if (shell) {
5382 shell->ResumeRefreshURIs();
5383 }
5384 }
5385
5386 return NS_OK;
5387}
5388
5389nsresult nsDocShell::RefreshURIFromQueue() {
5390 if (!mRefreshURIList) {
5391 return NS_OK;
5392 }
5393 uint32_t n = 0;
5394 mRefreshURIList->GetLength(&n);
5395
5396 while (n) {
5397 nsCOMPtr<nsITimerCallback> refreshInfo =
5398 do_QueryElementAt(mRefreshURIList, --n);
5399
5400 if (refreshInfo) {
5401 // This is the nsRefreshTimer object, waiting to be
5402 // setup in a timer object and fired.
5403 // Create the timer and trigger it.
5404 uint32_t delay = static_cast<nsRefreshTimer*>(
5405 static_cast<nsITimerCallback*>(refreshInfo))
5406 ->GetDelay();
5407 nsCOMPtr<nsPIDOMWindowOuter> win = GetWindow();
5408 if (win) {
5409 nsCOMPtr<nsITimer> timer;
5410 NS_NewTimerWithCallback(getter_AddRefs(timer), refreshInfo, delay,
5411 nsITimer::TYPE_ONE_SHOT);
5412
5413 if (timer) {
5414 // Replace the nsRefreshTimer element in the queue with
5415 // its corresponding timer object, so that in case another
5416 // load comes through before the timer can go off, the timer will
5417 // get cancelled in CancelRefreshURITimer()
5418 mRefreshURIList->ReplaceElementAt(timer, n);
5419 }
5420 }
5421 }
5422 }
5423
5424 return NS_OK;
5425}
5426
5427static bool IsFollowupPartOfMultipart(nsIRequest* aRequest) {
5428 nsCOMPtr<nsIMultiPartChannel> multiPartChannel = do_QueryInterface(aRequest);
5429 bool firstPart = false;
5430 return multiPartChannel &&
5431 NS_SUCCEEDED(multiPartChannel->GetIsFirstPart(&firstPart))((bool)(__builtin_expect(!!(!NS_FAILED_impl(multiPartChannel->
GetIsFirstPart(&firstPart))), 1)))
&&
5432 !firstPart;
5433}
5434
5435nsresult nsDocShell::Embed(nsIDocumentViewer* aDocumentViewer,
5436 WindowGlobalChild* aWindowActor,
5437 bool aIsTransientAboutBlank, nsIRequest* aRequest,
5438 nsIURI* aPreviousURI) {
5439 // Save the LayoutHistoryState of the previous document, before
5440 // setting up new document
5441 PersistLayoutHistoryState();
5442
5443 nsresult rv = SetupNewViewer(aDocumentViewer, aWindowActor);
5444 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, "./../../../docshell/base/nsDocShell.cpp"
, 5444); return rv; } } while (false)
;
5445
5446 // XXX What if SetupNewViewer fails?
5447 if (mLoadingEntry) {
5448 // Set history.state
5449 SetDocCurrentStateObj(mLoadingEntry ? &mLoadingEntry->mInfo : nullptr);
5450 }
5451
5452 if (!aIsTransientAboutBlank && !IsFollowupPartOfMultipart(aRequest)) {
5453 bool expired = false;
5454 uint32_t cacheKey = 0;
5455 nsCOMPtr<nsICacheInfoChannel> cacheChannel = do_QueryInterface(aRequest);
5456 if (cacheChannel) {
5457 // Check if the page has expired from cache
5458 uint32_t expTime = 0;
5459 cacheChannel->GetCacheTokenExpirationTime(&expTime);
5460 uint32_t now = PRTimeToSeconds(PR_Now());
5461 if (expTime <= now) {
5462 expired = true;
5463 }
5464
5465 // The checks for updating cache key are similar to the old session
5466 // history in OnNewURI. Try to update the cache key if
5467 // - we should update session history and aren't doing a session
5468 // history load.
5469 // - we're doing a forced reload.
5470 if (((!mLoadingEntry || !mLoadingEntry->mLoadIsFromSessionHistory) &&
5471 mBrowsingContext->ShouldUpdateSessionHistory(mLoadType)) ||
5472 IsForceReloadType(mLoadType)) {
5473 cacheChannel->GetCacheKey(&cacheKey);
5474 }
5475 }
5476
5477 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)
;
5478 MoveLoadingToActiveEntry(expired, cacheKey, aPreviousURI);
5479 }
5480
5481 bool updateHistory = true;
5482
5483 // Determine if this type of load should update history
5484 switch (mLoadType) {
5485 case LOAD_NORMAL_REPLACE:
5486 case LOAD_REFRESH_REPLACE:
5487 case LOAD_STOP_CONTENT_AND_REPLACE:
5488 case LOAD_RELOAD_BYPASS_CACHE:
5489 case LOAD_RELOAD_BYPASS_PROXY:
5490 case LOAD_RELOAD_BYPASS_PROXY_AND_CACHE:
5491 case LOAD_REPLACE_BYPASS_CACHE:
5492 updateHistory = false;
5493 break;
5494 default:
5495 break;
5496 }
5497
5498 if (!updateHistory) {
5499 SetLayoutHistoryState(nullptr);
5500 }
5501
5502 return NS_OK;
5503}
5504
5505//*****************************************************************************
5506// nsDocShell::nsIWebProgressListener
5507//*****************************************************************************
5508
5509NS_IMETHODIMPnsresult
5510nsDocShell::OnProgressChange(nsIWebProgress* aProgress, nsIRequest* aRequest,
5511 int32_t aCurSelfProgress, int32_t aMaxSelfProgress,
5512 int32_t aCurTotalProgress,
5513 int32_t aMaxTotalProgress) {
5514 // Listeners in the parent process only care about aCurTotalProgress and
5515 // aMaxTotalProgress, which is internally managed by nsDocLoader. Because of
5516 // this, we don't send progress notifications except when they are recorded by
5517 // the toplevel context, and only report them on the toplevel context in the
5518 // parent process.
5519 //
5520 // FIXME: We should track progress for out-of-process iframes and manage total
5521 // progress in the parent process for more accurate notifications.
5522 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"
")", "./../../../docshell/base/nsDocShell.cpp", 5524); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "mBrowsingContext->IsTop()" ") (" "notification excluded in AddProgressListener(...) for non-toplevel BCs"
")"); do { MOZ_CrashSequence(__null, 5524); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
5523 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"
")", "./../../../docshell/base/nsDocShell.cpp", 5524); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "mBrowsingContext->IsTop()" ") (" "notification excluded in AddProgressListener(...) for non-toplevel BCs"
")"); do { MOZ_CrashSequence(__null, 5524); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
5524 "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"
")", "./../../../docshell/base/nsDocShell.cpp", 5524); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "mBrowsingContext->IsTop()" ") (" "notification excluded in AddProgressListener(...) for non-toplevel BCs"
")"); do { MOZ_CrashSequence(__null, 5524); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5525
5526 if (nsCOMPtr<nsIWebProgressListener> listener = BCWebProgressListener()) {
5527 listener->OnProgressChange(aProgress, aRequest, aCurSelfProgress,
5528 aMaxSelfProgress, aCurTotalProgress,
5529 aMaxTotalProgress);
5530 }
5531
5532 return NS_OK;
5533}
5534
5535NS_IMETHODIMPnsresult
5536nsDocShell::OnStateChange(nsIWebProgress* aProgress, nsIRequest* aRequest,
5537 uint32_t aStateFlags, nsresult aStatus) {
5538 // If we're receiving a notification on ourselves which has at least one of
5539 // the state change flags in kStateChangeFlagFilter, also notify WebProgress
5540 // on BrowsingContextWebProgress, potentially over IPC.
5541 //
5542 // NOTE: We don't notify for bubbled notifications (aProgress != this), as
5543 // BrowsingContextWebProgress independently handles event bubbling in the
5544 // parent process.
5545 //
5546 // NOTE: We don't filter notifications when registering our listener, as
5547 // `STATE_IS_REDIRECTED_DOCUMENT` cannot be filtered for at registration time.
5548 static constexpr uint32_t kStateChangeFlagFilter =
5549 STATE_IS_NETWORK | STATE_IS_DOCUMENT | STATE_IS_WINDOW |
5550 STATE_IS_REDIRECTED_DOCUMENT;
5551 if (aProgress == this && (aStateFlags & kStateChangeFlagFilter) != 0) {
5552 if (nsCOMPtr<nsIWebProgressListener> listener = BCWebProgressListener()) {
5553 listener->OnStateChange(aProgress, aRequest, aStateFlags, aStatus);
5554 }
5555 }
5556
5557 if ((~aStateFlags & (STATE_START | STATE_IS_NETWORK)) == 0) {
5558 // Save timing statistics.
5559 nsCOMPtr<nsIChannel> channel(do_QueryInterface(aRequest));
5560 nsCOMPtr<nsIURI> uri;
5561 channel->GetURI(getter_AddRefs(uri));
5562 nsAutoCString aURI;
5563 uri->GetAsciiSpec(aURI);
5564
5565 if (this == aProgress) {
5566 (void)MaybeInitTiming();
5567 mTiming->NotifyFetchStart(uri,
5568 ConvertLoadTypeToNavigationType(mLoadType));
5569 // If we are starting a DocumentChannel, we need to pass the timing
5570 // statistics so that should a process switch occur, the starting type can
5571 // be passed to the new DocShell running in the other content process.
5572 if (RefPtr<DocumentChannel> docChannel = do_QueryObject(aRequest)) {
5573 docChannel->SetNavigationTiming(mTiming);
5574 }
5575 }
5576
5577 // Page has begun to load
5578 mBusyFlags = (BusyFlags)(BUSY_FLAGS_BUSY | BUSY_FLAGS_BEFORE_PAGE_LOAD);
5579
5580 if ((aStateFlags & STATE_RESTORING) == 0) {
5581 if (SessionStorePlatformCollection()) {
5582 if (IsForceReloadType(mLoadType)) {
5583 if (WindowContext* windowContext =
5584 mBrowsingContext->GetCurrentWindowContext()) {
5585 SessionStoreChild::From(windowContext->GetWindowGlobalChild())
5586 ->ResetSessionStore(mBrowsingContext,
5587 mBrowsingContext->GetSessionStoreEpoch());
5588 }
5589 }
5590 }
5591 }
5592 } else if ((~aStateFlags & (STATE_TRANSFERRING | STATE_IS_DOCUMENT)) == 0) {
5593 // Page is loading
5594 mBusyFlags = (BusyFlags)(BUSY_FLAGS_BUSY | BUSY_FLAGS_PAGE_LOADING);
5595 } else if ((aStateFlags & STATE_STOP) && (aStateFlags & STATE_IS_NETWORK)) {
5596 // Page has finished loading
5597 mBusyFlags = BUSY_FLAGS_NONE;
5598 }
5599
5600 if ((~aStateFlags & (STATE_IS_DOCUMENT | STATE_STOP)) == 0) {
5601 nsCOMPtr<nsIWebProgress> webProgress =
5602 do_QueryInterface(GetAsSupports(this));
5603 // Is the document stop notification for this document?
5604 if (aProgress == webProgress.get()) {
5605 nsCOMPtr<nsIChannel> channel(do_QueryInterface(aRequest));
5606 EndPageLoad(aProgress, channel, aStatus);
5607 }
5608 }
5609 // note that redirect state changes will go through here as well, but it
5610 // is better to handle those in OnRedirectStateChange where more
5611 // information is available.
5612 return NS_OK;
5613}
5614
5615NS_IMETHODIMPnsresult
5616nsDocShell::OnLocationChange(nsIWebProgress* aProgress, nsIRequest* aRequest,
5617 nsIURI* aURI, uint32_t aFlags) {
5618 // If we're receiving a notification on ourselves, also notify WebProgress on
5619 // BrowsingContextWebProgress, potentially over IPC.
5620 //
5621 // NOTE: We don't notify for bubbled notifications (aProgress != this), as
5622 // BrowsingContextWebProgress independently handles event bubbling in the
5623 // parent process.
5624 //
5625 // NOTE: Tests depend on this happening before UpdateSecurityState.
5626 if (aProgress == this) {
5627 if (nsCOMPtr<nsIWebProgressListener> listener = BCWebProgressListener()) {
5628 listener->OnLocationChange(aProgress, aRequest, aURI, aFlags);
5629 }
5630 }
5631
5632 // Since we've now changed Documents, notify the BrowsingContext that we've
5633 // changed. Ideally we'd just let the BrowsingContext do this when it
5634 // changes the current window global, but that happens before this and we
5635 // have a lot of tests that depend on the specific ordering of messages.
5636 bool isTopLevel = false;
5637 if (XRE_IsParentProcess() &&
5638 !(aFlags & nsIWebProgressListener::LOCATION_CHANGE_SAME_DOCUMENT) &&
5639 NS_SUCCEEDED(aProgress->GetIsTopLevel(&isTopLevel))((bool)(__builtin_expect(!!(!NS_FAILED_impl(aProgress->GetIsTopLevel
(&isTopLevel))), 1)))
&& isTopLevel) {
5640 GetBrowsingContext()->Canonical()->UpdateSecurityState();
5641 }
5642 return NS_OK;
5643}
5644
5645void nsDocShell::OnRedirectStateChange(nsIChannel* aOldChannel,
5646 nsIChannel* aNewChannel,
5647 uint32_t aRedirectFlags,
5648 uint32_t aStateFlags) {
5649 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", "./../../../docshell/base/nsDocShell.cpp"
, 5650); MOZ_PretendNoReturn(); } } while (0)
5650 "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", "./../../../docshell/base/nsDocShell.cpp"
, 5650); MOZ_PretendNoReturn(); } } while (0)
;
5651
5652 if (!(aStateFlags & STATE_IS_DOCUMENT)) {
5653 return; // not a toplevel document
5654 }
5655
5656 nsCOMPtr<nsIURI> oldURI, newURI;
5657 aOldChannel->GetURI(getter_AddRefs(oldURI));
5658 aNewChannel->GetURI(getter_AddRefs(newURI));
5659 if (!oldURI || !newURI) {
5660 return;
5661 }
5662
5663 // DocumentChannel adds redirect chain to global history in the parent
5664 // process. The redirect chain can't be queried from the content process, so
5665 // there's no need to update global history here.
5666 RefPtr<DocumentChannel> docChannel = do_QueryObject(aOldChannel);
5667 if (!docChannel) {
5668 // Below a URI visit is saved (see AddURIVisit method doc).
5669 // The visit chain looks something like:
5670 // ...
5671 // Site N - 1
5672 // => Site N
5673 // (redirect to =>) Site N + 1 (we are here!)
5674
5675 // Get N - 1 and transition type
5676 nsCOMPtr<nsIURI> previousURI;
5677 uint32_t previousFlags = 0;
5678 ExtractLastVisit(aOldChannel, getter_AddRefs(previousURI), &previousFlags);
5679
5680 if (aRedirectFlags & nsIChannelEventSink::REDIRECT_INTERNAL ||
5681 net::ChannelIsPost(aOldChannel)) {
5682 // 1. Internal redirects are ignored because they are specific to the
5683 // channel implementation.
5684 // 2. POSTs are not saved by global history.
5685 //
5686 // Regardless, we need to propagate the previous visit to the new
5687 // channel.
5688 SaveLastVisit(aNewChannel, previousURI, previousFlags);
5689 } else {
5690 // Get the HTTP response code, if available.
5691 uint32_t responseStatus = 0;
5692 nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(aOldChannel);
5693 if (httpChannel) {
5694 (void)httpChannel->GetResponseStatus(&responseStatus);
5695 }
5696
5697 // Add visit N -1 => N
5698 AddURIVisit(oldURI, previousURI, previousFlags, responseStatus);
5699
5700 // Since N + 1 could be the final destination, we will not save N => N + 1
5701 // here. OnNewURI will do that, so we will cache it.
5702 SaveLastVisit(aNewChannel, oldURI, aRedirectFlags);
5703 }
5704 }
5705
5706 if (!(aRedirectFlags & nsIChannelEventSink::REDIRECT_INTERNAL) &&
5707 mLoadType & (LOAD_CMD_RELOAD | LOAD_CMD_HISTORY)) {
5708 mLoadType = LOAD_NORMAL_REPLACE;
5709 }
5710}
5711
5712NS_IMETHODIMPnsresult
5713nsDocShell::OnStatusChange(nsIWebProgress* aWebProgress, nsIRequest* aRequest,
5714 nsresult aStatus, const char16_t* aMessage) {
5715 // If we're receiving a notification on ourselves, also notify WebProgress on
5716 // BrowsingContextWebProgress, potentially over IPC.
5717 //
5718 // NOTE: We don't notify for bubbled notifications (aWebProgress != this), as
5719 // BrowsingContextWebProgress independently handles event bubbling in the
5720 // parent process.
5721 if (aWebProgress == this) {
5722 if (nsCOMPtr<nsIWebProgressListener> listener = BCWebProgressListener()) {
5723 listener->OnStatusChange(aWebProgress, aRequest, aStatus, aMessage);
5724 }
5725 }
5726
5727 return NS_OK;
5728}
5729
5730NS_IMETHODIMPnsresult
5731nsDocShell::OnSecurityChange(nsIWebProgress* aWebProgress, nsIRequest* aRequest,
5732 uint32_t aState) {
5733 // If we're receiving a notification on ourselves, also notify WebProgress on
5734 // BrowsingContextWebProgress, potentially over IPC.
5735 //
5736 // NOTE: We don't notify for bubbled notifications (aWebProgress != this), as
5737 // BrowsingContextWebProgress independently handles event bubbling in the
5738 // parent process.
5739 if (aWebProgress == this) {
5740 if (nsCOMPtr<nsIWebProgressListener> listener = BCWebProgressListener()) {
5741 listener->OnSecurityChange(aWebProgress, aRequest, aState);
5742 }
5743 }
5744
5745 return NS_OK;
5746}
5747
5748NS_IMETHODIMPnsresult
5749nsDocShell::OnContentBlockingEvent(nsIWebProgress* aWebProgress,
5750 nsIRequest* aRequest, uint32_t aEvent) {
5751 MOZ_ASSERT_UNREACHABLE("notification excluded in AddProgressListener(...)")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "MOZ_ASSERT_UNREACHABLE: "
"notification excluded in AddProgressListener(...)" ")", "./../../../docshell/base/nsDocShell.cpp"
, 5751); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "notification excluded in AddProgressListener(...)"
")"); do { MOZ_CrashSequence(__null, 5751); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5752 return NS_OK;
5753}
5754
5755already_AddRefed<nsIWebProgressListener> nsDocShell::BCWebProgressListener() {
5756 // If this BrowsingContext has been replaced, we should discard any
5757 // notifications which would otherwise be delivered in-process.
5758 if (XRE_IsParentProcess() && mBrowsingContext->Canonical()->IsReplaced()) {
5759 return nullptr;
5760 }
5761
5762 // Create a nsBrowserStatusFilter to perform some throttling of
5763 // OnProgressChange and OnStatusChange notifications which are delivered to
5764 // our BCWebProgress listener. This reduces the amount of IPC traffic.
5765 if (!mBCWebProgressStatusFilter && !mIsBeingDestroyed) {
5766 nsCOMPtr<nsIWebProgressListener> innerListener;
5767 if (XRE_IsParentProcess()) {
5768 innerListener = mBrowsingContext->Canonical()->GetWebProgress();
5769 } else {
5770 innerListener = do_QueryReferent(mBrowserChild);
5771 }
5772 if (innerListener) {
5773 // NOTE: We need to disable filtering of StateChange events here, as
5774 // listeners on BrowsingContextWebProgress may depend on state change
5775 // notifications are otherwise filtered.
5776 // NOTE: Unlike other nsIWebProgress types, nsBrowserStatusFilter holds a
5777 // strong cycle-collected reference to the inner listener.
5778 mBCWebProgressStatusFilter = MakeRefPtr<nsBrowserStatusFilter>(
5779 /* aDisableStateChangeFilters */ true);
5780 mBCWebProgressStatusFilter->AddProgressListener(
5781 innerListener, nsIWebProgress::NOTIFY_ALL);
5782 }
5783 }
5784
5785 return do_AddRef(mBCWebProgressStatusFilter);
5786}
5787
5788already_AddRefed<nsIURIFixupInfo> nsDocShell::KeywordToURI(
5789 const nsACString& aKeyword, bool aIsPrivateContext) {
5790 nsCOMPtr<nsIURIFixupInfo> info;
5791 if (!XRE_IsContentProcess()) {
5792 nsCOMPtr<nsIURIFixup> uriFixup = components::URIFixup::Service();
5793 if (uriFixup) {
5794 uriFixup->KeywordToURI(aKeyword, aIsPrivateContext, getter_AddRefs(info));
5795 }
5796 }
5797 return info.forget();
5798}
5799
5800/* static */
5801already_AddRefed<nsIURI> nsDocShell::MaybeFixBadCertDomainErrorURI(
5802 nsIChannel* aChannel, nsIURI* aUrl) {
5803 if (!aChannel) {
5804 return nullptr;
5805 }
5806
5807 nsresult rv = NS_OK;
5808 nsAutoCString host;
5809 rv = aUrl->GetAsciiHost(host);
5810 if (NS_WARN_IF(NS_FAILED(rv))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(rv
)), 0))), "NS_FAILED(rv)", "./../../../docshell/base/nsDocShell.cpp"
, 5810)
) {
5811 return nullptr;
5812 }
5813
5814 // Return if fixup enable pref is turned off.
5815 if (!mozilla::StaticPrefs::security_bad_cert_domain_error_url_fix_enabled()) {
5816 return nullptr;
5817 }
5818
5819 // Return if scheme is not HTTPS.
5820 if (!aUrl->SchemeIs("https")) {
5821 return nullptr;
5822 }
5823
5824 nsCOMPtr<nsILoadInfo> info = aChannel->LoadInfo();
5825 if (!info) {
5826 return nullptr;
5827 }
5828
5829 // Skip doing the fixup if our channel was redirected, because we
5830 // shouldn't be guessing things about the post-redirect URI.
5831 if (!info->RedirectChain().IsEmpty()) {
5832 return nullptr;
5833 }
5834
5835 int32_t port = 0;
5836 rv = aUrl->GetPort(&port);
5837 if (NS_WARN_IF(NS_FAILED(rv))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(rv
)), 0))), "NS_FAILED(rv)", "./../../../docshell/base/nsDocShell.cpp"
, 5837)
) {
5838 return nullptr;
5839 }
5840
5841 // Don't fix up hosts with ports.
5842 if (port != -1) {
5843 return nullptr;
5844 }
5845
5846 // Don't fix up localhost url.
5847 if (host == "localhost") {
5848 return nullptr;
5849 }
5850
5851 // Don't fix up hostnames with IP address.
5852 if (net_IsValidIPv4Addr(host) || net_IsValidIPv6Addr(host)) {
5853 return nullptr;
5854 }
5855
5856 nsAutoCString userPass;
5857 rv = aUrl->GetUserPass(userPass);
5858 if (NS_WARN_IF(NS_FAILED(rv))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(rv
)), 0))), "NS_FAILED(rv)", "./../../../docshell/base/nsDocShell.cpp"
, 5858)
) {
5859 return nullptr;
5860 }
5861
5862 // Security - URLs with user / password info should NOT be modified.
5863 if (!userPass.IsEmpty()) {
5864 return nullptr;
5865 }
5866
5867 nsCOMPtr<nsITransportSecurityInfo> tsi;
5868 rv = aChannel->GetSecurityInfo(getter_AddRefs(tsi));
5869 if (NS_WARN_IF(NS_FAILED(rv))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(rv
)), 0))), "NS_FAILED(rv)", "./../../../docshell/base/nsDocShell.cpp"
, 5869)
) {
5870 return nullptr;
5871 }
5872
5873 if (NS_WARN_IF(!tsi)NS_warn_if_impl(!tsi, "!tsi", "./../../../docshell/base/nsDocShell.cpp"
, 5873)
) {
5874 return nullptr;
5875 }
5876
5877 nsCOMPtr<nsIX509Cert> cert;
5878 rv = tsi->GetServerCert(getter_AddRefs(cert));
5879 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", "./../../../docshell/base/nsDocShell.cpp"
, 5879)
) {
5880 return nullptr;
5881 }
5882
5883 nsTArray<uint8_t> certBytes;
5884 rv = cert->GetRawDER(certBytes);
5885 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
5886 return nullptr;
5887 }
5888
5889 mozilla::pkix::Input serverCertInput;
5890 mozilla::pkix::Result result =
5891 serverCertInput.Init(certBytes.Elements(), certBytes.Length());
5892 if (result != mozilla::pkix::Success) {
5893 return nullptr;
5894 }
5895
5896 constexpr auto wwwPrefix = "www."_ns;
5897 nsAutoCString newHost;
5898 if (StringBeginsWith(host, wwwPrefix)) {
5899 // Try www.example.com -> example.com
5900 newHost.Assign(Substring(host, wwwPrefix.Length()));
5901 } else {
5902 // Try example.com -> www.example.com
5903 newHost.Assign(wwwPrefix);
5904 newHost.Append(host);
5905 }
5906
5907 mozilla::pkix::Input newHostInput;
5908 result = newHostInput.Init(
5909 BitwiseCast<const uint8_t*, const char*>(newHost.BeginReading()),
5910 newHost.Length());
5911 if (result != mozilla::pkix::Success) {
5912 return nullptr;
5913 }
5914
5915 // Because certificate verification returned Result::ERROR_BAD_CERT_DOMAIN /
5916 // SSL_ERROR_BAD_CERT_DOMAIN, a chain was built and we know whether or not
5917 // the root was a built-in.
5918 bool rootIsBuiltIn;
5919 if (NS_FAILED(tsi->GetIsBuiltCertChainRootBuiltInRoot(&rootIsBuiltIn))((bool)(__builtin_expect(!!(NS_FAILED_impl(tsi->GetIsBuiltCertChainRootBuiltInRoot
(&rootIsBuiltIn))), 0)))
) {
5920 return nullptr;
5921 }
5922 mozilla::psm::SkipInvalidSANsForNonBuiltInRootsPolicy nameMatchingPolicy(
5923 rootIsBuiltIn);
5924
5925 // Check if the certificate is valid for the new hostname.
5926 result = mozilla::pkix::CheckCertHostname(serverCertInput, newHostInput,
5927 nameMatchingPolicy);
5928 if (result != mozilla::pkix::Success) {
5929 return nullptr;
5930 }
5931
5932 nsCOMPtr<nsIURI> newURI;
5933 (void)NS_MutateURI(aUrl).SetHost(newHost).Finalize(getter_AddRefs(newURI));
5934
5935 return newURI.forget();
5936}
5937
5938/* static */
5939already_AddRefed<nsIURI> nsDocShell::AttemptURIFixup(
5940 nsIChannel* aChannel, nsresult aStatus,
5941 const mozilla::Maybe<nsCString>& aOriginalURIString, uint32_t aLoadType,
5942 bool aIsTopFrame, bool aAllowKeywordFixup, bool aUsePrivateBrowsing,
5943 bool aNotifyKeywordSearchLoading, nsIInputStream** aNewPostData,
5944 nsILoadInfo::SchemelessInputType* outSchemelessInput) {
5945 if (aStatus != NS_ERROR_UNKNOWN_HOST && aStatus != NS_ERROR_NET_RESET &&
5946 aStatus != NS_ERROR_CONNECTION_REFUSED &&
5947 aStatus !=
5948 mozilla::psm::GetXPCOMFromNSSError(SSL_ERROR_BAD_CERT_DOMAIN)) {
5949 return nullptr;
5950 }
5951
5952 if (!(aLoadType == LOAD_NORMAL && aIsTopFrame) && !aAllowKeywordFixup) {
5953 return nullptr;
5954 }
5955
5956 nsCOMPtr<nsIURI> url;
5957 nsresult rv = aChannel->GetURI(getter_AddRefs(url));
5958 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
5959 return nullptr;
5960 }
5961
5962 //
5963 // Try and make an alternative URI from the old one
5964 //
5965 nsCOMPtr<nsIURI> newURI;
5966 nsCOMPtr<nsIInputStream> newPostData;
5967
5968 nsAutoCString oldSpec;
5969 url->GetSpec(oldSpec);
5970
5971 //
5972 // First try keyword fixup
5973 //
5974 nsAutoString keywordProviderId, keywordAsSent;
5975 if (aStatus == NS_ERROR_UNKNOWN_HOST && aAllowKeywordFixup) {
5976 // we should only perform a keyword search under the following
5977 // conditions:
5978 // (0) Pref keyword.enabled is true
5979 // (1) the url scheme is http (or https)
5980 // (2) the url does not have a protocol scheme
5981 // If we don't enforce such a policy, then we end up doing
5982 // keyword searchs on urls we don't intend like imap, file,
5983 // mailbox, etc. This could lead to a security problem where we
5984 // send data to the keyword server that we shouldn't be.
5985 // Someone needs to clean up keywords in general so we can
5986 // determine on a per url basis if we want keywords
5987 // enabled...this is just a bandaid...
5988 if (Preferences::GetBool("keyword.enabled", false) &&
5989 net::SchemeIsHttpOrHttps(url)) {
5990 bool attemptFixup = false;
5991 nsAutoCString host;
5992 (void)url->GetHost(host);
5993 if (host.FindChar('.') == kNotFound) {
5994 attemptFixup = true;
5995 } else {
5996 // For domains with dots, we check the public suffix validity.
5997 nsCOMPtr<nsIEffectiveTLDService> tldService =
5998 do_GetService(NS_EFFECTIVETLDSERVICE_CONTRACTID"@mozilla.org/network/effective-tld-service;1");
5999 if (tldService) {
6000 nsAutoCString suffix;
6001 attemptFixup =
6002 NS_SUCCEEDED(tldService->GetKnownPublicSuffix(url, suffix))((bool)(__builtin_expect(!!(!NS_FAILED_impl(tldService->GetKnownPublicSuffix
(url, suffix))), 1)))
&&
6003 suffix.IsEmpty();
6004 }
6005 }
6006 if (attemptFixup) {
6007 nsCOMPtr<nsIURIFixupInfo> info;
6008 // only send non-qualified hosts to the keyword server
6009 if (aOriginalURIString && !aOriginalURIString->IsEmpty()) {
6010 info = KeywordToURI(*aOriginalURIString, aUsePrivateBrowsing);
6011 } else {
6012 //
6013 // If this string was passed through nsStandardURL by
6014 // chance, then it may have been converted from UTF-8 to
6015 // Punycode, which would result in a completely bogus keyword
6016 // query. Here we try to recover the original Unicode
6017 // value, but this is not 100% correct since the value may
6018 // have been normalized per the IDN normalization rules.
6019 //
6020 // Since we don't have access to the exact original string
6021 // that was entered by the user, this will just have to do.
6022 nsAutoCString utf8Host;
6023 mozilla_net_recover_keyword_from_punycode(&host, &utf8Host);
6024 info = KeywordToURI(utf8Host, aUsePrivateBrowsing);
6025 }
6026 if (info) {
6027 info->GetPreferredURI(getter_AddRefs(newURI));
6028 info->GetSchemelessInput(outSchemelessInput);
6029 if (newURI) {
6030 info->GetKeywordAsSent(keywordAsSent);
6031 info->GetKeywordProviderId(keywordProviderId);
6032 info->GetPostData(getter_AddRefs(newPostData));
6033 }
6034 }
6035 }
6036 }
6037 }
6038
6039 //
6040 // Now try change the address, e.g. turn http://foo into
6041 // http://www.foo.com, and if that doesn't work try https with
6042 // https://foo and https://www.foo.com.
6043 //
6044 if (aStatus == NS_ERROR_UNKNOWN_HOST || aStatus == NS_ERROR_NET_RESET) {
6045 // Skip fixup for anything except a normal document load
6046 // operation on the topframe.
6047 bool doCreateAlternate = aLoadType == LOAD_NORMAL && aIsTopFrame;
6048
6049 if (doCreateAlternate) {
6050 nsCOMPtr<nsILoadInfo> loadInfo = aChannel->LoadInfo();
6051 nsIPrincipal* principal = loadInfo->TriggeringPrincipal();
6052 // Only do this if our channel was loaded directly by the user from the
6053 // URL bar or similar (system principal) and not redirected, because we
6054 // shouldn't be guessing things about links from other sites, or a
6055 // post-redirect URI.
6056 doCreateAlternate = principal && principal->IsSystemPrincipal() &&
6057 loadInfo->RedirectChain().IsEmpty();
6058 }
6059 // Test if keyword lookup produced a new URI or not
6060 if (doCreateAlternate && newURI) {
6061 bool sameURI = false;
6062 url->Equals(newURI, &sameURI);
6063 if (!sameURI) {
6064 // Keyword lookup made a new URI so no need to try
6065 // an alternate one.
6066 doCreateAlternate = false;
6067 }
6068 }
6069 if (doCreateAlternate) {
6070 newURI = nullptr;
6071 newPostData = nullptr;
6072 keywordProviderId.Truncate();
6073 keywordAsSent.Truncate();
6074 nsCOMPtr<nsIURIFixup> uriFixup = components::URIFixup::Service();
6075 if (uriFixup) {
6076 nsCOMPtr<nsIURIFixupInfo> fixupInfo;
6077 uriFixup->GetFixupURIInfo(oldSpec, nsIURIFixup::FIXUP_FLAG_NONE,
6078 getter_AddRefs(fixupInfo));
6079 if (fixupInfo) {
6080 fixupInfo->GetPreferredURI(getter_AddRefs(newURI));
6081 }
6082 }
6083 }
6084 } else if (aStatus == NS_ERROR_CONNECTION_REFUSED &&
6085 Preferences::GetBool("browser.fixup.fallback-to-https", false)) {
6086 // Try HTTPS, since http didn't work
6087 if (url->SchemeIs("http")) {
6088 int32_t port = 0;
6089 url->GetPort(&port);
6090
6091 // Fall back to HTTPS only if port is default
6092 if (port == -1) {
6093 newURI = nullptr;
6094 newPostData = nullptr;
6095 (void)NS_MutateURI(url)
6096 .SetScheme("https"_ns)
6097 .Finalize(getter_AddRefs(newURI));
6098 }
6099 }
6100 }
6101
6102 // If we have a SSL_ERROR_BAD_CERT_DOMAIN error, try adding or removing
6103 // "www." to/from the beginning of the domain name to see if we can avoid
6104 // showing the cert error page. For example, https://example.com ->
6105 // https://www.example.com or https://www.example.com -> https://example.com.
6106 if (aStatus ==
6107 mozilla::psm::GetXPCOMFromNSSError(SSL_ERROR_BAD_CERT_DOMAIN)) {
6108 newPostData = nullptr;
6109 newURI = MaybeFixBadCertDomainErrorURI(aChannel, url);
6110 }
6111
6112 // Did we make a new URI that is different to the old one? If so
6113 // load it.
6114 //
6115 if (newURI) {
6116 // Make sure the new URI is different from the old one,
6117 // otherwise there's little point trying to load it again.
6118 bool sameURI = false;
6119 url->Equals(newURI, &sameURI);
6120 if (!sameURI) {
6121 if (aNewPostData) {
6122 newPostData.forget(aNewPostData);
6123 }
6124 if (aNotifyKeywordSearchLoading) {
6125 // This notification is meant for Firefox Health Report so it
6126 // can increment counts from the search engine
6127 MaybeNotifyKeywordSearchLoading(keywordProviderId, keywordAsSent);
6128 }
6129 return newURI.forget();
6130 }
6131 }
6132
6133 return nullptr;
6134}
6135
6136nsresult nsDocShell::FilterStatusForErrorPage(
6137 nsresult aStatus, nsIChannel* aChannel, uint32_t aLoadType,
6138 bool aIsTopFrame, bool aUseErrorPages,
6139 bool* aSkippedUnknownProtocolNavigation) {
6140 // Errors to be shown only on top-level frames
6141 if ((aStatus == NS_ERROR_UNKNOWN_HOST ||
6142 aStatus == NS_ERROR_CONNECTION_REFUSED ||
6143 aStatus == NS_ERROR_UNKNOWN_PROXY_HOST ||
6144 aStatus == NS_ERROR_PROXY_CONNECTION_REFUSED ||
6145 aStatus == NS_ERROR_PROXY_FORBIDDEN ||
6146 aStatus == NS_ERROR_PROXY_NOT_IMPLEMENTED ||
6147 aStatus == NS_ERROR_PROXY_AUTHENTICATION_FAILED ||
6148 aStatus == NS_ERROR_PROXY_TOO_MANY_REQUESTS ||
6149 aStatus == NS_ERROR_MALFORMED_URI ||
6150 aStatus == NS_ERROR_HARMFULADDON_URI ||
6151 aStatus == NS_ERROR_BLOCKED_BY_POLICY ||
6152 aStatus == NS_ERROR_DOM_COOP_FAILED ||
6153 aStatus == NS_ERROR_DOM_COEP_FAILED ||
6154 aStatus == NS_ERROR_DOM_INVALID_HEADER_VALUE) &&
6155 (aIsTopFrame || aUseErrorPages)) {
6156 return aStatus;
6157 }
6158
6159 if (aStatus == NS_ERROR_NET_TIMEOUT ||
6160 aStatus == NS_ERROR_NET_TIMEOUT_EXTERNAL ||
6161 aStatus == NS_ERROR_OS_LOCAL_NETWORK_ACCESS_DENIED ||
6162 aStatus == NS_ERROR_NET_EMPTY_RESPONSE ||
6163 aStatus == NS_ERROR_NET_ERROR_RESPONSE ||
6164 aStatus == NS_ERROR_PROXY_GATEWAY_TIMEOUT ||
6165 aStatus == NS_ERROR_REDIRECT_LOOP ||
6166 aStatus == NS_ERROR_UNKNOWN_SOCKET_TYPE ||
6167 aStatus == NS_ERROR_NET_INTERRUPT || aStatus == NS_ERROR_NET_RESET ||
6168 aStatus == NS_ERROR_PROXY_BAD_GATEWAY || aStatus == NS_ERROR_OFFLINE ||
6169 aStatus == NS_ERROR_MALWARE_URI || aStatus == NS_ERROR_PHISHING_URI ||
6170 aStatus == NS_ERROR_UNWANTED_URI || aStatus == NS_ERROR_HARMFUL_URI ||
6171 aStatus == NS_ERROR_UNSAFE_CONTENT_TYPE ||
6172 aStatus == NS_ERROR_INTERCEPTION_FAILED ||
6173 aStatus == NS_ERROR_NET_INADEQUATE_SECURITY ||
6174 aStatus == NS_ERROR_NET_HTTP2_SENT_GOAWAY ||
6175 aStatus == NS_ERROR_NET_HTTP3_PROTOCOL_ERROR ||
6176 aStatus == NS_ERROR_BASIC_HTTP_AUTH_DISABLED ||
6177 aStatus == NS_ERROR_DOM_BAD_URI || aStatus == NS_ERROR_FILE_NOT_FOUND ||
6178 aStatus == NS_ERROR_FILE_ACCESS_DENIED ||
6179 aStatus == NS_ERROR_CORRUPTED_CONTENT ||
6180 aStatus == NS_ERROR_INVALID_CONTENT_ENCODING ||
6181 NS_ERROR_GET_MODULE(aStatus) == NS_ERROR_MODULE_SECURITY21) {
6182 // Errors to be shown for any frame
6183 return aStatus;
6184 }
6185
6186 if (aStatus == NS_ERROR_UNKNOWN_PROTOCOL) {
6187 // For unknown protocols we only display an error if the load is triggered
6188 // by the browser itself. Showing the error for page-triggered navigations
6189 // causes annoying behavior for users when a page tries to open an external
6190 // app which has not been installed, see bug 1528305. A missing WebExtension
6191 // protocol handlers will however always load the error page, as it is not
6192 // expected to be opened externally, see bug 1921426.
6193 nsCOMPtr<nsILoadInfo> info = aChannel->LoadInfo();
6194 if (!info->TriggeringPrincipal()->IsSystemPrincipal() &&
6195 !BasePrincipal::Cast(info->TriggeringPrincipal())->AddonPolicy()) {
6196 if (aSkippedUnknownProtocolNavigation) {
6197 *aSkippedUnknownProtocolNavigation = true;
6198 }
6199 return NS_OK;
6200 }
6201 return aStatus;
6202 }
6203
6204 if (aStatus == NS_ERROR_DOCUMENT_NOT_CACHED) {
6205 // Non-caching channels will simply return NS_ERROR_OFFLINE.
6206 // Caching channels would have to look at their flags to work
6207 // out which error to return. Or we can fix up the error here.
6208 if (!(aLoadType & LOAD_CMD_HISTORY)) {
6209 return NS_ERROR_OFFLINE;
6210 }
6211 return aStatus;
6212 }
6213
6214 return NS_OK;
6215}
6216
6217nsresult nsDocShell::EndPageLoad(nsIWebProgress* aProgress,
6218 nsIChannel* aChannel, nsresult aStatus) {
6219 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)
6220 ("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)
6221 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)
;
6222 if (!aChannel) {
6223 return NS_ERROR_NULL_POINTER;
6224 }
6225
6226 // Make sure to discard the initial client if we never created the initial
6227 // about:blank document. Do this before possibly returning from the method
6228 // due to an error.
6229 mInitialClientSource.reset();
6230
6231 nsCOMPtr<nsIConsoleReportCollector> reporter = do_QueryInterface(aChannel);
6232 if (reporter) {
6233 nsCOMPtr<nsILoadGroup> loadGroup;
6234 aChannel->GetLoadGroup(getter_AddRefs(loadGroup));
6235 if (loadGroup) {
6236 reporter->FlushConsoleReports(loadGroup);
6237 } else {
6238 reporter->FlushConsoleReports(GetDocument());
6239 }
6240 }
6241
6242 nsCOMPtr<nsIURI> url;
6243 nsresult rv = aChannel->GetURI(getter_AddRefs(url));
6244 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
6245 return rv;
6246 }
6247
6248 nsCOMPtr<nsITimedChannel> timingChannel = do_QueryInterface(aChannel);
6249 if (timingChannel) {
6250 TimeStamp channelCreationTime;
6251 rv = timingChannel->GetChannelCreation(&channelCreationTime);
6252 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && !channelCreationTime.IsNull()) {
6253 glean::performance_page::total_content_page_load.AccumulateRawDuration(
6254 TimeStamp::Now() - channelCreationTime);
6255 }
6256 }
6257
6258 // Timing is picked up by the window, we don't need it anymore
6259 mTiming = nullptr;
6260
6261 // clean up reload state for meta charset
6262 if (eCharsetReloadRequested == mCharsetReloadState) {
6263 mCharsetReloadState = eCharsetReloadStopOrigional;
6264 } else {
6265 mCharsetReloadState = eCharsetReloadInit;
6266 }
6267
6268 //
6269 // one of many safeguards that prevent death and destruction if
6270 // someone is so very very rude as to bring this window down
6271 // during this load handler.
6272 //
6273 nsCOMPtr<nsIDocShell> kungFuDeathGrip(this);
6274
6275 // Notify the DocumentViewer that the Document has finished loading. This
6276 // will cause any OnLoad(...) and PopState(...) handlers to fire.
6277 if (!mEODForCurrentDocument && mDocumentViewer) {
6278 mIsExecutingOnLoadHandler = true;
6279 nsCOMPtr<nsIDocumentViewer> viewer = mDocumentViewer;
6280 viewer->LoadComplete(aStatus);
6281 mIsExecutingOnLoadHandler = false;
6282
6283 mEODForCurrentDocument = true;
6284 }
6285 /* Check if the httpChannel has any cache-control related response headers,
6286 * like no-store, no-cache. If so, update SHEntry so that
6287 * when a user goes back/forward to this page, we appropriately do
6288 * form value restoration or load from server.
6289 */
6290 nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(aChannel));
6291 if (!httpChannel) {
6292 // HttpChannel could be hiding underneath a Multipart channel.
6293 GetHttpChannel(aChannel, getter_AddRefs(httpChannel));
6294 }
6295
6296 mActiveEntryIsLoadingFromSessionHistory = false;
6297
6298 // if there's a refresh header in the channel, this method
6299 // will set it up for us.
6300 if (mBrowsingContext->IsActive() || !mDisableMetaRefreshWhenInactive)
6301 RefreshURIFromQueue();
6302
6303 // Test whether this is the top frame or a subframe
6304 bool isTopFrame = mBrowsingContext->IsTop();
6305
6306 bool hadErrorStatus = false;
6307 // If status code indicates an error it means that DocumentChannel already
6308 // tried to fixup the uri and failed. Throw an error dialog box here.
6309 if (NS_FAILED(aStatus)((bool)(__builtin_expect(!!(NS_FAILED_impl(aStatus)), 0)))) {
6310 // If we got CONTENT_BLOCKED from EndPageLoad, then we need to fire
6311 // the error event to our embedder, since tests are relying on this.
6312 // The error event is usually fired by the caller of InternalLoad, but
6313 // this particular error can happen asynchronously.
6314 // Bug 1629201 is filed for having much clearer decision making around
6315 // which cases need error events.
6316 bool fireFrameErrorEvent = (aStatus == NS_ERROR_CONTENT_BLOCKED_SHOW_ALT ||
6317 aStatus == NS_ERROR_CONTENT_BLOCKED);
6318 UnblockEmbedderLoadEventForFailure(fireFrameErrorEvent);
6319
6320 bool skippedUnknownProtocolNavigation = false;
6321 aStatus = FilterStatusForErrorPage(aStatus, aChannel, mLoadType, isTopFrame,
6322 mBrowsingContext->GetUseErrorPages(),
6323 &skippedUnknownProtocolNavigation);
6324 hadErrorStatus = true;
6325 if (NS_FAILED(aStatus)((bool)(__builtin_expect(!!(NS_FAILED_impl(aStatus)), 0)))) {
6326 if (!mIsBeingDestroyed) {
6327 DisplayLoadError(aStatus, url, nullptr, aChannel);
6328 }
6329 } else if (skippedUnknownProtocolNavigation) {
6330 nsAutoCString sanitized;
6331 nsTArray<nsString> params;
6332 if (NS_SUCCEEDED(NS_GetSanitizedURIStringFromURI(url, sanitized))((bool)(__builtin_expect(!!(!NS_FAILED_impl(NS_GetSanitizedURIStringFromURI
(url, sanitized))), 1)))
) {
6333 params.AppendElement(NS_ConvertUTF8toUTF16(sanitized));
6334 } else {
6335 params.AppendElement(u"(unknown uri)"_ns);
6336 }
6337 nsContentUtils::ReportToConsole(
6338 nsIScriptError::warningFlag, "DOM"_ns, GetExtantDocument(),
6339 PropertiesFile::DOM_PROPERTIES, "UnknownProtocolNavigationPrevented",
6340 params);
6341 }
6342 }
6343
6344 if (hadErrorStatus) {
6345 // Don't send session store updates if the reason EndPageLoad was called is
6346 // because we are process switching. Sometimes the update takes too long and
6347 // incorrectly overrides session store data from the following load.
6348 return NS_OK;
6349 }
6350 if (SessionStorePlatformCollection()) {
6351 if (WindowContext* windowContext =
6352 mBrowsingContext->GetCurrentWindowContext()) {
6353 using Change = SessionStoreChangeListener::Change;
6354
6355 // We've finished loading the page and now we want to collect all the
6356 // session store state that the page is initialized with.
6357 SessionStoreChangeListener::CollectSessionStoreData(
6358 windowContext,
6359 EnumSet<Change>(Change::Input, Change::Scroll, Change::SessionHistory,
6360 Change::WireFrame));
6361 }
6362 }
6363
6364 return NS_OK;
6365}
6366
6367//*****************************************************************************
6368// nsDocShell: Content Viewer Management
6369//*****************************************************************************
6370
6371bool nsDocShell::VerifyDocumentViewer() {
6372 if (mDocumentViewer) {
6373 return true;
6374 }
6375 if (mIsBeingDestroyed) {
6376 return false;
6377 }
6378 if (!mInitialized) {
6379 // The viewer should be created during docshell initialization. If something
6380 // wants a viewer or document, it has to initialize the docshell first.
6381 MOZ_ASSERT_UNREACHABLE(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: "
"The docshell should be initialized to get a viewer." ")", "./../../../docshell/base/nsDocShell.cpp"
, 6382); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "The docshell should be initialized to get a viewer."
")"); do { MOZ_CrashSequence(__null, 6382); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6382 "The docshell should be initialized to get a viewer.")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: "
"The docshell should be initialized to get a viewer." ")", "./../../../docshell/base/nsDocShell.cpp"
, 6382); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "The docshell should be initialized to get a viewer."
")"); do { MOZ_CrashSequence(__null, 6382); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6383 } else {
6384 NS_WARNING("No document viewer, docshell failed to initialize.")NS_DebugBreak(NS_DEBUG_WARNING, "No document viewer, docshell failed to initialize."
, nullptr, "./../../../docshell/base/nsDocShell.cpp", 6384)
;
6385 }
6386 return false;
6387}
6388
6389nsresult nsDocShell::CreateInitialDocumentViewer(
6390 nsIOpenWindowInfo* aOpenWindowInfo,
6391 mozilla::dom::WindowGlobalChild* aWindowActor) {
6392 if (mIsBeingDestroyed) {
6393 return NS_ERROR_FAILURE;
6394 }
6395 MOZ_DIAGNOSTIC_ASSERT(!mDocumentViewer)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mDocumentViewer)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mDocumentViewer))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("!mDocumentViewer"
, "./../../../docshell/base/nsDocShell.cpp", 6395); AnnotateMozCrashReason
("MOZ_DIAGNOSTIC_ASSERT" "(" "!mDocumentViewer" ")"); do { MOZ_CrashSequence
(__null, 6395); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
6396 MOZ_ASSERT(aOpenWindowInfo, "Why don't we have openwindowinfo?")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aOpenWindowInfo)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aOpenWindowInfo))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("aOpenWindowInfo"
" (" "Why don't we have openwindowinfo?" ")", "./../../../docshell/base/nsDocShell.cpp"
, 6396); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aOpenWindowInfo"
") (" "Why don't we have openwindowinfo?" ")"); do { MOZ_CrashSequence
(__null, 6396); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
6397
6398 nsCOMPtr<nsIPrincipal> principal =
6399 aOpenWindowInfo->PrincipalToInheritForAboutBlank();
6400 nsCOMPtr<nsIPrincipal> partitionedPrincipal =
6401 aOpenWindowInfo->PartitionedPrincipalToInheritForAboutBlank();
6402
6403 // Previously, CreateDocumentViewerForActor would've used the actor's
6404 // principal.
6405 MOZ_ASSERT_IF(aWindowActor, aWindowActor->DocumentPrincipal() == principal)do { if (aWindowActor) { do { static_assert( mozilla::detail::
AssertionConditionType<decltype(aWindowActor->DocumentPrincipal
() == principal)>::isValid, "invalid assertion condition")
; if ((__builtin_expect(!!(!(!!(aWindowActor->DocumentPrincipal
() == principal))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("aWindowActor->DocumentPrincipal() == principal", "./../../../docshell/base/nsDocShell.cpp"
, 6405); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aWindowActor->DocumentPrincipal() == principal"
")"); do { MOZ_CrashSequence(__null, 6405); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
6406 MOZ_ASSERT_IF(aWindowActor,do { if (aWindowActor) { do { static_assert( mozilla::detail::
AssertionConditionType<decltype(aWindowActor->DocumentPrincipal
() == partitionedPrincipal)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aWindowActor->DocumentPrincipal
() == partitionedPrincipal))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("aWindowActor->DocumentPrincipal() == partitionedPrincipal"
, "./../../../docshell/base/nsDocShell.cpp", 6407); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aWindowActor->DocumentPrincipal() == partitionedPrincipal"
")"); do { MOZ_CrashSequence(__null, 6407); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
6407 aWindowActor->DocumentPrincipal() == partitionedPrincipal)do { if (aWindowActor) { do { static_assert( mozilla::detail::
AssertionConditionType<decltype(aWindowActor->DocumentPrincipal
() == partitionedPrincipal)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aWindowActor->DocumentPrincipal
() == partitionedPrincipal))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("aWindowActor->DocumentPrincipal() == partitionedPrincipal"
, "./../../../docshell/base/nsDocShell.cpp", 6407); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aWindowActor->DocumentPrincipal() == partitionedPrincipal"
")"); do { MOZ_CrashSequence(__null, 6407); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
6408
6409 nsCOMPtr<nsIPolicyContainer> policyContainer =
6410 aOpenWindowInfo->PolicyContainerToInheritForAboutBlank();
6411 nsCOMPtr<nsIURI> base = aOpenWindowInfo->BaseUriToInheritForAboutBlank();
6412 MOZ_TRY(CreateAboutBlankDocumentViewer(__extension__({ auto mozTryVarTempResult = ::mozilla::ToResult
(CreateAboutBlankDocumentViewer( principal, partitionedPrincipal
, policyContainer, base, true, aOpenWindowInfo->CoepToInheritForAboutBlank
(), true, false, aWindowActor)); if ((__builtin_expect(!!(mozTryVarTempResult
.isErr()), 0))) { return mozTryVarTempResult.propagateErr(); }
mozTryVarTempResult.unwrap(); })
6413 principal, partitionedPrincipal, policyContainer, base,__extension__({ auto mozTryVarTempResult = ::mozilla::ToResult
(CreateAboutBlankDocumentViewer( principal, partitionedPrincipal
, policyContainer, base, true, aOpenWindowInfo->CoepToInheritForAboutBlank
(), true, false, aWindowActor)); if ((__builtin_expect(!!(mozTryVarTempResult
.isErr()), 0))) { return mozTryVarTempResult.propagateErr(); }
mozTryVarTempResult.unwrap(); })
6414 /* aIsInitialDocument */ true,__extension__({ auto mozTryVarTempResult = ::mozilla::ToResult
(CreateAboutBlankDocumentViewer( principal, partitionedPrincipal
, policyContainer, base, true, aOpenWindowInfo->CoepToInheritForAboutBlank
(), true, false, aWindowActor)); if ((__builtin_expect(!!(mozTryVarTempResult
.isErr()), 0))) { return mozTryVarTempResult.propagateErr(); }
mozTryVarTempResult.unwrap(); })
6415 aOpenWindowInfo->CoepToInheritForAboutBlank(),__extension__({ auto mozTryVarTempResult = ::mozilla::ToResult
(CreateAboutBlankDocumentViewer( principal, partitionedPrincipal
, policyContainer, base, true, aOpenWindowInfo->CoepToInheritForAboutBlank
(), true, false, aWindowActor)); if ((__builtin_expect(!!(mozTryVarTempResult
.isErr()), 0))) { return mozTryVarTempResult.propagateErr(); }
mozTryVarTempResult.unwrap(); })
6416 /* aTryToSaveOldPresentation */ true,__extension__({ auto mozTryVarTempResult = ::mozilla::ToResult
(CreateAboutBlankDocumentViewer( principal, partitionedPrincipal
, policyContainer, base, true, aOpenWindowInfo->CoepToInheritForAboutBlank
(), true, false, aWindowActor)); if ((__builtin_expect(!!(mozTryVarTempResult
.isErr()), 0))) { return mozTryVarTempResult.propagateErr(); }
mozTryVarTempResult.unwrap(); })
6417 /* aCheckPermitUnload */ false, aWindowActor))__extension__({ auto mozTryVarTempResult = ::mozilla::ToResult
(CreateAboutBlankDocumentViewer( principal, partitionedPrincipal
, policyContainer, base, true, aOpenWindowInfo->CoepToInheritForAboutBlank
(), true, false, aWindowActor)); if ((__builtin_expect(!!(mozTryVarTempResult
.isErr()), 0))) { return mozTryVarTempResult.propagateErr(); }
mozTryVarTempResult.unwrap(); })
;
6418
6419 NS_ENSURE_STATE(mDocumentViewer)do { if ((__builtin_expect(!!(!(mDocumentViewer)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "mDocumentViewer" ") failed"
, nullptr, "./../../../docshell/base/nsDocShell.cpp", 6419); return
NS_ERROR_UNEXPECTED; } } while (false)
;
6420
6421 RefPtr<Document> doc(GetDocument());
6422 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!"
")", "./../../../docshell/base/nsDocShell.cpp", 6423); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "doc" ") (" "Should have doc if CreateAboutBlankDocumentViewer succeeded!"
")"); do { MOZ_CrashSequence(__null, 6423); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6423 "Should have doc 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 doc if CreateAboutBlankDocumentViewer succeeded!"
")", "./../../../docshell/base/nsDocShell.cpp", 6423); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "doc" ") (" "Should have doc if CreateAboutBlankDocumentViewer succeeded!"
")"); do { MOZ_CrashSequence(__null, 6423); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6424 MOZ_ASSERT(doc->IsInitialDocument(), "Document should be initial document")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(doc->IsInitialDocument())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(doc->IsInitialDocument())
)), 0))) { do { } while (false); MOZ_ReportAssertionFailure("doc->IsInitialDocument()"
" (" "Document should be initial document" ")", "./../../../docshell/base/nsDocShell.cpp"
, 6424); AnnotateMozCrashReason("MOZ_ASSERT" "(" "doc->IsInitialDocument()"
") (" "Document should be initial document" ")"); do { MOZ_CrashSequence
(__null, 6424); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
6425
6426 // Documents created using CreateInitialDocumentViewer may be transient
6427 // placeholders created by framescripts before content has a
6428 // chance to load. In some cases, window.open(..., "noopener")
6429 // will create such a document and then synchronously tear it
6430 // down, firing a "pagehide" event. Doing so violates our
6431 // assertions about DocGroups. It's easier to silence the
6432 // assertion here than to avoid creating the extra document.
6433 doc->IgnoreDocGroupMismatches();
6434
6435 return NS_OK;
6436}
6437
6438// Location.ancestorOrigins for about:blank, need special case handling.
6439// Particularly in the case for initial about:blank, which does not go through
6440// normal code that happen with navigations.
6441static void CreateAboutBlankAncestorOriginsForNonTopLevel(Document* aDoc) {
6442 BrowsingContext* bc = aDoc->GetBrowsingContext();
6443 MOZ_ASSERT(bc && !bc->IsDiscarded() && bc->GetEmbedderElement())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(bc && !bc->IsDiscarded() && bc->
GetEmbedderElement())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(bc && !bc->IsDiscarded
() && bc->GetEmbedderElement()))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("bc && !bc->IsDiscarded() && bc->GetEmbedderElement()"
, "./../../../docshell/base/nsDocShell.cpp", 6443); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "bc && !bc->IsDiscarded() && bc->GetEmbedderElement()"
")"); do { MOZ_CrashSequence(__null, 6443); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6444 // We're not even going to attempt to deal with location.ancestorOrigins stuff
6445 // in the parent process.
6446 if (!XRE_IsContentProcess()) {
6447 return;
6448 }
6449
6450 const auto* frame = bc->GetEmbedderElement();
6451 const auto referrerPolicy = frame->GetReferrerPolicyAsEnum();
6452 // Inform the parent process that it needs to create an internal ancestor
6453 // origins list for this browsing context `bc`
6454 (void)ContentChild::GetSingleton()->SendUpdateAncestorOriginsList(bc);
6455
6456 const bool masked = referrerPolicy == ReferrerPolicy::No_referrer;
6457 BrowsingContext* parent = bc->GetParent();
6458 MOZ_DIAGNOSTIC_ASSERT(parent && parent->IsInProcess() &&do { static_assert( mozilla::detail::AssertionConditionType<
decltype(parent && parent->IsInProcess() &&
parent->GetExtantDocument())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(parent && parent->
IsInProcess() && parent->GetExtantDocument()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("parent && parent->IsInProcess() && parent->GetExtantDocument()"
, "./../../../docshell/base/nsDocShell.cpp", 6459); AnnotateMozCrashReason
("MOZ_DIAGNOSTIC_ASSERT" "(" "parent && parent->IsInProcess() && parent->GetExtantDocument()"
")"); do { MOZ_CrashSequence(__null, 6459); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6459 parent->GetExtantDocument())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(parent && parent->IsInProcess() &&
parent->GetExtantDocument())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(parent && parent->
IsInProcess() && parent->GetExtantDocument()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("parent && parent->IsInProcess() && parent->GetExtantDocument()"
, "./../../../docshell/base/nsDocShell.cpp", 6459); AnnotateMozCrashReason
("MOZ_DIAGNOSTIC_ASSERT" "(" "parent && parent->IsInProcess() && parent->GetExtantDocument()"
")"); do { MOZ_CrashSequence(__null, 6459); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6460
6461 nsTArray<nsCOMPtr<nsIPrincipal>> ancestorPrincipals;
6462 constexpr auto getPrincipal =
6463 [](const BrowsingContext* ctx) -> nsIPrincipal* {
6464 if (!ctx) {
6465 return nullptr;
6466 }
6467 auto* doc = ctx->GetExtantDocument();
6468 return doc ? doc->GetPrincipal() : nullptr;
6469 };
6470 BrowsingContext* ancestorContextToCopyAncestorListFrom = parent;
6471
6472 // about:blank is different from normal docs.
6473 // We only care about in-process, same-origin ancestors.
6474 // Therefore run the algorithm all the way up to the last same-origin doc
6475 // add that origin to the list, and then append that origin's ancestor origins
6476 // list
6477 if (masked) {
6478 ancestorPrincipals.AppendElement(nullptr);
6479 // 16.1.1. If ancestorOrigin is same origin with parentDoc's origin, then
6480 // append a new opaque origin to output.
6481 auto* parentDocPrincipal = getPrincipal(parent);
6482 for (auto* ancestor = parent->GetParent(); ancestor;
6483 ancestor = ancestor->GetParent()) {
6484 auto* principal = getPrincipal(ancestor);
6485 if (principal && principal->Equals(parentDocPrincipal)) {
6486 // same principal, same process, adding nullptr for
6487 // parentContextToCopyAncestorListFrom
6488 ancestorContextToCopyAncestorListFrom = ancestor;
6489 ancestorPrincipals.AppendElement(nullptr);
6490 } else {
6491 // 16.1.2 Otherwise, append ancestorOrigin to output and set masked to
6492 // false.
6493 // Note: But in the case of about:blank, ancestorOrigin can
6494 // potentially live in another process. So we stop right before it, and
6495 // just copy `ancestorContextToCopyAncestorListFrom` list, since the
6496 // masking steps should finish here.
6497 break;
6498 }
6499 }
6500 } else {
6501 ancestorPrincipals.AppendElement(getPrincipal(parent));
6502 }
6503
6504 nsTArray<nsString> list = ProduceAncestorOriginsList(ancestorPrincipals);
6505 Document* ancestorDoc =
6506 ancestorContextToCopyAncestorListFrom->GetExtantDocument();
6507 MOZ_DIAGNOSTIC_ASSERT(ancestorDoc)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(ancestorDoc)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(ancestorDoc))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("ancestorDoc", "./../../../docshell/base/nsDocShell.cpp"
, 6507); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "ancestorDoc"
")"); do { MOZ_CrashSequence(__null, 6507); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6508 list.AppendElements(ancestorDoc->GetAncestorOriginsList());
6509 aDoc->SetAncestorOriginsList(std::move(list));
6510}
6511
6512nsresult nsDocShell::CreateAboutBlankDocumentViewer(
6513 nsIPrincipal* aPrincipal, nsIPrincipal* aPartitionedPrincipal,
6514 nsIPolicyContainer* aPolicyContainer, nsIURI* aBaseURI,
6515 bool aIsInitialDocument,
6516 const Maybe<nsILoadInfo::CrossOriginEmbedderPolicy>& aCOEP,
6517 bool aTryToSaveOldPresentation, bool aCheckPermitUnload,
6518 WindowGlobalChild* aActor) {
6519 RefPtr<Document> blankDoc;
6520 nsCOMPtr<nsIDocumentViewer> viewer;
6521 nsresult rv = NS_ERROR_FAILURE;
6522
6523 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
)
6524 MarkerStack::Capture())do { ; do { if (profiler_is_collecting_markers()) { ::profiler_add_marker_impl
("CreateAboutBlankDocumentViewer", ::geckoprofiler::category::
DOM, MarkerStack::Capture()); } } while (false); } while (false
)
;
6525
6526 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"
, "./../../../docshell/base/nsDocShell.cpp", 6526); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aActor->DocumentPrincipal() == aPrincipal"
")"); do { MOZ_CrashSequence(__null, 6526); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
6527
6528 MOZ_DIAGNOSTIC_ASSERT(mInitialized, "Must initialize before viewer creation")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mInitialized)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mInitialized))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("mInitialized" " ("
"Must initialize before viewer creation" ")", "./../../../docshell/base/nsDocShell.cpp"
, 6528); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "mInitialized"
") (" "Must initialize before viewer creation" ")"); do { MOZ_CrashSequence
(__null, 6528); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
6529
6530 /* mCreatingDocument should never be true at this point. However, it's
6531 a theoretical possibility. We want to know about it and make it stop,
6532 and this sounds like a job for an assertion. */
6533 NS_ASSERTION(!mCreatingDocument,do { if (!(!mCreatingDocument)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "infinite(?) loop creating document averted", "!mCreatingDocument"
, "./../../../docshell/base/nsDocShell.cpp", 6534); MOZ_PretendNoReturn
(); } } while (0)
6534 "infinite(?) loop creating document averted")do { if (!(!mCreatingDocument)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "infinite(?) loop creating document averted", "!mCreatingDocument"
, "./../../../docshell/base/nsDocShell.cpp", 6534); MOZ_PretendNoReturn
(); } } while (0)
;
6535 if (mCreatingDocument) {
6536 return NS_ERROR_FAILURE;
6537 }
6538
6539 if (!mBrowsingContext->AncestorsAreCurrent() ||
6540 mBrowsingContext->IsInBFCache()) {
6541 mBrowsingContext->RemoveRootFromBFCacheSync();
6542 return NS_ERROR_NOT_AVAILABLE;
6543 }
6544
6545 // mDocumentViewer->PermitUnload may release |this| docshell.
6546 nsCOMPtr<nsIDocShell> kungFuDeathGrip(this);
6547
6548 // Ensure that UsesOriginAgentCluster has been initialized for this
6549 // BrowsingContextGroup/principal pair before creating the document.
6550 if (aPrincipal) {
6551 mBrowsingContext->Group()->EnsureUsesOriginAgentClusterInitialized(
6552 aPrincipal);
6553 }
6554
6555 AutoRestore<bool> creatingDocument(mCreatingDocument);
6556 mCreatingDocument = true;
6557
6558 if (aPrincipal && !aPrincipal->IsSystemPrincipal() &&
6559 mItemType != typeChrome) {
6560 if (GetIsTopLevelContentDocShell()) {
6561 // Bug 1948216 tracks having a FPD for top-level initial about:blank
6562 MOZ_ASSERT(aPrincipal->OriginAttributesRef().EqualsIgnoringFPD(do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aPrincipal->OriginAttributesRef().EqualsIgnoringFPD
( mBrowsingContext->OriginAttributesRef()))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aPrincipal->OriginAttributesRef
().EqualsIgnoringFPD( mBrowsingContext->OriginAttributesRef
())))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("aPrincipal->OriginAttributesRef().EqualsIgnoringFPD( mBrowsingContext->OriginAttributesRef())"
, "./../../../docshell/base/nsDocShell.cpp", 6563); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aPrincipal->OriginAttributesRef().EqualsIgnoringFPD( mBrowsingContext->OriginAttributesRef())"
")"); do { MOZ_CrashSequence(__null, 6563); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6563 mBrowsingContext->OriginAttributesRef()))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aPrincipal->OriginAttributesRef().EqualsIgnoringFPD
( mBrowsingContext->OriginAttributesRef()))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aPrincipal->OriginAttributesRef
().EqualsIgnoringFPD( mBrowsingContext->OriginAttributesRef
())))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("aPrincipal->OriginAttributesRef().EqualsIgnoringFPD( mBrowsingContext->OriginAttributesRef())"
, "./../../../docshell/base/nsDocShell.cpp", 6563); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aPrincipal->OriginAttributesRef().EqualsIgnoringFPD( mBrowsingContext->OriginAttributesRef())"
")"); do { MOZ_CrashSequence(__null, 6563); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6564 } else {
6565 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()"
, "./../../../docshell/base/nsDocShell.cpp", 6566); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aPrincipal->OriginAttributesRef() == mBrowsingContext->OriginAttributesRef()"
")"); do { MOZ_CrashSequence(__null, 6566); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6566 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()"
, "./../../../docshell/base/nsDocShell.cpp", 6566); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aPrincipal->OriginAttributesRef() == mBrowsingContext->OriginAttributesRef()"
")"); do { MOZ_CrashSequence(__null, 6566); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6567 }
6568 }
6569
6570 // Make sure timing is created. But first record whether we had it
6571 // already, so we don't clobber the timing for an in-progress load.
6572 bool hadTiming = mTiming;
6573 bool toBeReset = MaybeInitTiming();
6574 if (mDocumentViewer) {
6575 if (aCheckPermitUnload) {
6576 // We've got a content viewer already. Make sure the user
6577 // permits us to discard the current document and replace it
6578 // with about:blank. And also ensure we fire the unload events
6579 // in the current document.
6580
6581 // Unload gets fired first for
6582 // document loaded from the session history.
6583 mTiming->NotifyBeforeUnload();
6584
6585 bool okToUnload;
6586 rv = mDocumentViewer->PermitUnload(&okToUnload);
6587 if (mIsBeingDestroyed) {
6588 // unload handler destroyed this docshell.
6589 return NS_ERROR_NOT_AVAILABLE;
6590 }
6591 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && !okToUnload) {
6592 // The user chose not to unload the page, interrupt the load.
6593 MaybeResetInitTiming(toBeReset);
6594 return NS_ERROR_FAILURE;
6595 }
6596 if (mTiming) {
6597 mTiming->NotifyUnloadAccepted(mCurrentURI);
6598 }
6599 }
6600
6601 // Make sure to blow away our mLoadingURI just in case. No loads
6602 // from inside this pagehide.
6603 mLoadingURI = nullptr;
6604
6605 // Stop any in-progress loading, so that we don't accidentally trigger any
6606 // PageShow notifications from Embed() interrupting our loading below.
6607 Stop();
6608
6609 // Notify the current document that it is about to be unloaded!!
6610 //
6611 // It is important to fire the unload() notification *before* any state
6612 // is changed within the DocShell - otherwise, javascript will get the
6613 // wrong information :-(
6614 //
6615 (void)FirePageHideNotification();
6616 // pagehide notification might destroy this docshell.
6617 if (mIsBeingDestroyed) {
6618 return NS_ERROR_DOCSHELL_DYING;
6619 }
6620 }
6621
6622 // Now make sure we don't think we're in the middle of firing unload after
6623 // this point. This will make us fire unload when the about:blank document
6624 // unloads... but that's ok, more or less. Would be nice if it fired load
6625 // too, of course.
6626 mFiredUnloadEvent = false;
6627
6628 nsCOMPtr<nsIDocumentLoaderFactory> docFactory =
6629 nsContentUtils::FindInternalDocumentViewer("text/html"_ns);
6630
6631 if (docFactory) {
6632 nsCOMPtr<nsIPrincipal> principal, partitionedPrincipal;
6633 const uint32_t sandboxFlags =
6634 mBrowsingContext->GetHasLoadedNonInitialDocument()
6635 ? mBrowsingContext->GetSandboxFlags()
6636 : mBrowsingContext->GetInitialSandboxFlags();
6637 // If we're sandboxed, then create a new null principal. We skip
6638 // this if we're being created from WindowGlobalChild, since in
6639 // that case we already have a null principal if required.
6640 // We can't compare againt the BrowsingContext sandbox flag, since
6641 // the value was taken when the load initiated and may have since
6642 // changed.
6643 if ((sandboxFlags & SANDBOXED_ORIGIN) && !aActor) {
6644 if (aPrincipal) {
6645 principal = NullPrincipal::CreateWithInheritedAttributes(aPrincipal);
6646 } else {
6647 principal = NullPrincipal::Create(GetOriginAttributes());
6648 }
6649 partitionedPrincipal = principal;
6650 } else {
6651 principal = aPrincipal;
6652 partitionedPrincipal = aPartitionedPrincipal;
6653 }
6654
6655 // We cannot get the foreign partitioned principal for the initial
6656 // about:blank page. So, we change to check if we need to use the
6657 // partitioned principal for the service worker here.
6658 MaybeCreateInitialClientSource(
6659 StoragePrincipalHelper::ShouldUsePartitionPrincipalForServiceWorker(
6660 this)
6661 ? partitionedPrincipal
6662 : principal);
6663
6664 // generate (about:blank) document to load
6665 blankDoc = nsContentDLF::CreateBlankDocument(mLoadGroup, principal,
6666 partitionedPrincipal, this);
6667 if (blankDoc) {
6668 // Hack: manually set the policyContainer for the new document
6669 // Please create an actual copy of the policyContainer (do not share the
6670 // same reference) otherwise modifying the new container (such as
6671 // appending a new policy to CSP) within the new document will be
6672 // incorrectly propagated to the opening doc.
6673 if (aPolicyContainer) {
6674 RefPtr policyContainerToInherit = MakeRefPtr<PolicyContainer>();
6675 policyContainerToInherit->InitFromOther(
6676 PolicyContainer::Cast(aPolicyContainer));
6677 blankDoc->SetPolicyContainer(policyContainerToInherit);
6678 if (!PolicyContainer::GetCSP(policyContainerToInherit)) {
6679 RefPtr newCsp = MakeRefPtr<nsCSPContext>();
6680 policyContainerToInherit->SetCSP(newCsp);
6681 nsresult rv = newCsp->SetRequestContextWithDocument(blankDoc);
6682 if (NS_WARN_IF(NS_FAILED(rv))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(rv
)), 0))), "NS_FAILED(rv)", "./../../../docshell/base/nsDocShell.cpp"
, 6682)
) {
6683 return rv;
6684 }
6685 }
6686 }
6687
6688 blankDoc->SetInitialStatus(
6689 aIsInitialDocument ? Document::InitialStatus::IsInitialUncommitted
6690 : Document::InitialStatus::NeverInitial);
6691
6692 blankDoc->SetEmbedderPolicy(aCOEP);
6693
6694 // Hack: set the base URI manually, since this document never
6695 // got Reset() with a channel.
6696 blankDoc->SetBaseURI(aBaseURI);
6697
6698 // Copy our sandbox flags to the document. These are immutable
6699 // after being set here.
6700 blankDoc->SetSandboxFlags(sandboxFlags);
6701
6702 // We inherit the classification flags from the parent document if the
6703 // principal matches.
6704 nsCOMPtr<nsIDocShellTreeItem> parentItem;
6705 GetInProcessSameTypeParent(getter_AddRefs(parentItem));
6706 if (parentItem) {
6707 RefPtr<Document> parentDocument = parentItem->GetDocument();
6708 if (parentDocument && principal &&
6709 principal->Equals(parentDocument->NodePrincipal())) {
6710 blankDoc->SetClassificationFlags(
6711 parentDocument->GetClassificationFlags());
6712 }
6713 }
6714
6715 // create a content viewer for us and the new document
6716 docFactory->CreateInstanceForDocument(
6717 NS_ISUPPORTS_CAST(nsIDocShell*, this)static_cast<nsISupports*>(static_cast<nsIDocShell*>
(this))
, blankDoc, "view",
6718 getter_AddRefs(viewer));
6719
6720 // hook 'em up
6721 if (viewer) {
6722 viewer->SetContainer(this);
6723 if (mLoadingEntry && mBrowsingContext->IsTop()) {
6724 mLoadingEntry->mInfo.SetTransient();
6725 }
6726 const nsCOMPtr<nsIURI> uri = mCurrentURI;
6727 rv = Embed(viewer, aActor, true, nullptr, uri);
6728 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, "./../../../docshell/base/nsDocShell.cpp"
, 6728); return rv; } } while (false)
;
6729
6730 SetCurrentURI(blankDoc->GetDocumentURI(), nullptr,
6731 /* aFireLocationChange */ true,
6732 /* aIsInitialAboutBlank */ aIsInitialDocument,
6733 /* aLocationFlags */ 0);
6734 rv = mIsBeingDestroyed ? NS_ERROR_NOT_AVAILABLE : NS_OK;
6735 }
6736
6737 if (Element* embedderElement = blankDoc->GetEmbedderElement()) {
6738 blankDoc->InitFeaturePolicy(AsVariant(embedderElement));
6739 } else {
6740 blankDoc->InitFeaturePolicy(AsVariant(Nothing{}));
6741 }
6742
6743 // Perform redacted location.ancestorOrigins algorithm for about:blank
6744 if (BrowsingContext* bc = GetBrowsingContext();
6745 bc && bc->GetEmbedderElement()) {
6746 CreateAboutBlankAncestorOriginsForNonTopLevel(blankDoc);
6747 }
6748 }
6749 }
6750
6751 // Clear out our mTiming like we would in EndPageLoad, if we didn't
6752 // have one before entering this function.
6753 if (!hadTiming) {
6754 mTiming = nullptr;
6755 mBlankTiming = true;
6756 }
6757
6758 return rv;
6759}
6760
6761NS_IMETHODIMPnsresult
6762nsDocShell::CreateAboutBlankDocumentViewer(
6763 nsIPrincipal* aPrincipal, nsIPrincipal* aPartitionedPrincipal,
6764 nsIPolicyContainer* aPolicyContainer) {
6765 return CreateAboutBlankDocumentViewer(aPrincipal, aPartitionedPrincipal,
6766 aPolicyContainer, nullptr,
6767 /* aIsInitialDocument */ false);
6768}
6769
6770/* static */
6771void nsDocShell::ReportBFCacheComboTelemetry(uint32_t aCombo) {
6772 // There are 11 possible reasons to make a request fails to use BFCache
6773 // (see BFCacheStatus in dom/base/Document.h), and we'd like to record
6774 // the common combinations for reasons which make requests fail to use
6775 // BFCache. These combinations are generated based on some local browsings,
6776 // we need to adjust them when necessary.
6777 enum BFCacheStatusCombo : uint32_t {
6778 BFCACHE_SUCCESS,
6779 NOT_ONLY_TOPLEVEL = mozilla::dom::BFCacheStatus::NOT_ONLY_TOPLEVEL_IN_BCG,
6780 // If both unload and beforeunload listeners are presented, it'll be
6781 // recorded as unload
6782 UNLOAD = mozilla::dom::BFCacheStatus::UNLOAD_LISTENER,
6783 UNLOAD_REQUEST = mozilla::dom::BFCacheStatus::UNLOAD_LISTENER |
6784 mozilla::dom::BFCacheStatus::REQUEST,
6785 REQUEST = mozilla::dom::BFCacheStatus::REQUEST,
6786 UNLOAD_REQUEST_PEER = mozilla::dom::BFCacheStatus::UNLOAD_LISTENER |
6787 mozilla::dom::BFCacheStatus::REQUEST |
6788 mozilla::dom::BFCacheStatus::ACTIVE_PEER_CONNECTION,
6789 UNLOAD_REQUEST_PEER_MSE =
6790 mozilla::dom::BFCacheStatus::UNLOAD_LISTENER |
6791 mozilla::dom::BFCacheStatus::REQUEST |
6792 mozilla::dom::BFCacheStatus::ACTIVE_PEER_CONNECTION |
6793 mozilla::dom::BFCacheStatus::CONTAINS_MSE_CONTENT,
6794 UNLOAD_REQUEST_MSE = mozilla::dom::BFCacheStatus::UNLOAD_LISTENER |
6795 mozilla::dom::BFCacheStatus::REQUEST |
6796 mozilla::dom::BFCacheStatus::CONTAINS_MSE_CONTENT,
6797 SUSPENDED_UNLOAD_REQUEST_PEER =
6798 mozilla::dom::BFCacheStatus::SUSPENDED |
6799 mozilla::dom::BFCacheStatus::UNLOAD_LISTENER |
6800 mozilla::dom::BFCacheStatus::REQUEST |
6801 mozilla::dom::BFCacheStatus::ACTIVE_PEER_CONNECTION,
6802 REMOTE_SUBFRAMES = mozilla::dom::BFCacheStatus::CONTAINS_REMOTE_SUBFRAMES,
6803 BEFOREUNLOAD = mozilla::dom::BFCacheStatus::BEFOREUNLOAD_LISTENER,
6804 };
6805
6806 // Beforeunload is recorded as a blocker only if it is the only one to block
6807 // bfcache.
6808 if (aCombo != mozilla::dom::BFCacheStatus::BEFOREUNLOAD_LISTENER) {
6809 aCombo &= ~mozilla::dom::BFCacheStatus::BEFOREUNLOAD_LISTENER;
6810 }
6811 switch (aCombo) {
6812 case BFCACHE_SUCCESS:
6813 glean::bfcache::combo.EnumGet(glean::bfcache::ComboLabel::eBfcacheSuccess)
6814 .Add();
6815 break;
6816 case NOT_ONLY_TOPLEVEL:
6817 if (StaticPrefs::docshell_shistory_bfcache_require_no_opener()) {
6818 glean::bfcache::combo.EnumGet(glean::bfcache::ComboLabel::eOther).Add();
6819 break;
6820 }
6821 glean::bfcache::combo.EnumGet(glean::bfcache::ComboLabel::eBfcacheSuccess)
6822 .Add();
6823 glean::bfcache::combo
6824 .EnumGet(glean::bfcache::ComboLabel::eSuccessNotToplevel)
6825 .Add();
6826 break;
6827 case UNLOAD:
6828 glean::bfcache::combo.EnumGet(glean::bfcache::ComboLabel::eUnload).Add();
6829 break;
6830 case BEFOREUNLOAD:
6831 glean::bfcache::combo.EnumGet(glean::bfcache::ComboLabel::eBeforeunload)
6832 .Add();
6833 break;
6834 case UNLOAD_REQUEST:
6835 glean::bfcache::combo.EnumGet(glean::bfcache::ComboLabel::eUnloadReq)
6836 .Add();
6837 break;
6838 case REQUEST:
6839 glean::bfcache::combo.EnumGet(glean::bfcache::ComboLabel::eReq).Add();
6840 break;
6841 case UNLOAD_REQUEST_PEER:
6842 glean::bfcache::combo.EnumGet(glean::bfcache::ComboLabel::eUnloadReqPeer)
6843 .Add();
6844 break;
6845 case UNLOAD_REQUEST_PEER_MSE:
6846 glean::bfcache::combo
6847 .EnumGet(glean::bfcache::ComboLabel::eUnloadReqPeerMse)
6848 .Add();
6849 break;
6850 case UNLOAD_REQUEST_MSE:
6851 glean::bfcache::combo.EnumGet(glean::bfcache::ComboLabel::eUnloadReqMse)
6852 .Add();
6853 break;
6854 case SUSPENDED_UNLOAD_REQUEST_PEER:
6855 glean::bfcache::combo
6856 .EnumGet(glean::bfcache::ComboLabel::eSpdUnloadReqPeer)
6857 .Add();
6858 break;
6859 case REMOTE_SUBFRAMES:
6860 glean::bfcache::combo
6861 .EnumGet(glean::bfcache::ComboLabel::eRemoteSubframes)
6862 .Add();
6863 break;
6864 default:
6865 glean::bfcache::combo.EnumGet(glean::bfcache::ComboLabel::eOther).Add();
6866 break;
6867 }
6868};
6869
6870void nsDocShell::DetachEditorFromWindow() {
6871 if (!mEditorData || mEditorData->WaitingForLoad()) {
6872 // If there's nothing to detach, or if the editor data is actually set
6873 // up for the _new_ page that's coming in, don't detach.
6874 return;
6875 }
6876
6877 nsresult res = mEditorData->DetachFromWindow();
6878 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)", "./../../../docshell/base/nsDocShell.cpp"
, 6878); MOZ_PretendNoReturn(); } } while (0)
;
6879
6880 if (NS_SUCCEEDED(res)((bool)(__builtin_expect(!!(!NS_FAILED_impl(res)), 1)))) {
6881 mEditorData = nullptr;
6882 }
6883
6884#ifdef DEBUG1
6885 {
6886 bool isEditable;
6887 GetEditable(&isEditable);
6888 NS_ASSERTION(!isEditable,do { if (!(!isEditable)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "Window is still editable after detaching editor."
, "!isEditable", "./../../../docshell/base/nsDocShell.cpp", 6889
); MOZ_PretendNoReturn(); } } while (0)
6889 "Window is still editable after detaching editor.")do { if (!(!isEditable)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "Window is still editable after detaching editor."
, "!isEditable", "./../../../docshell/base/nsDocShell.cpp", 6889
); MOZ_PretendNoReturn(); } } while (0)
;
6890 }
6891#endif // DEBUG
6892}
6893
6894NS_IMETHODIMPnsresult
6895nsDocShell::GetRestoringDocument(bool* aRestoring) {
6896 *aRestoring = mIsRestoringDocument;
6897 return NS_OK;
6898}
6899
6900bool nsDocShell::SandboxFlagsImplyCookies(const uint32_t& aSandboxFlags) {
6901 return (aSandboxFlags & (SANDBOXED_ORIGIN | SANDBOXED_SCRIPTS)) == 0;
6902}
6903
6904nsresult nsDocShell::CreateDocumentViewer(const nsACString& aContentType,
6905 nsIRequest* aRequest,
6906 nsIStreamListener** aContentHandler) {
6907 *aContentHandler = nullptr;
6908
6909 if (!mTreeOwner || mIsBeingDestroyed) {
6910 // If we don't have a tree owner, then we're in the process of being
6911 // destroyed. Rather than continue trying to load something, just give up.
6912 return NS_ERROR_DOCSHELL_DYING;
6913 }
6914
6915 if (!mBrowsingContext->AncestorsAreCurrent() ||
6916 mBrowsingContext->IsInBFCache()) {
6917 mBrowsingContext->RemoveRootFromBFCacheSync();
6918 return NS_ERROR_NOT_AVAILABLE;
6919 }
6920
6921 // Can we check the content type of the current content viewer
6922 // and reuse it without destroying it and re-creating it?
6923
6924 NS_ASSERTION(mLoadGroup, "Someone ignored return from Init()?")do { if (!(mLoadGroup)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "Someone ignored return from Init()?"
, "mLoadGroup", "./../../../docshell/base/nsDocShell.cpp", 6924
); MOZ_PretendNoReturn(); } } while (0)
;
6925
6926 // Instantiate the content viewer object
6927 nsCOMPtr<nsIDocumentViewer> viewer;
6928 nsresult rv = NewDocumentViewerObj(aContentType, aRequest, mLoadGroup,
6929 aContentHandler, getter_AddRefs(viewer));
6930
6931 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
6932 return rv;
6933 }
6934
6935 // Notify the current document that it is about to be unloaded!!
6936 //
6937 // It is important to fire the unload() notification *before* any state
6938 // is changed within the DocShell - otherwise, javascript will get the
6939 // wrong information :-(
6940 //
6941
6942 NS_ASSERTION(!mLoadingURI, "Re-entering unload?")do { if (!(!mLoadingURI)) { NS_DebugBreak(NS_DEBUG_ASSERTION,
"Re-entering unload?", "!mLoadingURI", "./../../../docshell/base/nsDocShell.cpp"
, 6942); MOZ_PretendNoReturn(); } } while (0)
;
6943
6944 nsCOMPtr<nsIChannel> aOpenedChannel = do_QueryInterface(aRequest);
6945 if (aOpenedChannel) {
6946 aOpenedChannel->GetURI(getter_AddRefs(mLoadingURI));
6947 }
6948
6949 // Grab the current URI, we need to pass it to Embed, and OnNewURI will reset
6950 // it before we do call Embed.
6951 nsCOMPtr<nsIURI> previousURI = mCurrentURI;
6952
6953 FirePageHideNotification();
6954 if (mIsBeingDestroyed) {
6955 // Force to stop the newly created orphaned viewer.
6956 viewer->Stop();
6957 return NS_ERROR_DOCSHELL_DYING;
6958 }
6959 mLoadingURI = nullptr;
6960
6961 // Set mFiredUnloadEvent = false so that the unload handler for the
6962 // *new* document will fire.
6963 mFiredUnloadEvent = false;
6964
6965 // we've created a new document so go ahead and call
6966 // OnNewURI(), but don't fire OnLocationChange()
6967 // notifications before we've called Embed(). See bug 284993.
6968 mURIResultedInDocument = true;
6969 bool errorOnLocationChangeNeeded = false;
6970 nsCOMPtr<nsIChannel> failedChannel = mFailedChannel;
6971 nsCOMPtr<nsIURI> failedURI;
6972
6973 // https://html.spec.whatwg.org/#finalize-a-cross-document-navigation
6974 // 9. If entryToReplace is null, then: ...
6975 // Otherwise: ...
6976 // 4. If historyEntry's document state's origin is same origin with
6977 // entryToReplace's document state's origin, then set
6978 // historyEntry's navigation API key to entryToReplace's
6979 // navigation API key.
6980 bool isReplace =
6981 mActiveEntry && mLoadingEntry &&
6982 mLoadingEntry->mTriggeringNavigationType
6983 .map([](auto type) { return type == NavigationType::Replace; })
6984 .valueOr(false);
6985 if (isReplace) {
6986 nsCOMPtr<nsIURI> uri = mActiveEntry->GetURIOrInheritedForAboutBlank();
6987 nsCOMPtr<nsIURI> targetURI =
6988 mLoadingEntry->mInfo.GetURIOrInheritedForAboutBlank();
6989 bool sameOrigin =
6990 NS_SUCCEEDED(nsContentUtils::GetSecurityManager()->CheckSameOriginURI(((bool)(__builtin_expect(!!(!NS_FAILED_impl(nsContentUtils::GetSecurityManager
()->CheckSameOriginURI( targetURI, uri, false, false))), 1
)))
6991 targetURI, uri, false, false))((bool)(__builtin_expect(!!(!NS_FAILED_impl(nsContentUtils::GetSecurityManager
()->CheckSameOriginURI( targetURI, uri, false, false))), 1
)))
;
6992 if (sameOrigin) {
6993 mLoadingEntry->mInfo.NavigationKey() = mActiveEntry->NavigationKey();
6994 }
6995 }
6996
6997 if (mLoadType == LOAD_ERROR_PAGE) {
6998 // We need to set the SH entry and our current URI here and not
6999 // at the moment we load the page. We want the same behavior
7000 // of Stop() as for a normal page load. See bug 514232 for details.
7001
7002 // Revert mLoadType to load type to state the page load failed,
7003 // following function calls need it.
7004 mLoadType = mFailedLoadType;
7005
7006 Document* doc = viewer->GetDocument();
7007 if (doc) {
7008 doc->SetFailedChannel(failedChannel);
7009 }
7010
7011 nsCOMPtr<nsIPrincipal> triggeringPrincipal;
7012 if (failedChannel) {
7013 // Make sure we have a URI to set currentURI.
7014 NS_GetFinalChannelURI(failedChannel, getter_AddRefs(failedURI));
7015 } else {
7016 // if there is no failed channel we have to explicitly provide
7017 // a triggeringPrincipal for the history entry.
7018 triggeringPrincipal = nsContentUtils::GetSystemPrincipal();
7019 }
7020
7021 if (!failedURI) {
7022 failedURI = mFailedURI;
7023 }
7024 if (!failedURI) {
7025 // We need a URI object to store a session history entry, so make up a URI
7026 NS_NewURI(getter_AddRefs(failedURI), "about:blank");
7027 }
7028
7029 // When we don't have failedURI, something wrong will happen. See
7030 // bug 291876.
7031 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."
")", "./../../../docshell/base/nsDocShell.cpp", 7031); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "failedURI" ") (" "We don't have a URI for history APIs."
")"); do { MOZ_CrashSequence(__null, 7031); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7032
7033 mFailedChannel = nullptr;
7034 mFailedURI = nullptr;
7035
7036 // Create an shistory entry for the old load.
7037 if (failedURI) {
7038 errorOnLocationChangeNeeded =
7039 OnNewURI(failedURI, failedChannel, triggeringPrincipal, nullptr,
7040 nullptr, nullptr, false, false);
7041 }
7042
7043 mLoadType = LOAD_ERROR_PAGE;
7044 }
7045
7046 nsCOMPtr<nsIURI> finalURI;
7047 // If this a redirect, use the final url (uri)
7048 // else use the original url
7049 //
7050 // Note that this should match what documents do (see Document::Reset).
7051 NS_GetFinalChannelURI(aOpenedChannel, getter_AddRefs(finalURI));
7052
7053 bool onLocationChangeNeeded = false;
7054 if (finalURI) {
7055 // Pass false for aCloneSHChildren, since we're loading a new page here.
7056 onLocationChangeNeeded = OnNewURI(finalURI, aOpenedChannel, nullptr,
7057 nullptr, nullptr, nullptr, true, false);
7058 }
7059
7060 // We inherit the classification flags from the parent document if the
7061 // document is about:blank and the principal matches.
7062 nsCOMPtr<nsIDocShellTreeItem> parentItem;
7063 GetInProcessSameTypeParent(getter_AddRefs(parentItem));
7064 if (parentItem && finalURI && NS_IsAboutBlank(finalURI)) {
7065 RefPtr<Document> doc = viewer->GetDocument();
7066 RefPtr<Document> parentDocument = parentItem->GetDocument();
7067 if (parentDocument && doc &&
7068 doc->NodePrincipal()->Equals(parentDocument->NodePrincipal())) {
7069 doc->SetClassificationFlags(parentDocument->GetClassificationFlags());
7070 }
7071 }
7072
7073 // let's try resetting the load group if we need to...
7074 nsCOMPtr<nsILoadGroup> currentLoadGroup;
7075 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, "./../../../docshell/base/nsDocShell.cpp"
, 7077); return NS_ERROR_FAILURE; } } while (false)
7076 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, "./../../../docshell/base/nsDocShell.cpp"
, 7077); return NS_ERROR_FAILURE; } } while (false)
7077 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, "./../../../docshell/base/nsDocShell.cpp"
, 7077); return NS_ERROR_FAILURE; } } while (false)
;
7078
7079 if (currentLoadGroup != mLoadGroup) {
7080 nsLoadFlags loadFlags = 0;
7081
7082 // Cancel any URIs that are currently loading...
7083 // XXX: Need to do this eventually Stop();
7084 //
7085 // Retarget the document to this loadgroup...
7086 //
7087 /* First attach the channel to the right loadgroup
7088 * and then remove from the old loadgroup. This
7089 * puts the notifications in the right order and
7090 * we don't null-out mLSHE in OnStateChange() for
7091 * all redirected urls
7092 */
7093 aOpenedChannel->SetLoadGroup(mLoadGroup);
7094
7095 // Mark the channel as being a document URI...
7096 aOpenedChannel->GetLoadFlags(&loadFlags);
7097 loadFlags |= nsIChannel::LOAD_DOCUMENT_URI;
7098 nsCOMPtr<nsILoadInfo> loadInfo = aOpenedChannel->LoadInfo();
7099 if (SandboxFlagsImplyCookies(loadInfo->GetSandboxFlags())) {
7100 loadFlags |= nsIRequest::LOAD_DOCUMENT_NEEDS_COOKIE;
7101 }
7102
7103 aOpenedChannel->SetLoadFlags(loadFlags);
7104
7105 mLoadGroup->AddRequest(aRequest, nullptr);
7106 if (currentLoadGroup) {
7107 currentLoadGroup->RemoveRequest(aRequest, nullptr, NS_BINDING_RETARGETED);
7108 }
7109
7110 // Update the notification callbacks, so that progress and
7111 // status information are sent to the right docshell...
7112 aOpenedChannel->SetNotificationCallbacks(this);
7113 }
7114
7115 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, "./../../../docshell/base/nsDocShell.cpp"
, 7116); return NS_ERROR_FAILURE; } } while (false)
7116 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, "./../../../docshell/base/nsDocShell.cpp"
, 7116); return NS_ERROR_FAILURE; } } while (false)
;
7117
7118 if (!mBrowsingContext->GetHasLoadedNonInitialDocument()) {
7119 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))"
, "./../../../docshell/base/nsDocShell.cpp", 7119); AnnotateMozCrashReason
("MOZ_CRASH(" "NS_SUCCEEDED(mBrowsingContext->SetHasLoadedNonInitialDocument(true))"
")"); do { MOZ_CrashSequence(__null, 7119); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
;
7120 }
7121
7122 mSavedRefreshURIList = nullptr;
7123 mEODForCurrentDocument = false;
7124
7125 // if this document is part of a multipart document,
7126 // the ID can be used to distinguish it from the other parts.
7127 nsCOMPtr<nsIMultiPartChannel> multiPartChannel(do_QueryInterface(aRequest));
7128 if (multiPartChannel) {
7129 if (PresShell* presShell = GetPresShell()) {
7130 if (Document* doc = presShell->GetDocument()) {
7131 uint32_t partID;
7132 multiPartChannel->GetPartID(&partID);
7133 doc->SetPartID(partID);
7134 }
7135 }
7136 }
7137
7138 if (errorOnLocationChangeNeeded) {
7139 FireOnLocationChange(this, failedChannel, failedURI,
7140 LOCATION_CHANGE_ERROR_PAGE);
7141 } else if (onLocationChangeNeeded) {
7142 uint32_t locationFlags =
7143 (mLoadType & LOAD_CMD_RELOAD) ? uint32_t(LOCATION_CHANGE_RELOAD) : 0;
7144 FireOnLocationChange(this, aRequest, mCurrentURI, locationFlags);
7145 }
7146
7147 return NS_OK;
7148}
7149
7150nsresult nsDocShell::NewDocumentViewerObj(const nsACString& aContentType,
7151 nsIRequest* aRequest,
7152 nsILoadGroup* aLoadGroup,
7153 nsIStreamListener** aContentHandler,
7154 nsIDocumentViewer** aViewer) {
7155 nsCOMPtr<nsIChannel> aOpenedChannel = do_QueryInterface(aRequest);
7156
7157 nsCOMPtr<nsIDocumentLoaderFactory> docLoaderFactory =
7158 nsContentUtils::FindInternalDocumentViewer(aContentType);
7159 if (!docLoaderFactory) {
7160 return NS_ERROR_FAILURE;
7161 }
7162
7163 // Now create an instance of the content viewer nsLayoutDLF makes the
7164 // determination if it should be a "view-source" instead of "view"
7165 nsresult rv = docLoaderFactory->CreateInstance(
7166 "view", aOpenedChannel, aLoadGroup, aContentType, this, nullptr,
7167 aContentHandler, aViewer);
7168 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, "./../../../docshell/base/nsDocShell.cpp"
, 7168); return rv; } } while (false)
;
7169
7170 (*aViewer)->SetContainer(this);
7171 return NS_OK;
7172}
7173
7174nsresult nsDocShell::SetupNewViewer(nsIDocumentViewer* aNewViewer,
7175 WindowGlobalChild* aWindowActor) {
7176 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"
, "./../../../docshell/base/nsDocShell.cpp", 7176); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!mIsBeingDestroyed" ")"); do { MOZ_CrashSequence
(__null, 7176); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
7177
7178 //
7179 // Copy content viewer state from previous or parent content viewer.
7180 //
7181 // The following logic is mirrored in nsHTMLDocument::StartDocumentLoad!
7182 //
7183 // Do NOT to maintain a reference to the old content viewer outside
7184 // of this "copying" block, or it will not be destroyed until the end of
7185 // this routine and all <SCRIPT>s and event handlers fail! (bug 20315)
7186 //
7187 // In this block of code, if we get an error result, we return it
7188 // but if we get a null pointer, that's perfectly legal for parent
7189 // and parentDocumentViewer.
7190 //
7191
7192 int32_t x = 0;
7193 int32_t y = 0;
7194 int32_t cx = 0;
7195 int32_t cy = 0;
7196
7197 // This will get the size from the current content viewer or from the
7198 // Init settings
7199 DoGetPositionAndSize(&x, &y, &cx, &cy);
7200
7201 nsCOMPtr<nsIDocShellTreeItem> parentAsItem;
7202 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, "./../../../docshell/base/nsDocShell.cpp"
, 7203); return NS_ERROR_FAILURE; } } while (false)
7203 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, "./../../../docshell/base/nsDocShell.cpp"
, 7203); return NS_ERROR_FAILURE; } } while (false)
;
7204 nsCOMPtr<nsIDocShell> parent(do_QueryInterface(parentAsItem));
7205
7206 const Encoding* reloadEncoding = nullptr;
7207 int32_t reloadEncodingSource = kCharsetUninitialized;
7208 // |newMUDV| also serves as a flag to set the data from the above vars
7209 nsCOMPtr<nsIDocumentViewer> newViewer;
7210
7211 if (mDocumentViewer || parent) {
7212 nsCOMPtr<nsIDocumentViewer> oldViewer;
7213 if (mDocumentViewer) {
7214 // Get any interesting state from old content viewer
7215 // XXX: it would be far better to just reuse the document viewer ,
7216 // since we know we're just displaying the same document as before
7217 oldViewer = mDocumentViewer;
7218 } else {
7219 // No old content viewer, so get state from parent's content viewer
7220 parent->GetDocViewer(getter_AddRefs(oldViewer));
7221 }
7222
7223 if (oldViewer) {
7224 newViewer = aNewViewer;
7225 if (newViewer) {
7226 reloadEncoding =
7227 oldViewer->GetReloadEncodingAndSource(&reloadEncodingSource);
7228 }
7229 }
7230 }
7231
7232 SingleCanvasBackground canvasBg = {};
7233 bool isUnderHiddenEmbedderElement = false;
7234 // Ensure that the content viewer is destroyed *after* the GC - bug 71515
7235 nsCOMPtr<nsIDocumentViewer> viewer = mDocumentViewer;
7236 if (viewer) {
7237 // Stop any activity that may be happening in the old document before
7238 // releasing it...
7239 viewer->Stop();
7240
7241 // Try to extract the canvas background color from the old
7242 // presentation shell, so we can use it for the next document.
7243 if (PresShell* presShell = viewer->GetPresShell()) {
7244 canvasBg = presShell->GetViewportCanvasBackground();
7245 isUnderHiddenEmbedderElement = presShell->IsUnderHiddenEmbedderElement();
7246 }
7247
7248 viewer->Close();
7249 aNewViewer->SetPreviousViewer(viewer);
7250 }
7251
7252 mDocumentViewer = nullptr;
7253
7254 // Now that we're about to switch documents, forget all of our children.
7255 // Note that we cached them as needed up in CaptureState above.
7256 DestroyChildren();
7257
7258 mDocumentViewer = aNewViewer;
7259
7260 nsCOMPtr<nsIWidget> widget = GetMainWidget();
7261 LayoutDeviceIntRect bounds(x, y, cx, cy);
7262
7263 mDocumentViewer->SetNavigationTiming(mTiming);
7264
7265 nsresult rv =
7266 MOZ_KnownLive(mDocumentViewer)(mDocumentViewer)->Init(widget, bounds, aWindowActor);
7267 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
7268 nsCOMPtr<nsIDocumentViewer> viewer = mDocumentViewer;
7269 viewer->Close();
7270 viewer->Destroy();
7271 mDocumentViewer = nullptr;
7272 SetCurrentURIInternal(nullptr);
7273 NS_WARNING("DocumentViewer Initialization failed")NS_DebugBreak(NS_DEBUG_WARNING, "DocumentViewer Initialization failed"
, nullptr, "./../../../docshell/base/nsDocShell.cpp", 7273)
;
7274 return rv;
7275 }
7276
7277 // If we have old state to copy, set the old state onto the new content
7278 // viewer
7279 if (newViewer) {
7280 newViewer->SetReloadEncodingAndSource(reloadEncoding, reloadEncodingSource);
7281 }
7282
7283 NS_ENSURE_TRUE(mDocumentViewer, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(mDocumentViewer)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "mDocumentViewer" ") failed"
, nullptr, "./../../../docshell/base/nsDocShell.cpp", 7283); return
NS_ERROR_FAILURE; } } while (false)
;
7284
7285 // Stuff the bgcolor from the old pres shell into the new
7286 // pres shell. This improves page load continuity.
7287 if (RefPtr<PresShell> presShell = mDocumentViewer->GetPresShell()) {
7288 presShell->SetViewportCanvasBackground(canvasBg);
7289 presShell->ActivenessMaybeChanged();
7290 if (isUnderHiddenEmbedderElement) {
7291 presShell->SetIsUnderHiddenEmbedderElement(isUnderHiddenEmbedderElement);
7292 }
7293 }
7294
7295 // XXX: It looks like the LayoutState gets restored again in Embed()
7296 // right after the call to SetupNewViewer(...)
7297
7298 // We don't show the mDocumentViewer yet, since we want to draw the old page
7299 // until we have enough of the new page to show. Just return with the new
7300 // viewer still set to hidden.
7301
7302 return NS_OK;
7303}
7304
7305void nsDocShell::SetDocCurrentStateObj(SessionHistoryInfo* aInfo) {
7306 NS_ENSURE_TRUE_VOID(mDocumentViewer)do { if ((__builtin_expect(!!(!(mDocumentViewer)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "mDocumentViewer" ") failed"
, nullptr, "./../../../docshell/base/nsDocShell.cpp", 7306); return
; } } while (false)
;
7307
7308 RefPtr<Document> document = GetDocument();
7309 NS_ENSURE_TRUE_VOID(document)do { if ((__builtin_expect(!!(!(document)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "document" ") failed", nullptr
, "./../../../docshell/base/nsDocShell.cpp", 7309); return; }
} while (false)
;
7310
7311 nsCOMPtr<nsIStructuredCloneContainer> scContainer;
7312 // If aInfo is null, just set the document's state object to null.
7313 if (aInfo) {
7314 scContainer = aInfo->GetStateData();
7315 }
7316 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)
7317 ("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)
;
7318
7319 // It's OK for scContainer too be null here; that just means there's no
7320 // state data associated with this history entry.
7321 document->SetStateObject(scContainer);
7322}
7323
7324nsresult nsDocShell::CheckLoadingPermissions() {
7325 // This method checks whether the caller may load content into
7326 // this docshell. Even though we've done our best to hide windows
7327 // from code that doesn't have the right to access them, it's
7328 // still possible for an evil site to open a window and access
7329 // frames in the new window through window.frames[] (which is
7330 // allAccess for historic reasons), so we still need to do this
7331 // check on load.
7332 nsresult rv = NS_OK;
7333
7334 if (!IsSubframe()) {
7335 // We're not a frame. Permit all loads.
7336 return rv;
7337 }
7338
7339 // Note - The check for a current JSContext here isn't necessarily sensical.
7340 // It's just designed to preserve the old semantics during a mass-conversion
7341 // patch.
7342 if (!nsContentUtils::GetCurrentJSContext()) {
7343 return NS_OK;
7344 }
7345
7346 // Check if the caller is from the same origin as this docshell,
7347 // or any of its ancestors.
7348 nsIPrincipal* subjectPrincipal = nsContentUtils::SubjectPrincipal();
7349 for (RefPtr<BrowsingContext> bc = mBrowsingContext; bc;
7350 bc = bc->GetParent()) {
7351 // If the BrowsingContext is not in process, then it
7352 // is true by construction that its principal will not
7353 // subsume the current docshell principal.
7354 if (!bc->IsInProcess()) {
7355 continue;
7356 }
7357
7358 nsCOMPtr<nsIScriptGlobalObject> sgo =
7359 bc->GetDocShell()->GetScriptGlobalObject();
7360 nsCOMPtr<nsIScriptObjectPrincipal> sop(do_QueryInterface(sgo));
7361
7362 nsIPrincipal* p;
7363 if (!sop || !(p = sop->GetPrincipal())) {
7364 return NS_ERROR_UNEXPECTED;
7365 }
7366
7367 // file: URIs are considered the same domain for the purpose of frame
7368 // navigation by clicking a targeted link, regardless of script
7369 // accessibility (bug 1934807).
7370 if (subjectPrincipal->Subsumes(p) ||
7371 (subjectPrincipal->SchemeIs("file") && p->SchemeIs("file"))) {
7372 // Same origin, permit load
7373 return NS_OK;
7374 }
7375 }
7376
7377 return NS_ERROR_DOM_PROP_ACCESS_DENIED;
7378}
7379
7380//*****************************************************************************
7381// nsDocShell: Site Loading
7382//*****************************************************************************
7383
7384void nsDocShell::CopyFavicon(nsIURI* aOldURI, nsIURI* aNewURI,
7385 bool aInPrivateBrowsing) {
7386 if (XRE_IsContentProcess()) {
7387 dom::ContentChild* contentChild = dom::ContentChild::GetSingleton();
7388 if (contentChild) {
7389 contentChild->SendCopyFavicon(aOldURI, aNewURI, aInPrivateBrowsing);
7390 }
7391 return;
7392 }
7393
7394#ifdef MOZ_PLACES1
7395 auto* faviconService = nsFaviconService::GetFaviconService();
7396 if (faviconService) {
7397 faviconService->AsyncTryCopyFavicons(
7398 aOldURI, aNewURI,
7399 aInPrivateBrowsing ? nsIFaviconService::FAVICON_LOAD_PRIVATE
7400 : nsIFaviconService::FAVICON_LOAD_NON_PRIVATE);
7401 }
7402#endif
7403}
7404
7405class InternalLoadEvent : public Runnable {
7406 public:
7407 InternalLoadEvent(nsDocShell* aDocShell, nsDocShellLoadState* aLoadState)
7408 : mozilla::Runnable("InternalLoadEvent"),
7409 mDocShell(aDocShell),
7410 mLoadState(aLoadState) {
7411 // For events, both target and filename should be the version of "null" they
7412 // expect. By the time the event is fired, both window targeting and file
7413 // downloading have been handled, so we should never have an internal load
7414 // event that retargets or had a download.
7415 mLoadState->SetTarget(u""_ns);
7416 mLoadState->SetFileName(VoidString());
7417 }
7418
7419 NS_IMETHODvirtual nsresult
7420 Run() override {
7421#ifndef ANDROID
7422 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"
")", "./../../../docshell/base/nsDocShell.cpp", 7423); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "mLoadState->TriggeringPrincipal()" ") ("
"InternalLoadEvent: Should always have a principal here" ")"
); do { MOZ_CrashSequence(__null, 7423); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
7423 "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"
")", "./../../../docshell/base/nsDocShell.cpp", 7423); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "mLoadState->TriggeringPrincipal()" ") ("
"InternalLoadEvent: Should always have a principal here" ")"
); do { MOZ_CrashSequence(__null, 7423); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7424#endif
7425 return mDocShell->InternalLoad(mLoadState);
7426 }
7427
7428 private:
7429 RefPtr<nsDocShell> mDocShell;
7430 RefPtr<nsDocShellLoadState> mLoadState;
7431};
7432
7433/**
7434 * Returns true if we started an asynchronous load (i.e., from the network), but
7435 * the document we're loading there hasn't yet become this docshell's active
7436 * document.
7437 *
7438 * When JustStartedNetworkLoad is true, you should be careful about modifying
7439 * mLoadType and mLSHE. These are both set when the asynchronous load first
7440 * starts, and the load expects that, when it eventually runs InternalLoad,
7441 * mLoadType and mLSHE will have their original values.
7442 */
7443bool nsDocShell::JustStartedNetworkLoad() {
7444 return mDocumentRequest && mDocumentRequest != GetCurrentDocChannel();
7445}
7446
7447// The contentType will be INTERNAL_(I)FRAME if this docshell is for a
7448// non-toplevel browsing context in spec terms. (frame, iframe, <object>,
7449// <embed>, etc)
7450//
7451// This return value will be used when we call NS_CheckContentLoadPolicy, and
7452// later when we call DoURILoad.
7453nsContentPolicyType nsDocShell::DetermineContentType() {
7454 if (!IsSubframe()) {
7455 return nsIContentPolicy::TYPE_DOCUMENT;
7456 }
7457
7458 const auto& maybeEmbedderElementType =
7459 GetBrowsingContext()->GetEmbedderElementType();
7460 if (!maybeEmbedderElementType) {
7461 // If the EmbedderElementType hasn't been set yet, just assume we're
7462 // an iframe since that's more common.
7463 return nsIContentPolicy::TYPE_INTERNAL_IFRAME;
7464 }
7465
7466 return maybeEmbedderElementType->EqualsLiteral("iframe")
7467 ? nsIContentPolicy::TYPE_INTERNAL_IFRAME
7468 : nsIContentPolicy::TYPE_INTERNAL_FRAME;
7469}
7470
7471bool nsDocShell::NoopenerForceEnabled() {
7472 // If current's top-level browsing context's active document's
7473 // cross-origin-opener-policy is "same-origin" or "same-origin + COEP" then
7474 // if currentDoc's origin is not same origin with currentDoc's top-level
7475 // origin, noopener is force enabled, and name is cleared to "_blank".
7476 auto topPolicy = mBrowsingContext->Top()->GetOpenerPolicy();
7477 return (topPolicy == nsILoadInfo::OPENER_POLICY_SAME_ORIGIN ||
7478 topPolicy ==
7479 nsILoadInfo::
7480 OPENER_POLICY_SAME_ORIGIN_EMBEDDER_POLICY_REQUIRE_CORP) &&
7481 !mBrowsingContext->SameOriginWithTop();
7482}
7483
7484nsresult nsDocShell::ComputeNamedTargetBrowsingContext(
7485 nsDocShellLoadState* aLoadState) {
7486 if (aLoadState->HasComputedNamedTargetBrowsingContext() ||
7487 aLoadState->Target().IsEmpty()) {
7488 return NS_OK;
7489 }
7490 // Only _self, _parent, and _top are supported in noopener case. But we
7491 // have to be careful to not apply that to the noreferrer case. See bug
7492 // 1358469.
7493 bool allowNamedTarget =
7494 !aLoadState->HasInternalLoadFlags(INTERNAL_LOAD_FLAGS_NO_OPENER) ||
7495 aLoadState->HasInternalLoadFlags(INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER);
7496 if (allowNamedTarget ||
7497 aLoadState->Target().LowerCaseEqualsLiteral("_self") ||
7498 aLoadState->Target().LowerCaseEqualsLiteral("_parent") ||
7499 aLoadState->Target().LowerCaseEqualsLiteral("_top")) {
7500 Document* document = GetDocument();
7501 NS_ENSURE_TRUE(document, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(document)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "document" ") failed", nullptr
, "./../../../docshell/base/nsDocShell.cpp", 7501); return NS_ERROR_FAILURE
; } } while (false)
;
7502 WindowGlobalChild* wgc = document->GetWindowGlobalChild();
7503 NS_ENSURE_TRUE(wgc, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(wgc)), 0))) { NS_DebugBreak(NS_DEBUG_WARNING
, "NS_ENSURE_TRUE(" "wgc" ") failed", nullptr, "./../../../docshell/base/nsDocShell.cpp"
, 7503); return NS_ERROR_FAILURE; } } while (false)
;
7504 aLoadState->SetTargetBrowsingContext(wgc->FindBrowsingContextWithName(
7505 aLoadState->Target(), /* aUseEntryGlobalForAccessCheck */ false));
7506 }
7507 aLoadState->SetHasComputedNamedTargetBrowsingContext(true);
7508 return NS_OK;
7509}
7510
7511nsresult nsDocShell::PerformRetargeting(nsDocShellLoadState* aLoadState) {
7512 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!"
")", "./../../../docshell/base/nsDocShell.cpp", 7512); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aLoadState" ") (" "need a load state!" ")"
); do { MOZ_CrashSequence(__null, 7512); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7513 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!"
")", "./../../../docshell/base/nsDocShell.cpp", 7513); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!aLoadState->Target().IsEmpty()" ") (" "should have a target here!"
")"); do { MOZ_CrashSequence(__null, 7513); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7514
7515 nsresult rv = NS_OK;
7516
7517 rv = ComputeNamedTargetBrowsingContext(aLoadState);
7518 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, "./../../../docshell/base/nsDocShell.cpp"
, 7518); return rv; } } while (false)
;
7519 const MaybeDiscarded<BrowsingContext>& targetBCMaybeDiscarded =
7520 aLoadState->TargetBrowsingContext();
7521 if (targetBCMaybeDiscarded.IsDiscarded()) {
7522 // e.g. target frame navigated to cross-origin site before async navigation
7523 // happened
7524 return NS_BINDING_ABORTED;
7525 }
7526 RefPtr<BrowsingContext> targetContext =
7527 targetBCMaybeDiscarded.GetMaybeDiscarded();
7528
7529 if (!targetContext) {
7530 // If the targetContext doesn't exist, then this is a new docShell and we
7531 // should consider this a TYPE_DOCUMENT load
7532 //
7533 // For example, when target="_blank"
7534
7535 // If there's no targetContext, that means we are about to create a new
7536 // window. Perform a content policy check before creating the window. Please
7537 // note for all other docshell loads content policy checks are performed
7538 // within the contentSecurityManager when the channel is about to be
7539 // openend.
7540 nsISupports* requestingContext = nullptr;
7541 if (XRE_IsContentProcess()) {
7542 // In e10s the child process doesn't have access to the element that
7543 // contains the browsing context (because that element is in the chrome
7544 // process). So we just pass mScriptGlobal.
7545 requestingContext = ToSupports(mScriptGlobal);
7546 } else {
7547 // This is for loading non-e10s tabs and toplevel windows of various
7548 // sorts.
7549 // For the toplevel window cases, requestingElement will be null.
7550 nsCOMPtr<Element> requestingElement =
7551 mScriptGlobal->GetFrameElementInternal();
7552 requestingContext = requestingElement;
7553 }
7554
7555 // Ideally we should use the same loadinfo as within DoURILoad which
7556 // should match this one when both are applicable.
7557 RefPtr secCheckLoadInfo = MakeRefPtr<LoadInfo>(
7558 mScriptGlobal, aLoadState->URI(), aLoadState->TriggeringPrincipal(),
7559 requestingContext, nsILoadInfo::SEC_ONLY_FOR_EXPLICIT_CONTENTSEC_CHECK,
7560 0);
7561
7562 // Since Content Policy checks are performed within docShell as well as
7563 // the ContentSecurityManager we need a reliable way to let certain
7564 // nsIContentPolicy consumers ignore duplicate calls.
7565 secCheckLoadInfo->SetSkipContentPolicyCheckForWebRequest(true);
7566
7567 int16_t shouldLoad = nsIContentPolicy::ACCEPT;
7568 rv = NS_CheckContentLoadPolicy(aLoadState->URI(), secCheckLoadInfo,
7569 &shouldLoad);
7570
7571 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) || NS_CP_REJECTED(shouldLoad)((shouldLoad) != nsIContentPolicy::ACCEPT)) {
7572 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
7573 if (shouldLoad == nsIContentPolicy::REJECT_TYPE) {
7574 return NS_ERROR_CONTENT_BLOCKED_SHOW_ALT;
7575 }
7576 if (shouldLoad == nsIContentPolicy::REJECT_POLICY) {
7577 return NS_ERROR_BLOCKED_BY_POLICY;
7578 }
7579 }
7580
7581 return NS_ERROR_CONTENT_BLOCKED;
7582 }
7583 }
7584
7585 //
7586 // Resolve the window target before going any further...
7587 // If the load has been targeted to another DocShell, then transfer the
7588 // load to it...
7589 //
7590
7591 // We've already done our owner-inheriting. Mask out that bit, so we
7592 // don't try inheriting an owner from the target window if we came up
7593 // with a null owner above.
7594 aLoadState->UnsetInternalLoadFlag(INTERNAL_LOAD_FLAGS_INHERIT_PRINCIPAL);
7595
7596 if (!targetContext) {
7597 // If the docshell's document is sandboxed, only open a new window
7598 // if the document's SANDBOXED_AUXILLARY_NAVIGATION flag is not set.
7599 // (i.e. if allow-popups is specified)
7600 NS_ENSURE_TRUE(mDocumentViewer, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(mDocumentViewer)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "mDocumentViewer" ") failed"
, nullptr, "./../../../docshell/base/nsDocShell.cpp", 7600); return
NS_ERROR_FAILURE; } } while (false)
;
7601 Document* doc = mDocumentViewer->GetDocument();
7602
7603 const bool isDocumentAuxSandboxed =
7604 doc && (doc->GetSandboxFlags() & SANDBOXED_AUXILIARY_NAVIGATION);
7605
7606 if (isDocumentAuxSandboxed) {
7607 return NS_ERROR_DOM_INVALID_ACCESS_ERR;
7608 }
7609
7610 nsCOMPtr<nsPIDOMWindowOuter> win = GetWindow();
7611 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, "./../../../docshell/base/nsDocShell.cpp"
, 7611); return NS_ERROR_NOT_AVAILABLE; } } while (false)
;
7612
7613 RefPtr<BrowsingContext> newBC;
7614 nsAutoCString spec;
7615 aLoadState->URI()->GetSpec(spec);
7616
7617 // If we are a noopener load, we just hand the whole thing over to our
7618 // window.
7619 if (aLoadState->HasInternalLoadFlags(INTERNAL_LOAD_FLAGS_NO_OPENER) ||
7620 NoopenerForceEnabled()) {
7621 // Various asserts that we know to hold because NO_OPENER loads can only
7622 // happen for links.
7623 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()", "./../../../docshell/base/nsDocShell.cpp"
, 7623); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aLoadState->LoadReplace()"
")"); do { MOZ_CrashSequence(__null, 7623); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7624 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()"
, "./../../../docshell/base/nsDocShell.cpp", 7625); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aLoadState->PrincipalToInherit() == aLoadState->TriggeringPrincipal()"
")"); do { MOZ_CrashSequence(__null, 7625); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
7625 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()"
, "./../../../docshell/base/nsDocShell.cpp", 7625); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aLoadState->PrincipalToInherit() == aLoadState->TriggeringPrincipal()"
")"); do { MOZ_CrashSequence(__null, 7625); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7626 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"
")", "./../../../docshell/base/nsDocShell.cpp", 7630); 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, 7630); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
7627 ~(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"
")", "./../../../docshell/base/nsDocShell.cpp", 7630); 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, 7630); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
7628 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"
")", "./../../../docshell/base/nsDocShell.cpp", 7630); 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, 7630); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
7629 "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"
")", "./../../../docshell/base/nsDocShell.cpp", 7630); 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, 7630); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
7630 "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"
")", "./../../../docshell/base/nsDocShell.cpp", 7630); 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, 7630); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7631 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()", "./../../../docshell/base/nsDocShell.cpp"
, 7632); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->IsFormSubmission()"
")"); do { MOZ_CrashSequence(__null, 7632); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
7632 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()", "./../../../docshell/base/nsDocShell.cpp"
, 7632); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->IsFormSubmission()"
")"); do { MOZ_CrashSequence(__null, 7632); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
7633 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()", "./../../../docshell/base/nsDocShell.cpp"
, 7633); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aLoadState->HeadersStream()"
")"); do { MOZ_CrashSequence(__null, 7633); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7634 // If OnLinkClickSync was invoked inside the onload handler, the load
7635 // type would be set to LOAD_NORMAL_REPLACE; otherwise it should be
7636 // LOAD_LINK.
7637 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"
, "./../../../docshell/base/nsDocShell.cpp", 7638); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aLoadState->LoadType() == LOAD_LINK || aLoadState->LoadType() == LOAD_NORMAL_REPLACE"
")"); do { MOZ_CrashSequence(__null, 7638); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
7638 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"
, "./../../../docshell/base/nsDocShell.cpp", 7638); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aLoadState->LoadType() == LOAD_LINK || aLoadState->LoadType() == LOAD_NORMAL_REPLACE"
")"); do { MOZ_CrashSequence(__null, 7638); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7639 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()"
, "./../../../docshell/base/nsDocShell.cpp", 7639); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!aLoadState->LoadIsFromSessionHistory()"
")"); do { MOZ_CrashSequence(__null, 7639); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7640 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()"
, "./../../../docshell/base/nsDocShell.cpp", 7640); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aLoadState->FirstParty()" ")"); do { MOZ_CrashSequence
(__null, 7640); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
; // Windowwatcher will assume this.
7641
7642 RefPtr loadState = MakeRefPtr<nsDocShellLoadState>(aLoadState->URI());
7643
7644 // Set up our loadinfo so it will do the load as much like we would have
7645 // as possible.
7646 loadState->SetReferrerInfo(aLoadState->GetReferrerInfo());
7647 loadState->SetOriginalURI(aLoadState->OriginalURI());
7648
7649 Maybe<nsCOMPtr<nsIURI>> resultPrincipalURI;
7650 aLoadState->GetMaybeResultPrincipalURI(resultPrincipalURI);
7651
7652 loadState->SetMaybeResultPrincipalURI(resultPrincipalURI);
7653 loadState->SetKeepResultPrincipalURIIfSet(
7654 aLoadState->KeepResultPrincipalURIIfSet());
7655 // LoadReplace will always be false due to asserts above, skip setting
7656 // it.
7657 loadState->SetTriggeringPrincipal(aLoadState->TriggeringPrincipal());
7658 loadState->SetTriggeringSandboxFlags(
7659 aLoadState->TriggeringSandboxFlags());
7660 loadState->SetTriggeringWindowId(aLoadState->TriggeringWindowId());
7661 loadState->SetTriggeringStorageAccess(
7662 aLoadState->TriggeringStorageAccess());
7663 loadState->SetTriggeringClassificationFlags(
7664 aLoadState->TriggeringClassificationFlags());
7665 loadState->SetPolicyContainer(aLoadState->PolicyContainer());
7666 loadState->SetInheritPrincipal(aLoadState->HasInternalLoadFlags(
7667 INTERNAL_LOAD_FLAGS_INHERIT_PRINCIPAL));
7668 // Explicit principal because we do not want any guesses as to what the
7669 // principal to inherit is: it should be aTriggeringPrincipal.
7670 loadState->SetPrincipalIsExplicit(true);
7671 loadState->SetLoadType(aLoadState->LoadType());
7672 loadState->SetForceAllowDataURI(aLoadState->HasInternalLoadFlags(
7673 INTERNAL_LOAD_FLAGS_FORCE_ALLOW_DATA_URI));
7674
7675 loadState->SetHasValidUserGestureActivation(
7676 aLoadState->HasValidUserGestureActivation());
7677
7678 loadState->SetTextDirectiveUserActivation(
7679 aLoadState->GetTextDirectiveUserActivation());
7680
7681 // Propagate POST data to the new load.
7682 loadState->SetPostDataStream(aLoadState->PostDataStream());
7683 loadState->SetIsFormSubmission(aLoadState->IsFormSubmission());
7684
7685 loadState->SetNavigationAPIState(aLoadState->GetNavigationAPIState());
7686
7687 rv = win->Open(spec,
7688 aLoadState->Target(), // window name
7689 u""_ns, // Features
7690 loadState,
7691 true, // aForceNoOpener
7692 getter_AddRefs(newBC));
7693 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", "./../../../docshell/base/nsDocShell.cpp"
, 7693); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!newBC" ")"
); do { MOZ_CrashSequence(__null, 7693); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7694 return rv;
7695 }
7696
7697 rv = win->OpenNoNavigate(spec,
7698 aLoadState->Target(), // window name
7699 u""_ns, // Features
7700 getter_AddRefs(newBC));
7701
7702 // In some cases the Open call doesn't actually result in a new
7703 // window being opened. We can detect these cases by examining the
7704 // document in |newBC|, if any.
7705 nsCOMPtr<nsPIDOMWindowOuter> piNewWin =
7706 newBC ? newBC->GetDOMWindow() : nullptr;
7707 if (piNewWin) {
7708 RefPtr<Document> newDoc = piNewWin->GetExtantDoc();
7709 if (!newDoc || newDoc->IsInitialDocument()) {
7710 aLoadState->SetInternalLoadFlag(INTERNAL_LOAD_FLAGS_FIRST_LOAD);
7711 }
7712 }
7713
7714 if (newBC) {
7715 targetContext = newBC;
7716 }
7717 }
7718 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, "./../../../docshell/base/nsDocShell.cpp"
, 7718); return rv; } } while (false)
;
7719 NS_ENSURE_TRUE(targetContext, rv)do { if ((__builtin_expect(!!(!(targetContext)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "targetContext" ") failed"
, nullptr, "./../../../docshell/base/nsDocShell.cpp", 7719); return
rv; } } while (false)
;
7720
7721 // If our target BrowsingContext is still pending initialization, ignore the
7722 // navigation request targeting it.
7723 if (NS_WARN_IF(targetContext->GetPendingInitialization())NS_warn_if_impl(targetContext->GetPendingInitialization(),
"targetContext->GetPendingInitialization()", "./../../../docshell/base/nsDocShell.cpp"
, 7723)
) {
7724 return NS_OK;
7725 }
7726
7727 aLoadState->SetTargetBrowsingContext(targetContext);
7728 if (aLoadState->IsFormSubmission()) {
7729 aLoadState->SetLoadType(
7730 GetLoadTypeForFormSubmission(targetContext, aLoadState));
7731 }
7732
7733 //
7734 // Transfer the load to the target BrowsingContext... Clear the window target
7735 // name to the empty string to prevent recursive retargeting!
7736 //
7737 // No window target
7738 aLoadState->SetTarget(u""_ns);
7739 // No forced download
7740 aLoadState->SetFileName(VoidString());
7741 return targetContext->InternalLoad(aLoadState);
7742}
7743
7744static nsAutoCString RefMaybeNull(nsIURI* aURI) {
7745 nsAutoCString result;
7746 if (NS_FAILED(aURI->GetRef(result))((bool)(__builtin_expect(!!(NS_FAILED_impl(aURI->GetRef(result
))), 0)))
) {
7747 result.SetIsVoid(true);
7748 }
7749 return result;
7750}
7751
7752uint32_t nsDocShell::GetSameDocumentNavigationFlags(nsIURI* aNewURI) {
7753 uint32_t flags = LOCATION_CHANGE_SAME_DOCUMENT;
7754
7755 bool equal = false;
7756 if (mCurrentURI &&
7757 NS_SUCCEEDED(mCurrentURI->EqualsExceptRef(aNewURI, &equal))((bool)(__builtin_expect(!!(!NS_FAILED_impl(mCurrentURI->EqualsExceptRef
(aNewURI, &equal))), 1)))
&& equal &&
7758 RefMaybeNull(mCurrentURI) != RefMaybeNull(aNewURI)) {
7759 flags |= LOCATION_CHANGE_HASHCHANGE;
7760 }
7761
7762 return flags;
7763}
7764
7765struct SameDocumentNavigationState {
7766 nsAutoCString mCurrentHash;
7767 nsAutoCString mNewHash;
7768 nsTArray<TextDirective> mTextDirectives;
7769 bool mCurrentURIHasRef = false;
7770 bool mNewURIHasRef = false;
7771 bool mSameExceptHashes = false;
7772 bool mSecureUpgradeURI = false;
7773 bool mHistoryNavBetweenSameDoc = false;
7774 bool mIdentical = false;
7775};
7776
7777bool nsDocShell::IsSameDocumentNavigation(nsDocShellLoadState* aLoadState,
7778 SameDocumentNavigationState& aState) {
7779 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", "./../../../docshell/base/nsDocShell.cpp"
, 7779); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState"
")"); do { MOZ_CrashSequence(__null, 7779); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7780 if (!(aLoadState->LoadType() == LOAD_NORMAL ||
7781 aLoadState->LoadType() == LOAD_STOP_CONTENT ||
7782 LOAD_TYPE_HAS_FLAGS(aLoadState->LoadType(),((aLoadState->LoadType()) & ((LOAD_FLAGS_REPLACE_HISTORY
) << 16))
7783 LOAD_FLAGS_REPLACE_HISTORY)((aLoadState->LoadType()) & ((LOAD_FLAGS_REPLACE_HISTORY
) << 16))
||
7784 aLoadState->LoadType() == LOAD_HISTORY ||
7785 aLoadState->LoadType() == LOAD_LINK)) {
7786 return false;
7787 }
7788
7789 if (GetExtantDocument() &&
7790 GetExtantDocument()->IsUncommittedInitialDocument()) {
7791 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 false, document is "
"uncommitted initial", this); } } while (0)
7792 ("nsDocShell::IsSameDocumentNavigation %p false, document is "do { const ::mozilla::LogModule* moz_real_module = 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 false, document is "
"uncommitted initial", this); } } while (0)
7793 "uncommitted initial",do { const ::mozilla::LogModule* moz_real_module = 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 false, document is "
"uncommitted initial", this); } } while (0)
7794 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::IsSameDocumentNavigation %p false, document is "
"uncommitted initial", this); } } while (0)
;
7795 return false;
7796 }
7797
7798 nsCOMPtr<nsIURI> currentURI = mCurrentURI;
7799
7800 nsresult rvURINew = aLoadState->URI()->GetRef(aState.mNewHash);
7801 if (NS_SUCCEEDED(rvURINew)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rvURINew)), 1)))) {
7802 rvURINew = aLoadState->URI()->GetHasRef(&aState.mNewURIHasRef);
7803 }
7804
7805 // A Fragment Directive must be removed from the new hash in order to allow
7806 // fallback element id scroll.
7807 FragmentDirective::ParseAndRemoveFragmentDirectiveFromFragmentString(
7808 aState.mNewHash, &aState.mTextDirectives, aLoadState->URI());
7809
7810 if (currentURI && NS_SUCCEEDED(rvURINew)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rvURINew)), 1)))) {
7811 nsresult rvURIOld = currentURI->GetRef(aState.mCurrentHash);
7812 if (NS_SUCCEEDED(rvURIOld)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rvURIOld)), 1)))) {
7813 rvURIOld = currentURI->GetHasRef(&aState.mCurrentURIHasRef);
7814 }
7815 if (NS_SUCCEEDED(rvURIOld)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rvURIOld)), 1)))) {
7816 if (NS_FAILED(currentURI->EqualsExceptRef(aLoadState->URI(),((bool)(__builtin_expect(!!(NS_FAILED_impl(currentURI->EqualsExceptRef
(aLoadState->URI(), &aState.mSameExceptHashes))), 0)))
7817 &aState.mSameExceptHashes))((bool)(__builtin_expect(!!(NS_FAILED_impl(currentURI->EqualsExceptRef
(aLoadState->URI(), &aState.mSameExceptHashes))), 0)))
) {
7818 aState.mSameExceptHashes = false;
7819 }
7820 }
7821 }
7822
7823 if (!aState.mSameExceptHashes && currentURI && NS_SUCCEEDED(rvURINew)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rvURINew)), 1)))) {
7824 // Maybe aLoadState->URI() came from the exposable form of currentURI?
7825 nsCOMPtr<nsIURI> currentExposableURI =
7826 nsIOService::CreateExposableURI(currentURI);
7827 nsresult rvURIOld = currentExposableURI->GetRef(aState.mCurrentHash);
7828 if (NS_SUCCEEDED(rvURIOld)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rvURIOld)), 1)))) {
7829 rvURIOld = currentExposableURI->GetHasRef(&aState.mCurrentURIHasRef);
7830 }
7831 if (NS_SUCCEEDED(rvURIOld)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rvURIOld)), 1)))) {
7832 if (NS_FAILED(currentExposableURI->EqualsExceptRef(((bool)(__builtin_expect(!!(NS_FAILED_impl(currentExposableURI
->EqualsExceptRef( aLoadState->URI(), &aState.mSameExceptHashes
))), 0)))
7833 aLoadState->URI(), &aState.mSameExceptHashes))((bool)(__builtin_expect(!!(NS_FAILED_impl(currentExposableURI
->EqualsExceptRef( aLoadState->URI(), &aState.mSameExceptHashes
))), 0)))
) {
7834 aState.mSameExceptHashes = false;
7835 }
7836 // HTTPS-Only Mode upgrades schemes from http to https in Necko, hence we
7837 // have to perform a special check here to avoid an actual navigation. If
7838 // HTTPS-Only Mode is enabled and the two URIs are same-origin (modulo the
7839 // fact that the new URI is currently http), then set mSameExceptHashes to
7840 // true and only perform a fragment navigation.
7841 if (!aState.mSameExceptHashes) {
7842 if (nsCOMPtr<nsIChannel> docChannel = GetCurrentDocChannel()) {
7843 nsCOMPtr<nsILoadInfo> docLoadInfo = docChannel->LoadInfo();
7844 nsHTTPSOnlyUtils::UpgradeMode upgradeMode =
7845 nsHTTPSOnlyUtils::GetUpgradeMode(docLoadInfo);
7846 if (!docLoadInfo->GetLoadErrorPage() &&
7847 (upgradeMode == nsHTTPSOnlyUtils::HTTPS_ONLY_MODE ||
7848 upgradeMode == nsHTTPSOnlyUtils::HTTPS_FIRST_MODE) &&
7849 nsHTTPSOnlyUtils::IsHttpDowngrade(currentExposableURI,
7850 aLoadState->URI())) {
7851 uint32_t status = docLoadInfo->GetHttpsOnlyStatus();
7852 if ((status &
7853 (nsILoadInfo::HTTPS_ONLY_UPGRADED_LISTENER_REGISTERED |
7854 nsILoadInfo::HTTPS_ONLY_UPGRADED_HTTPS_FIRST)) &&
7855 !(status & nsILoadInfo::HTTPS_ONLY_EXEMPT)) {
7856 // At this point the requested URI is for sure a fragment
7857 // navigation via HTTP and HTTPS-Only mode or HTTPS-First is
7858 // enabled. Also it is not interfering the upgrade order of
7859 // https://searchfox.org/firefox-main/source/netwerk/base/nsNetUtil.cpp#2948-2953.
7860 // Since we are on an HTTPS site the fragment
7861 // navigation should also be an HTTPS.
7862 // For that reason we should upgrade the URI to HTTPS.
7863 aState.mSecureUpgradeURI = true;
7864 aState.mSameExceptHashes = true;
7865 }
7866 }
7867 }
7868 }
7869 }
7870 }
7871
7872 if (mActiveEntry && aLoadState->LoadIsFromSessionHistory()) {
7873 aState.mHistoryNavBetweenSameDoc = mActiveEntry->SharesDocumentWith(
7874 aLoadState->GetLoadingSessionHistoryInfo()->mInfo);
7875 }
7876 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)
7877 ("nsDocShell::IsSameDocumentNavigation %p NavBetweenSameDoc=%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::IsSameDocumentNavigation %p NavBetweenSameDoc=%d"
, this, aState.mHistoryNavBetweenSameDoc); } } while (0)
7878 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)
;
7879
7880 // Two URIs are identical if they're same except hashes, they both have
7881 // hashes, and their hashes are the same.
7882 aState.mIdentical = aState.mSameExceptHashes &&
7883 (aState.mNewURIHasRef == aState.mCurrentURIHasRef) &&
7884 aState.mCurrentHash.Equals(aState.mNewHash);
7885
7886 // A same document navigation happens when we navigate between two SHEntries
7887 // for the same document. We do a same document navigation under two
7888 // circumstances. Either
7889 //
7890 // a) we're navigating between two different SHEntries which share a
7891 // document, or
7892 //
7893 // b) we're navigating to a new shentry whose URI differs from the
7894 // current URI only in its hash, the new hash is non-empty, and
7895 // we're not doing a POST.
7896 //
7897 // The restriction that the SHEntries in (a) must be different ensures
7898 // that history.go(0) and the like trigger full refreshes, rather than
7899 // same document navigations.
7900 if (aState.mHistoryNavBetweenSameDoc &&
7901 !aLoadState->GetLoadingSessionHistoryInfo()->mLoadingCurrentEntry) {
7902 return true;
7903 }
7904
7905 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)
7906 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)
7907 ("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)
7908 "!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)
7909 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)
7910 !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)
7911 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)
7912 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)
;
7913 return !aLoadState->LoadIsFromSessionHistory() &&
7914 !aLoadState->PostDataStream() && aState.mSameExceptHashes &&
7915 aState.mNewURIHasRef;
7916}
7917
7918static bool IsSamePrincipalForDocumentURI(nsIPrincipal* aCurrentPrincipal,
7919 nsIURI* aCurrentURI,
7920 nsIURI* aNewURI) {
7921 nsCOMPtr<nsIURI> principalURI = aCurrentPrincipal->GetURI();
7922 if (aCurrentPrincipal->GetIsNullPrincipal()) {
7923 if (nsCOMPtr<nsIPrincipal> precursor =
7924 aCurrentPrincipal->GetPrecursorPrincipal()) {
7925 principalURI = precursor->GetURI();
7926 }
7927 }
7928
7929 return !nsScriptSecurityManager::IsHttpOrHttpsAndCrossOrigin(principalURI,
7930 aNewURI) &&
7931 !nsScriptSecurityManager::IsHttpOrHttpsAndCrossOrigin(principalURI,
7932 aCurrentURI) &&
7933 !nsScriptSecurityManager::IsHttpOrHttpsAndCrossOrigin(aCurrentURI,
7934 aNewURI);
7935}
7936
7937nsresult nsDocShell::HandleSameDocumentNavigation(
7938 nsDocShellLoadState* aLoadState, SameDocumentNavigationState& aState,
7939 bool& aSameDocument) {
7940 aSameDocument = true;
7941#ifdef DEBUG1
7942 SameDocumentNavigationState state;
7943 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)"
, "./../../../docshell/base/nsDocShell.cpp", 7943); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "IsSameDocumentNavigation(aLoadState, state)"
")"); do { MOZ_CrashSequence(__null, 7943); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7944#endif
7945
7946 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)
7947 ("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)
7948 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)
7949 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)
;
7950
7951 RefPtr<Document> doc = GetDocument();
7952 NS_ENSURE_TRUE(doc, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(doc)), 0))) { NS_DebugBreak(NS_DEBUG_WARNING
, "NS_ENSURE_TRUE(" "doc" ") failed", nullptr, "./../../../docshell/base/nsDocShell.cpp"
, 7952); return NS_ERROR_FAILURE; } } while (false)
;
7953
7954 nsCOMPtr<nsIURI> currentURI = mCurrentURI;
7955
7956 // We need to upgrade the new URI from http: to https:
7957 nsCOMPtr<nsIURI> newURI = aLoadState->URI();
7958 if (aState.mSecureUpgradeURI) {
7959 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(); })
;
7960 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)
7961 ("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)
;
7962 }
7963
7964 // check if documentPrincipal, mCurrentURI, and aLoadState->URI() are same
7965 // origin skip handling otherwise
7966 if (!IsSamePrincipalForDocumentURI(doc->NodePrincipal(), mCurrentURI,
7967 newURI)) {
7968 aSameDocument = false;
7969 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)
7970 ("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)
7971 "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)
7972 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)
;
7973 return NS_OK;
7974 }
7975
7976 // https://html.spec.whatwg.org/#navigate-fragid
7977 // Step 2
7978 RefPtr<nsIStructuredCloneContainer> destinationNavigationAPIState =
7979 mActiveEntry ? mActiveEntry->GetNavigationAPIState() : nullptr;
7980 // Step 3
7981 if (auto* navigationAPIState = aLoadState->GetNavigationAPIState()) {
7982 destinationNavigationAPIState = navigationAPIState;
7983 }
7984
7985 if (nsCOMPtr<nsPIDOMWindowInner> window = doc->GetInnerWindow();
7986 window && !aState.mHistoryNavBetweenSameDoc) {
7987 // https://html.spec.whatwg.org/#navigate-fragid
7988 // Step 1
7989 if (RefPtr<Navigation> navigation = window->Navigation()) {
7990 AutoJSAPI jsapi;
7991 if (jsapi.Init(window)) {
7992 RefPtr<Element> sourceElement = aLoadState->GetSourceElement();
7993 // Step 4
7994 RefPtr apiMethodTracker = aLoadState->GetNavigationAPIMethodTracker();
7995 bool shouldContinue = navigation->FirePushReplaceReloadNavigateEvent(
7996 jsapi.cx(), aLoadState->GetNavigationType(), newURI,
7997 /* aIsSameDocument */ true,
7998 Some(aLoadState->UserNavigationInvolvement()), sourceElement,
7999 /* aFormDataEntryList */ nullptr,
8000 /* aNavigationAPIState */ destinationNavigationAPIState,
8001 /* aClassicHistoryAPIState */ nullptr, apiMethodTracker);
8002
8003 // Step 5
8004 if (!shouldContinue) {
8005 return NS_OK;
8006 }
8007 }
8008 }
8009 }
8010
8011 doc->DoNotifyPossibleTitleChange();
8012
8013 // Store the pending uninvoked directives if it is a same document
8014 // navigation. We need to set it here, in case the navigation happens before
8015 // the document has actually finished loading.
8016 doc->FragmentDirective()->SetTextDirectives(
8017 std::move(aState.mTextDirectives));
8018
8019#ifdef DEBUG1
8020 if (aState.mSameExceptHashes) {
8021 bool sameExceptHashes = false;
8022 currentURI->EqualsExceptRef(newURI, &sameExceptHashes);
8023 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"
, "./../../../docshell/base/nsDocShell.cpp", 8023); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "sameExceptHashes" ")"); do { MOZ_CrashSequence
(__null, 8023); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
8024 }
8025#endif
8026 const nsCOMPtr<nsILoadInfo> loadInfo =
8027 doc->GetChannel() ? doc->GetChannel()->LoadInfo() : nullptr;
8028 if (loadInfo) {
8029 loadInfo->SetIsSameDocumentNavigation(true);
8030 }
8031 // Save the position of the scrollers.
8032 nsPoint scrollPos = GetCurScrollPos();
8033
8034 // Reset mLoadType to its original value once we exit this block, because this
8035 // same document navigation might have started after a normal, network load,
8036 // and we don't want to clobber its load type. See bug 737307.
8037 Maybe<AutoRestore<uint32_t>> loadTypeResetter;
8038 if (StaticPrefs::
8039 docshell_shistory_sameDocumentNavigationOverridesLoadType() &&
8040 !doc->NodePrincipal()->IsURIInPrefList(
8041 "docshell.shistory.sameDocumentNavigationOverridesLoadType."
8042 "forceDisable")) {
8043 loadTypeResetter.emplace(mLoadType);
8044 }
8045 if (JustStartedNetworkLoad() && !loadTypeResetter.isSome()) {
8046 loadTypeResetter.emplace(mLoadType);
8047 }
8048
8049 // If a non-same-document-navigation (i.e., a network load) is pending, make
8050 // this a replacement load, so that we don't add a SHEntry here and the
8051 // network load goes into the SHEntry it expects to.
8052 if (JustStartedNetworkLoad() && (aLoadState->LoadType() & LOAD_CMD_NORMAL)) {
8053 mLoadType = LOAD_NORMAL_REPLACE;
8054 } else {
8055 mLoadType = aLoadState->LoadType();
8056 }
8057
8058 mURIResultedInDocument = true;
8059
8060 // we need to assign aLoadState->SHEntry() to mLoadingEntry right here, so
8061 // that on History loads, SetCurrentURI() called from OnNewURI() will send
8062 // proper onLocationChange() notifications to the browser to update
8063 // back/forward buttons.
8064 UniquePtr<mozilla::dom::LoadingSessionHistoryInfo> oldLoadingEntry;
8065 mLoadingEntry.swap(oldLoadingEntry);
8066 if (aLoadState->GetLoadingSessionHistoryInfo()) {
8067 mLoadingEntry = MakeUnique<LoadingSessionHistoryInfo>(
8068 *aLoadState->GetLoadingSessionHistoryInfo());
8069 mNeedToReportActiveAfterLoadingBecomesActive = false;
8070 }
8071
8072 // Set the doc's URI according to the new history entry's URI.
8073 doc->SetDocumentURI(newURI);
8074
8075 /* This is a anchor traversal within the same page.
8076 * call OnNewURI() so that, this traversal will be
8077 * recorded in session and global history.
8078 */
8079 nsCOMPtr<nsIPrincipal> newURITriggeringPrincipal, newURIPrincipalToInherit,
8080 newURIPartitionedPrincipalToInherit;
8081 nsCOMPtr<nsIPolicyContainer> newPolicyContainer;
8082 if (mActiveEntry) {
8083 newURITriggeringPrincipal = mActiveEntry->GetTriggeringPrincipal();
8084 newURIPrincipalToInherit = mActiveEntry->GetPrincipalToInherit();
8085 newURIPartitionedPrincipalToInherit =
8086 mActiveEntry->GetPartitionedPrincipalToInherit();
8087 newPolicyContainer = mActiveEntry->GetPolicyContainer();
8088 } else {
8089 newURITriggeringPrincipal = aLoadState->TriggeringPrincipal();
8090 newURIPrincipalToInherit = doc->NodePrincipal();
8091 newURIPartitionedPrincipalToInherit = doc->PartitionedPrincipal();
8092 newPolicyContainer = doc->GetPolicyContainer();
8093 }
8094
8095 uint32_t locationChangeFlags = GetSameDocumentNavigationFlags(newURI);
8096
8097 // Pass true for aCloneSHChildren, since we're not
8098 // changing documents here, so all of our subframes are
8099 // still relevant to the new session history entry.
8100 //
8101 // It also makes OnNewURI(...) set LOCATION_CHANGE_SAME_DOCUMENT
8102 // flag on firing onLocationChange(...).
8103 // Anyway, aCloneSHChildren param is simply reflecting
8104 // doSameDocumentNavigation in this scope.
8105 //
8106 // Note: we'll actually fire onLocationChange later, in order to preserve
8107 // ordering of HistoryCommit() in the parent vs onLocationChange (bug
8108 // 1668126)
8109 bool locationChangeNeeded = OnNewURI(
8110 newURI, nullptr, newURITriggeringPrincipal, newURIPrincipalToInherit,
8111 newURIPartitionedPrincipalToInherit, newPolicyContainer, true, true);
8112
8113 nsCOMPtr<nsIInputStream> postData;
8114 nsCOMPtr<nsIReferrerInfo> referrerInfo;
8115 uint32_t cacheKey = 0;
8116
8117 bool scrollRestorationIsManual = false;
8118 if (mActiveEntry) {
8119 mActiveEntry->SetScrollPosition(scrollPos.x, scrollPos.y);
8120 if (mBrowsingContext) {
8121 CollectWireframe();
8122 if (XRE_IsParentProcess()) {
8123 SessionHistoryEntry* entry =
8124 mBrowsingContext->Canonical()->GetActiveSessionHistoryEntry();
8125 if (entry) {
8126 entry->SetScrollPosition(scrollPos.x, scrollPos.y);
8127 }
8128 } else {
8129 (void)ContentChild::GetSingleton()
8130 ->SendSessionHistoryEntryScrollPosition(mBrowsingContext,
8131 scrollPos.x, scrollPos.y);
8132 }
8133 }
8134 }
8135 if (mLoadingEntry && !mLoadingEntry->mLoadIsFromSessionHistory) {
8136 // If we're not doing a history load, scroll restoration
8137 // should be inherited from the previous session history entry.
8138 // XXX This needs most probably tweaks once fragment navigation is
8139 // fixed to work with session-history-in-parent.
8140 SetScrollRestorationIsManualOnHistoryEntry(scrollRestorationIsManual);
8141 }
8142
8143 // If we're doing a history load, use its scroll restoration state.
8144 if (aLoadState->LoadIsFromSessionHistory()) {
8145 scrollRestorationIsManual = aLoadState->GetLoadingSessionHistoryInfo()
8146 ->mInfo.GetScrollRestorationIsManual();
8147 }
8148
8149 /* Make a new mActiveEntry. This will either be a new entry created
8150 * by OnNewURI() for normal loads or aLoadState->SHEntry() for history
8151 * loads.
8152 */
8153 if (aLoadState->LoadIsFromSessionHistory()) {
8154 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)
8155 ("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)
8156 "%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)
8157 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)
;
8158
8159 nsCOMPtr<nsILayoutHistoryState> currentLayoutHistoryState;
8160 if (mActiveEntry) {
8161 currentLayoutHistoryState = mActiveEntry->GetLayoutHistoryState();
8162 }
8163
8164 UniquePtr<SessionHistoryInfo> previousActiveEntry(mActiveEntry.release());
8165 mActiveEntry = MakeUnique<SessionHistoryInfo>(mLoadingEntry->mInfo);
8166 if (currentLayoutHistoryState) {
8167 // Restore the existing nsILayoutHistoryState object, since it is
8168 // possibly being used by the layout. When doing a new load, the
8169 // shared state is copied from the existing active entry, so this
8170 // special case is needed only with the history loads.
8171 mActiveEntry->SetLayoutHistoryState(currentLayoutHistoryState);
8172 }
8173
8174 if (cacheKey != 0) {
8175 mActiveEntry->SetCacheKey(cacheKey);
8176 }
8177
8178 // We're passing in mCurrentURI, which could be null. SessionHistoryCommit
8179 // does require a non-null uri if this is for a refresh load of the same
8180 // URI, but in that case mCurrentURI won't be null here.
8181 mBrowsingContext->SessionHistoryCommit(
8182 *mLoadingEntry, mLoadType, mCurrentURI, previousActiveEntry.get(), true,
8183 /* No expiration update on the same document loads*/
8184 false, cacheKey);
8185 // FIXME Need to set postdata.
8186
8187 // Set the title for the SH entry for this target url so that
8188 // SH menus in go/back/forward buttons won't be empty for this.
8189 // Note, when session history lives in the parent process, this does not
8190 // update the title there.
8191 SetTitleOnHistoryEntry(false);
8192 } else {
8193 Maybe<bool> scrollRestorationIsManual;
8194 if (mActiveEntry) {
8195 scrollRestorationIsManual.emplace(
8196 mActiveEntry->GetScrollRestorationIsManual());
8197
8198 // Get the postdata, page ident and referrer info from the current page,
8199 // if the new load is being done via normal means. Note that "normal
8200 // means" can be checked for just by checking for LOAD_CMD_NORMAL, given
8201 // the loadType and allowScroll check above -- it filters out some
8202 // LOAD_CMD_NORMAL cases that we wouldn't want here.
8203 if (aLoadState->LoadType() & LOAD_CMD_NORMAL) {
8204 postData = mActiveEntry->GetPostData();
8205 cacheKey = mActiveEntry->GetCacheKey();
8206 referrerInfo = mActiveEntry->GetReferrerInfo();
8207 }
8208 }
8209
8210 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)
8211 ("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)
8212 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)
;
8213 UniquePtr<SessionHistoryInfo> previousActiveEntry(mActiveEntry.release());
8214 if (previousActiveEntry) {
8215 mActiveEntry =
8216 MakeUnique<SessionHistoryInfo>(*previousActiveEntry, newURI);
8217 } else {
8218 mActiveEntry = MakeUnique<SessionHistoryInfo>(
8219 newURI, newURITriggeringPrincipal, newURIPrincipalToInherit,
8220 newURIPartitionedPrincipalToInherit, newPolicyContainer,
8221 mContentTypeHint);
8222 }
8223
8224 // Save the postData obtained from the previous page in to the session
8225 // history entry created for the anchor page, so that any history load of
8226 // the anchor page will restore the appropriate postData.
8227 if (postData) {
8228 mActiveEntry->SetPostData(postData);
8229 }
8230
8231 // Make sure we won't just repost without hitting the
8232 // cache first
8233 if (cacheKey != 0) {
8234 mActiveEntry->SetCacheKey(cacheKey);
8235 }
8236
8237 // As the document has not changed, the referrer info hasn't changed too,
8238 // so we can just copy it over.
8239 if (referrerInfo) {
8240 mActiveEntry->SetReferrerInfo(referrerInfo);
8241 }
8242
8243 // Set the title for the SH entry for this target url so that
8244 // SH menus in go/back/forward buttons won't be empty for this.
8245 mActiveEntry->SetTitle(mTitle);
8246
8247 if (scrollRestorationIsManual.isSome()) {
8248 mActiveEntry->SetScrollRestorationIsManual(
8249 scrollRestorationIsManual.value());
8250 }
8251
8252 if (destinationNavigationAPIState) {
8253 mActiveEntry->SetNavigationAPIState(destinationNavigationAPIState);
8254 }
8255
8256 if (LOAD_TYPE_HAS_FLAGS(mLoadType, LOAD_FLAGS_REPLACE_HISTORY)((mLoadType) & ((LOAD_FLAGS_REPLACE_HISTORY) << 16)
)
) {
8257 if (previousActiveEntry) {
8258 mActiveEntry->NavigationKey() = previousActiveEntry->NavigationKey();
8259 }
8260 mBrowsingContext->ReplaceActiveSessionHistoryEntry(mActiveEntry.get());
8261 } else {
8262 mBrowsingContext->IncrementHistoryEntryCountForBrowsingContext();
8263 // FIXME We should probably just compute mChildOffset in the parent
8264 // instead of passing it over IPC here.
8265 mBrowsingContext->SetActiveSessionHistoryEntry(
8266 Some(scrollPos), mActiveEntry.get(), previousActiveEntry.get(),
8267 mLoadType, cacheKey);
8268 // FIXME Do we need to update mPreviousEntryIndex and mLoadedEntryIndex?
8269 }
8270 }
8271
8272 if (locationChangeNeeded) {
8273 FireOnLocationChange(this, nullptr, newURI, locationChangeFlags);
8274 }
8275
8276 /* Restore the original LSHE if we were loading something
8277 * while same document navigation was initiated.
8278 */
8279 mLoadingEntry.swap(oldLoadingEntry);
8280
8281 /* Set the title for the Global History entry for this anchor url.
8282 */
8283 UpdateGlobalHistoryTitle(newURI);
8284
8285 SetDocCurrentStateObj(mActiveEntry.get());
8286
8287 // Inform the favicon service that the favicon for oldURI also
8288 // applies to newURI.
8289 CopyFavicon(currentURI, newURI, UsePrivateBrowsing());
8290
8291 RefPtr<nsGlobalWindowOuter> scriptGlobal = mScriptGlobal;
8292 nsCOMPtr<nsPIDOMWindowInner> win =
8293 scriptGlobal ? scriptGlobal->GetCurrentInnerWindow() : nullptr;
8294
8295 // https://html.spec.whatwg.org/#scroll-to-fragid
8296 // 14. Update document for history step application given navigable's
8297 // active document, historyEntry, true, scriptHistoryIndex,
8298 // scriptHistoryLength, and historyHandling.
8299 if (RefPtr navigation = win ? win->Navigation() : nullptr) {
8300 MOZ_LOG(gNavigationAPILog, LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = gNavigationAPILog
; 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)
8301 ("nsDocShell %p triggering a navigation event from "do { const ::mozilla::LogModule* moz_real_module = gNavigationAPILog
; 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)
8302 "HandleSameDocumentNavigation",do { const ::mozilla::LogModule* moz_real_module = gNavigationAPILog
; 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)
8303 this))do { const ::mozilla::LogModule* moz_real_module = gNavigationAPILog
; 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)
;
8304 // https://html.spec.whatwg.org/#update-document-for-history-step-application
8305 // 6.4.2. Update the navigation API entries for a same-document
8306 // navigation given navigation, entry, and navigationType.
8307 navigation->UpdateEntriesForSameDocumentNavigation(
8308 mActiveEntry.get(),
8309 NavigationUtils::NavigationTypeFromLoadType(mLoadType).valueOr(
8310 NavigationType::Push));
8311 }
8312
8313 // The check for uninvoked directives must come before ScrollToAnchor() is
8314 // called.
8315 const bool hasTextDirectives =
8316 doc->FragmentDirective()->HasUninvokedDirectives();
8317
8318 // https://html.spec.whatwg.org/#scroll-to-fragid
8319 // 15. Scroll to the fragment given navigable's active document.
8320
8321 // ScrollToAnchor doesn't necessarily cause us to scroll the window;
8322 // the function decides whether a scroll is appropriate based on the
8323 // arguments it receives. But even if we don't end up scrolling,
8324 // ScrollToAnchor performs other important tasks, such as informing
8325 // the presShell that we have a new hash. See bug 680257.
8326 nsresult rv = ScrollToAnchor(aState.mCurrentURIHasRef, aState.mNewURIHasRef,
8327 aState.mNewHash, aLoadState->LoadType());
8328 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, "./../../../docshell/base/nsDocShell.cpp"
, 8328); return rv; } } while (false)
;
8329
8330 /* restore previous position of scroller(s), if we're moving
8331 * back in history (bug 59774)
8332 */
8333 nscoord bx = 0;
8334 nscoord by = 0;
8335 bool needsScrollPosUpdate = false;
8336 if (mActiveEntry &&
8337 (aLoadState->LoadType() == LOAD_HISTORY ||
8338 aLoadState->LoadType() == LOAD_RELOAD_NORMAL) &&
8339 !scrollRestorationIsManual) {
8340 needsScrollPosUpdate = true;
8341 mActiveEntry->GetScrollPosition(&bx, &by);
8342 }
8343
8344 // Dispatch the popstate and hashchange events, as appropriate.
8345 //
8346 // The event dispatch below can cause us to re-enter script and
8347 // destroy the docshell, nulling out mScriptGlobal. Hold a stack
8348 // reference to avoid null derefs. See bug 914521.
8349 if (win) {
8350 // Fire a hashchange event URIs differ, and only in their hashes.
8351 // If the fragment contains a directive, compare hasRef.
8352 bool doHashchange = aState.mSameExceptHashes &&
8353 (!aState.mCurrentHash.Equals(aState.mNewHash) ||
8354 (hasTextDirectives &&
8355 aState.mCurrentURIHasRef != aState.mNewURIHasRef));
8356
8357 // We enqueue the hashchange event first before dispatching popstate,
8358 // differing from the spec.
8359 // See: https://github.com/whatwg/html/issues/12190
8360 if (doHashchange) {
8361 // Note that currentURI hasn't changed because it's on the
8362 // stack, so we can just use it directly as the old URI.
8363 win->DispatchAsyncHashchange(currentURI, newURI);
8364 }
8365
8366 if (aState.mHistoryNavBetweenSameDoc || doHashchange) {
8367 win->DispatchSyncPopState();
8368 }
8369
8370 if (needsScrollPosUpdate && win->HasActiveDocument()) {
8371 SetCurScrollPosEx(bx, by);
8372 }
8373 }
8374
8375 return NS_OK;
8376}
8377
8378static bool NavigationShouldTakeFocus(nsDocShell* aDocShell,
8379 nsDocShellLoadState* aLoadState) {
8380 if (!aLoadState->AllowFocusMove()) {
8381 return false;
8382 }
8383 if (!aLoadState->HasValidUserGestureActivation()) {
8384 return false;
8385 }
8386 const auto& sourceBC = aLoadState->SourceBrowsingContext();
8387 if (!sourceBC || !sourceBC->IsActive()) {
8388 // If the navigation didn't come from a foreground tab, then we don't steal
8389 // focus.
8390 return false;
8391 }
8392 auto* bc = aDocShell->GetBrowsingContext();
8393 if (sourceBC.get() == bc) {
8394 // If it comes from the same tab / frame, don't steal focus either.
8395 return false;
8396 }
8397 auto* fm = nsFocusManager::GetFocusManager();
8398 if (fm && bc->IsActive() && fm->IsInActiveWindow(bc)) {
8399 // If we're already on the foreground tab of the foreground window, then we
8400 // don't need to do this. This helps to e.g. not steal focus from the
8401 // browser chrome unnecessarily.
8402 return false;
8403 }
8404 if (auto* doc = aDocShell->GetExtantDocument()) {
8405 if (doc->IsInitialDocument()) {
8406 // If we're the initial load for the browsing context, the browser
8407 // chrome determines what to focus. This is important because the
8408 // browser chrome may want to e.g focus the url-bar
8409 return false;
8410 }
8411 }
8412 // Take loadDivertedInBackground into account so the behavior would be the
8413 // same as how the tab first opened.
8414 return !Preferences::GetBool("browser.tabs.loadDivertedInBackground", false);
8415}
8416
8417uint32_t nsDocShell::GetLoadTypeForFormSubmission(
8418 BrowsingContext* aTargetBC, nsDocShellLoadState* aLoadState) {
8419 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()", "./../../../docshell/base/nsDocShell.cpp"
, 8419); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->IsFormSubmission()"
")"); do { MOZ_CrashSequence(__null, 8419); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8420
8421 // https://html.spec.whatwg.org/#form-submission-algorithm
8422 // 22. Let historyHandling be "push".
8423 // 23. If form document equals targetNavigable's active document, and
8424 // form document has not yet completely loaded, then set
8425 // historyHandling to "replace".
8426 return GetBrowsingContext() == aTargetBC && !mEODForCurrentDocument
8427 ? LOAD_NORMAL_REPLACE
8428 : LOAD_LINK;
8429}
8430
8431static void MaybeConvertToReplaceLoad(nsDocShellLoadState* aLoadState,
8432 Document* aExtantDocument,
8433 bool aIdenticalURI,
8434 bool aHasActiveEntry) {
8435 // MaybeConvertToReplaceLoad implements steps 12 and 13 of #navigate, but
8436 // since we're not yet using historyBehavior for all types of loads and
8437 // configurations, we need to sometimes bail and revert to the old way of
8438 // handling push to replace load conversion. The different cases we can't
8439 // handle are:
8440 //
8441 // * When we don't have an active document
8442 // * When a document doesn't yet have a session history entry
8443 // * When we don't use historyBehavior
8444 if (!aExtantDocument || !aHasActiveEntry || !aLoadState->HistoryBehavior()) {
8445 aLoadState->ResetHistoryBehavior();
8446 return;
8447 }
8448
8449 bool convertToReplaceLoad = aLoadState->NeedsCompletelyLoadedDocument() &&
8450 !aExtantDocument->IsCompletelyLoaded();
8451 if (const auto& historyBehavior = aLoadState->HistoryBehavior();
8452 !convertToReplaceLoad && historyBehavior &&
8453 *historyBehavior == NavigationHistoryBehavior::Auto) {
8454 convertToReplaceLoad = aIdenticalURI;
8455 if (convertToReplaceLoad && aExtantDocument->GetPrincipal()) {
8456 aExtantDocument->GetPrincipal()->Equals(aLoadState->TriggeringPrincipal(),
8457 &convertToReplaceLoad);
8458 }
8459 } else if (aLoadState->HistoryBehavior() ==
8460 Some(NavigationHistoryBehavior::Replace)) {
8461 // This load is supposed to be a replace, regardless of completely loaded.
8462 // This can happen for form submissions since the planned form
8463 // navigation might be queued before the document is completely loaded
8464 // and then actually run after it is completely loaded:
8465 // https://html.spec.whatwg.org/#concept-form-submit
8466 convertToReplaceLoad = true;
8467 }
8468
8469 convertToReplaceLoad =
8470 convertToReplaceLoad || nsContentUtils::NavigationMustBeAReplace(
8471 *aLoadState->URI(), *aExtantDocument);
8472
8473 if (convertToReplaceLoad) {
8474 MOZ_LOG_FMT(gNavigationAPILog, LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = gNavigationAPILog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print_fmt(moz_real_module
, LogLevel::Debug, "Convert to replace when navigating from {} to {}, {}"
, *aExtantDocument->GetDocumentURI(), *aLoadState->URI(
), (aLoadState->NeedsCompletelyLoadedDocument() &&
!nsContentUtils::NavigationMustBeAReplace(*aLoadState->URI
(), *aExtantDocument)) ? "needs completely loaded document" :
"navigation must be a replace"); } } while (0)
8475 "Convert to replace when navigating from {} to {}, {}",do { const ::mozilla::LogModule* moz_real_module = gNavigationAPILog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print_fmt(moz_real_module
, LogLevel::Debug, "Convert to replace when navigating from {} to {}, {}"
, *aExtantDocument->GetDocumentURI(), *aLoadState->URI(
), (aLoadState->NeedsCompletelyLoadedDocument() &&
!nsContentUtils::NavigationMustBeAReplace(*aLoadState->URI
(), *aExtantDocument)) ? "needs completely loaded document" :
"navigation must be a replace"); } } while (0)
8476 *aExtantDocument->GetDocumentURI(), *aLoadState->URI(),do { const ::mozilla::LogModule* moz_real_module = gNavigationAPILog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print_fmt(moz_real_module
, LogLevel::Debug, "Convert to replace when navigating from {} to {}, {}"
, *aExtantDocument->GetDocumentURI(), *aLoadState->URI(
), (aLoadState->NeedsCompletelyLoadedDocument() &&
!nsContentUtils::NavigationMustBeAReplace(*aLoadState->URI
(), *aExtantDocument)) ? "needs completely loaded document" :
"navigation must be a replace"); } } while (0)
8477 (aLoadState->NeedsCompletelyLoadedDocument() &&do { const ::mozilla::LogModule* moz_real_module = gNavigationAPILog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print_fmt(moz_real_module
, LogLevel::Debug, "Convert to replace when navigating from {} to {}, {}"
, *aExtantDocument->GetDocumentURI(), *aLoadState->URI(
), (aLoadState->NeedsCompletelyLoadedDocument() &&
!nsContentUtils::NavigationMustBeAReplace(*aLoadState->URI
(), *aExtantDocument)) ? "needs completely loaded document" :
"navigation must be a replace"); } } while (0)
8478 !nsContentUtils::NavigationMustBeAReplace(*aLoadState->URI(),do { const ::mozilla::LogModule* moz_real_module = gNavigationAPILog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print_fmt(moz_real_module
, LogLevel::Debug, "Convert to replace when navigating from {} to {}, {}"
, *aExtantDocument->GetDocumentURI(), *aLoadState->URI(
), (aLoadState->NeedsCompletelyLoadedDocument() &&
!nsContentUtils::NavigationMustBeAReplace(*aLoadState->URI
(), *aExtantDocument)) ? "needs completely loaded document" :
"navigation must be a replace"); } } while (0)
8479 *aExtantDocument))do { const ::mozilla::LogModule* moz_real_module = gNavigationAPILog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print_fmt(moz_real_module
, LogLevel::Debug, "Convert to replace when navigating from {} to {}, {}"
, *aExtantDocument->GetDocumentURI(), *aLoadState->URI(
), (aLoadState->NeedsCompletelyLoadedDocument() &&
!nsContentUtils::NavigationMustBeAReplace(*aLoadState->URI
(), *aExtantDocument)) ? "needs completely loaded document" :
"navigation must be a replace"); } } while (0)
8480 ? "needs completely loaded document"do { const ::mozilla::LogModule* moz_real_module = gNavigationAPILog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print_fmt(moz_real_module
, LogLevel::Debug, "Convert to replace when navigating from {} to {}, {}"
, *aExtantDocument->GetDocumentURI(), *aLoadState->URI(
), (aLoadState->NeedsCompletelyLoadedDocument() &&
!nsContentUtils::NavigationMustBeAReplace(*aLoadState->URI
(), *aExtantDocument)) ? "needs completely loaded document" :
"navigation must be a replace"); } } while (0)
8481 : "navigation must be a replace")do { const ::mozilla::LogModule* moz_real_module = gNavigationAPILog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print_fmt(moz_real_module
, LogLevel::Debug, "Convert to replace when navigating from {} to {}, {}"
, *aExtantDocument->GetDocumentURI(), *aLoadState->URI(
), (aLoadState->NeedsCompletelyLoadedDocument() &&
!nsContentUtils::NavigationMustBeAReplace(*aLoadState->URI
(), *aExtantDocument)) ? "needs completely loaded document" :
"navigation must be a replace"); } } while (0)
;
8482 // There is no replace variant for LOAD_LINK, so we convert it to
8483 // LOAD_NORMAL_REPLACE just like in nsDocShell::OnNewURI.
8484 if (aLoadState->LoadType() == LOAD_LINK) {
8485 aLoadState->SetLoadType(LOAD_NORMAL_REPLACE);
8486 } else {
8487 aLoadState->SetLoadType(
8488 MaybeAddLoadFlags(aLoadState->LoadType(),
8489 nsIWebNavigation::LOAD_FLAGS_REPLACE_HISTORY));
8490 }
8491 aLoadState->SetHistoryBehavior(NavigationHistoryBehavior::Replace);
8492 } else {
8493 aLoadState->SetHistoryBehavior(NavigationHistoryBehavior::Push);
8494 }
8495}
8496
8497// InternalLoad performs several of the steps from
8498// https://html.spec.whatwg.org/#navigate.
8499nsresult nsDocShell::InternalLoad(nsDocShellLoadState* aLoadState,
8500 Maybe<uint32_t> aCacheKey) {
8501 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!"
")", "./../../../docshell/base/nsDocShell.cpp", 8501); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aLoadState" ") (" "need a load state!" ")"
); do { MOZ_CrashSequence(__null, 8501); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8502 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"
")", "./../../../docshell/base/nsDocShell.cpp", 8503); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aLoadState->TriggeringPrincipal()" ") ("
"need a valid TriggeringPrincipal" ")"); do { MOZ_CrashSequence
(__null, 8503); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
8503 "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"
")", "./../../../docshell/base/nsDocShell.cpp", 8503); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aLoadState->TriggeringPrincipal()" ") ("
"need a valid TriggeringPrincipal" ")"); do { MOZ_CrashSequence
(__null, 8503); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
8504
8505 if (!aLoadState->TriggeringPrincipal()) {
8506 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"
")", "./../../../docshell/base/nsDocShell.cpp", 8506); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "false" ") (" "InternalLoad needs a valid triggeringPrincipal"
")"); do { MOZ_CrashSequence(__null, 8506); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8507 return NS_ERROR_FAILURE;
8508 }
8509 if (NS_WARN_IF(mBrowsingContext->GetPendingInitialization())NS_warn_if_impl(mBrowsingContext->GetPendingInitialization
(), "mBrowsingContext->GetPendingInitialization()", "./../../../docshell/base/nsDocShell.cpp"
, 8509)
) {
8510 return NS_ERROR_NOT_AVAILABLE;
8511 }
8512
8513 const bool shouldTakeFocus = NavigationShouldTakeFocus(this, aLoadState);
8514
8515 mOriginalUriString.Truncate();
8516
8517 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)
8518 ("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)
8519 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)
;
8520
8521 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
, "./../../../docshell/base/nsDocShell.cpp", 8521); return NS_ERROR_INVALID_ARG
; } } while (false)
;
8522
8523 // Cancel loads coming from Docshells that are being destroyed.
8524 if (mIsBeingDestroyed) {
8525 return NS_ERROR_NOT_AVAILABLE;
8526 }
8527
8528 nsresult rv = EnsureScriptEnvironment();
8529 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
8530 return rv;
8531 }
8532
8533 // If we have a target to move to, do that now.
8534 if (!aLoadState->Target().IsEmpty()) {
8535 return PerformRetargeting(aLoadState);
8536 }
8537
8538 // This is the non-retargeting load path, we've already set the right loadtype
8539 // for form submissions in nsDocShell::OnLinkClickSync.
8540 if (aLoadState->TargetBrowsingContext().IsNull()) {
8541 aLoadState->SetTargetBrowsingContext(GetBrowsingContext());
8542 }
8543
8544 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" ")", "./../../../docshell/base/nsDocShell.cpp"
, 8546); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "aLoadState->TargetBrowsingContext() == GetBrowsingContext()"
") (" "Load must be targeting this BrowsingContext" ")"); do
{ MOZ_CrashSequence(__null, 8546); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
8545 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" ")", "./../../../docshell/base/nsDocShell.cpp"
, 8546); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "aLoadState->TargetBrowsingContext() == GetBrowsingContext()"
") (" "Load must be targeting this BrowsingContext" ")"); do
{ MOZ_CrashSequence(__null, 8546); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
8546 "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" ")", "./../../../docshell/base/nsDocShell.cpp"
, 8546); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "aLoadState->TargetBrowsingContext() == GetBrowsingContext()"
") (" "Load must be targeting this BrowsingContext" ")"); do
{ MOZ_CrashSequence(__null, 8546); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
8547
8548 MOZ_TRY(CheckDisallowedJavascriptLoad(aLoadState))__extension__({ auto mozTryVarTempResult = ::mozilla::ToResult
(CheckDisallowedJavascriptLoad(aLoadState)); if ((__builtin_expect
(!!(mozTryVarTempResult.isErr()), 0))) { return mozTryVarTempResult
.propagateErr(); } mozTryVarTempResult.unwrap(); })
;
8549
8550 // If we don't have a target, we're loading into ourselves, and our load
8551 // delegate may want to intercept that load.
8552 SameDocumentNavigationState sameDocumentNavigationState;
8553 bool sameDocument =
8554 IsSameDocumentNavigation(aLoadState, sameDocumentNavigationState) &&
8555 !aLoadState->GetPendingRedirectedChannel();
8556
8557 if (mLoadType != LOAD_ERROR_PAGE &&
8558 !aLoadState->HasLoadFlags(LOAD_FLAGS_FROM_EXTERNAL)) {
8559 MaybeConvertToReplaceLoad(aLoadState, GetExtantDocument(),
8560 sameDocumentNavigationState.mIdentical,
8561 !!mActiveEntry);
8562 }
8563
8564 // Note: We do this check both here and in BrowsingContext::
8565 // LoadURI/InternalLoad, since document-specific sandbox flags are only
8566 // available in the process triggering the load, and we don't want the target
8567 // process to have to trust the triggering process to do the appropriate
8568 // checks for the BrowsingContext's sandbox flags.
8569 MOZ_TRY(mBrowsingContext->CheckSandboxFlags(aLoadState))__extension__({ auto mozTryVarTempResult = ::mozilla::ToResult
(mBrowsingContext->CheckSandboxFlags(aLoadState)); if ((__builtin_expect
(!!(mozTryVarTempResult.isErr()), 0))) { return mozTryVarTempResult
.propagateErr(); } mozTryVarTempResult.unwrap(); })
;
8570 MOZ_TRY(mBrowsingContext->CheckFramebusting(aLoadState))__extension__({ auto mozTryVarTempResult = ::mozilla::ToResult
(mBrowsingContext->CheckFramebusting(aLoadState)); if ((__builtin_expect
(!!(mozTryVarTempResult.isErr()), 0))) { return mozTryVarTempResult
.propagateErr(); } mozTryVarTempResult.unwrap(); })
;
8571
8572 NS_ENSURE_STATE(!HasUnloadedParent())do { if ((__builtin_expect(!!(!(!HasUnloadedParent())), 0))) {
NS_DebugBreak(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "!HasUnloadedParent()"
") failed", nullptr, "./../../../docshell/base/nsDocShell.cpp"
, 8572); return NS_ERROR_UNEXPECTED; } } while (false)
;
8573
8574 rv = CheckLoadingPermissions();
8575 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
8576 return rv;
8577 }
8578
8579 if (mFiredUnloadEvent) {
8580 if (IsOKToLoadURI(aLoadState->URI())) {
8581 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!"
")", "./../../../docshell/base/nsDocShell.cpp", 8582); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aLoadState->Target().IsEmpty()" ") (" "Shouldn't have a window target here!"
")"); do { MOZ_CrashSequence(__null, 8582); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
8582 "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!"
")", "./../../../docshell/base/nsDocShell.cpp", 8582); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aLoadState->Target().IsEmpty()" ") (" "Shouldn't have a window target here!"
")"); do { MOZ_CrashSequence(__null, 8582); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8583
8584 // If this is a replace load, make whatever load triggered
8585 // the unload event also a replace load, so we don't
8586 // create extra history entries.
8587 if (LOAD_TYPE_HAS_FLAGS(aLoadState->LoadType(),((aLoadState->LoadType()) & ((LOAD_FLAGS_REPLACE_HISTORY
) << 16))
8588 LOAD_FLAGS_REPLACE_HISTORY)((aLoadState->LoadType()) & ((LOAD_FLAGS_REPLACE_HISTORY
) << 16))
) {
8589 mLoadType = LOAD_NORMAL_REPLACE;
8590 }
8591
8592 // Do this asynchronously
8593 RefPtr ev = MakeRefPtr<InternalLoadEvent>(this, aLoadState);
8594 return Dispatch(ev.forget());
8595 }
8596
8597 // Just ignore this load attempt
8598 return NS_OK;
8599 }
8600
8601 // If we are loading a URI that should inherit a security context (basically
8602 // javascript: at this point), and the caller has said that principal
8603 // inheritance is allowed, there are a few possible cases:
8604 //
8605 // 1) We are provided with the principal to inherit. In that case, we just use
8606 // it.
8607 //
8608 // 2) The load is coming from some other application. In this case we don't
8609 // want to inherit from whatever document we have loaded now, since the
8610 // load is unrelated to it.
8611 //
8612 // 3) It's a load from our application, but does not provide an explicit
8613 // principal to inherit. In that case, we want to inherit the principal of
8614 // our current document, or of our parent document (if any) if we don't
8615 // have a current document.
8616 {
8617 bool inherits;
8618
8619 if (!aLoadState->HasLoadFlags(LOAD_FLAGS_FROM_EXTERNAL) &&
8620 !aLoadState->PrincipalToInherit() &&
8621 (aLoadState->HasInternalLoadFlags(
8622 INTERNAL_LOAD_FLAGS_INHERIT_PRINCIPAL)) &&
8623 NS_SUCCEEDED(nsContentUtils::URIInheritsSecurityContext(((bool)(__builtin_expect(!!(!NS_FAILED_impl(nsContentUtils::URIInheritsSecurityContext
( aLoadState->URI(), &inherits))), 1)))
8624 aLoadState->URI(), &inherits))((bool)(__builtin_expect(!!(!NS_FAILED_impl(nsContentUtils::URIInheritsSecurityContext
( aLoadState->URI(), &inherits))), 1)))
&&
8625 inherits) {
8626 aLoadState->SetPrincipalToInherit(GetInheritedPrincipal(true));
8627 }
8628 // If principalToInherit is still null (e.g. if some of the conditions of
8629 // were not satisfied), then no inheritance of any sort will happen: the
8630 // load will just get a principal based on the URI being loaded.
8631 }
8632
8633 // If this docshell is owned by a frameloader, make sure to cancel
8634 // possible frameloader initialization before loading a new page.
8635 nsCOMPtr<nsIDocShellTreeItem> parent = GetInProcessParentDocshell();
8636 if (parent) {
8637 RefPtr<Document> doc = parent->GetDocument();
8638 if (doc) {
8639 doc->TryCancelFrameLoaderInitialization(this);
8640 }
8641 }
8642
8643 // Before going any further vet loads initiated by external programs.
8644 if (aLoadState->HasLoadFlags(LOAD_FLAGS_FROM_EXTERNAL)) {
8645 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"
, "./../../../docshell/base/nsDocShell.cpp", 8645); AnnotateMozCrashReason
("MOZ_DIAGNOSTIC_ASSERT" "(" "aLoadState->LoadType() == LOAD_NORMAL"
")"); do { MOZ_CrashSequence(__null, 8645); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8646
8647 // Disallow external chrome: loads targetted at content windows
8648 if (aLoadState->URI()->SchemeIs("chrome")) {
8649 NS_WARNING("blocked external chrome: url -- use '--chrome' option")NS_DebugBreak(NS_DEBUG_WARNING, "blocked external chrome: url -- use '--chrome' option"
, nullptr, "./../../../docshell/base/nsDocShell.cpp", 8649)
;
8650 return NS_ERROR_FAILURE;
8651 }
8652
8653 // clear the decks to prevent context bleed-through (bug 298255)
8654 rv = CreateAboutBlankDocumentViewer(nullptr, nullptr, nullptr, nullptr,
8655 /* aIsInitialDocument */ false);
8656 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
8657 return NS_ERROR_FAILURE;
8658 }
8659
8660 if (Document* doc = GetDocument()) {
8661 doc->DisallowBFCaching();
8662 }
8663 }
8664
8665 mAllowKeywordFixup = aLoadState->HasInternalLoadFlags(
8666 INTERNAL_LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP);
8667 mURIResultedInDocument = false; // reset the clock...
8668
8669 // If container is an iframe element and will lazy load element steps given
8670 // container returns true, then stop intersection-observing a lazy loading
8671 // element container and set container's lazy load resumption steps to null.
8672 if (IsSubframe()) {
8673 if (auto* iframe = HTMLIFrameElement::FromNodeOrNull(
8674 mBrowsingContext->GetEmbedderElement())) {
8675 // Per spec, reload doesn't cancel lazy loading iframes.
8676 if (!(aLoadState->LoadType() & LOAD_RELOAD_NORMAL)) {
8677 iframe->StopLazyLoading(HTMLIFrameElement::TriggerLoad::No);
8678 }
8679 }
8680 }
8681
8682 // See if this is actually a load between two history entries for the same
8683 // document. If the process fails, or if we successfully navigate within the
8684 // same document, return.
8685 if (sameDocument) {
8686 nsresult rv = HandleSameDocumentNavigation(
8687 aLoadState, sameDocumentNavigationState, sameDocument);
8688 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, "./../../../docshell/base/nsDocShell.cpp"
, 8688); return rv; } } while (false)
;
8689 if (shouldTakeFocus) {
8690 mBrowsingContext->Focus(CallerType::System, IgnoreErrors());
8691 }
8692 if (sameDocument) {
8693 if (aLoadState->LoadIsFromSessionHistory() &&
8694 (mLoadType & LOAD_CMD_HISTORY) &&
8695 !aLoadState->IsResumingInterceptedNavigation()) {
8696 // We must ensure to not abort intercepted history navigations. See
8697 // https://github.com/whatwg/html/issues/12407
8698 SetOngoingNavigation(Nothing());
8699 }
8700 return rv;
8701 }
8702 }
8703
8704 // mDocumentViewer->PermitUnload can destroy |this| docShell, which
8705 // causes the next call of CanSavePresentation to crash.
8706 // Hold onto |this| until we return, to prevent a crash from happening.
8707 // (bug#331040)
8708 nsCOMPtr<nsIDocShell> kungFuDeathGrip(this);
8709
8710 // Don't init timing for javascript:, since it generally doesn't
8711 // actually start a load or anything. If it does, we'll init
8712 // timing then, from OnStateChange.
8713
8714 // XXXbz mTiming should know what channel it's for, so we don't
8715 // need this hackery.
8716 const bool isJavaScript = aLoadState->URI()->SchemeIs("javascript");
8717 const bool isExternalProtocol =
8718 nsContentUtils::IsExternalProtocol(aLoadState->URI());
8719 const bool isDownload = !aLoadState->FileName().IsVoid();
8720 const bool toBeReset = !isJavaScript && MaybeInitTiming();
8721
8722 // FIXME(emilio): Should this be done by javascript: uris? What about external
8723 // protocols?
8724 if (mTiming && !isDownload) {
8725 mTiming->NotifyBeforeUnload();
8726 }
8727
8728 // The following steps are from https://html.spec.whatwg.org/#navigate
8729 // 20. Set the ongoing navigation for navigable to navigationId.
8730 SetOngoingNavigation(Some(OngoingNavigation::NavigationID));
8731
8732 // 21. If url's scheme is "javascript":
8733 if (isJavaScript) {
8734 // 21.1 Queue a global task on the navigation and traversal task source
8735 // given navigable's active window to navigate to a javascript: URL
8736 // given navigable, url, historyHandling, sourceSnapshotParams,
8737 // initiatorOriginSnapshot, userInvolvement, cspNavigationType,
8738 // initialInsertion, and navigationId.
8739 // 21.2 Return.
8740 //
8741 // Note: We don't queue a task, so instead we run step 3 of
8742 // https://html.spec.whatwg.org/#navigate-to-a-javascript:-url
8743 // 3. Set the ongoing navigation for targetNavigable to null.
8744 SetOngoingNavigation(Nothing());
8745 }
8746
8747 // 22. If all of the following are true:
8748 // * userInvolvement is not "browser UI";
8749 // * navigable's active document's origin is same origin-domain with
8750 // sourceDocument's origin;
8751 // * navigable's active document's is initial about:blank is false; and
8752 // * url's scheme is a fetch scheme,
8753 // then:
8754 if (RefPtr<Document> document = GetDocument();
8755 !aLoadState->LoadIsFromSessionHistory() && document &&
8756 aLoadState->UserNavigationInvolvement() !=
8757 UserNavigationInvolvement::BrowserUI &&
8758 !document->IsInitialDocument() &&
8759 !NS_IsAboutBlankAllowQueryAndFragment(document->GetDocumentURI()) &&
8760 NS_IsFetchScheme(aLoadState->URI()) &&
8761 document->NodePrincipal()->EqualsConsideringDomain(
8762 aLoadState->TriggeringPrincipal())) {
8763 if (nsCOMPtr<nsPIDOMWindowInner> window = document->GetInnerWindow()) {
8764 // 22.1 Let navigation be navigable's active window's navigation API.
8765 if (RefPtr<Navigation> navigation = window->Navigation()) {
8766 AutoJSAPI jsapi;
8767 if (jsapi.Init(window)) {
8768 RefPtr<Element> sourceElement = aLoadState->GetSourceElement();
8769
8770 // 22.2 Let entryListForFiring be formDataEntryList if
8771 // documentResource is a POST resource; otherwise, null.
8772 RefPtr<FormData> formData = aLoadState->GetFormDataEntryList();
8773
8774 // 22.3 Let navigationAPIStateForFiring be navigationAPIState if
8775 // navigationAPIState is not null; otherwise,
8776 // StructuredSerializeForStorage(undefined).
8777 RefPtr<nsIStructuredCloneContainer> navigationAPIStateForFiring =
8778 aLoadState->GetNavigationAPIState();
8779
8780 nsCOMPtr<nsIURI> destinationURL = aLoadState->URI();
8781 // 22.4 Let continue be the result of firing a push/replace/reload
8782 // navigate event at navigation with navigationType set to
8783 // historyHandling, isSameDocument set to false, userInvolvement
8784 // set to userInvolvement, sourceElement set to sourceElement,
8785 // formDataEntryList set to entryListForFiring, destinationURL
8786 // set to url, navigationAPIState set to
8787 // navigationAPIStateForFiring, and apiMethodTracker set to
8788 // apiMethodTracker.
8789 RefPtr apiMethodTracker = aLoadState->GetNavigationAPIMethodTracker();
8790 bool shouldContinue = navigation->FirePushReplaceReloadNavigateEvent(
8791 jsapi.cx(), aLoadState->GetNavigationType(), destinationURL,
8792 /* aIsSameDocument */ false,
8793 Some(aLoadState->UserNavigationInvolvement()), sourceElement,
8794 formData, navigationAPIStateForFiring,
8795 /* aClassicHistoryAPIState */ nullptr, apiMethodTracker);
8796
8797 // 22.5 If continue is false, then return.
8798 if (!shouldContinue) {
8799 return NS_OK;
8800 }
8801 }
8802 }
8803 }
8804 }
8805
8806 // Check if the page doesn't want to be unloaded. The javascript:
8807 // protocol handler deals with this for javascript: URLs.
8808 // NOTE(emilio): As of this writing, other browsers fire beforeunload for
8809 // external protocols, so keep doing that even though they don't return data
8810 // and thus we won't really unload this...
8811 if (!isJavaScript && !isDownload &&
8812 !aLoadState->NotifiedBeforeUnloadListeners() && mDocumentViewer) {
8813 // Check if request is exempted from HTTPSOnlyMode and if https-first is
8814 // enabled, if so it means:
8815 // * https-first failed to upgrade request to https
8816 // * we already asked for permission to unload and the user accepted
8817 // otherwise we wouldn't be here.
8818 const bool isPrivateWin = GetOriginAttributes().IsPrivateBrowsing();
8819 const uint32_t loadType = aLoadState->LoadType();
8820
8821 // Check if request is a reload.
8822 const bool isHistoryOrReload =
8823 loadType == LOAD_RELOAD_NORMAL ||
8824 loadType == LOAD_RELOAD_BYPASS_CACHE ||
8825 loadType == LOAD_RELOAD_BYPASS_PROXY ||
8826 loadType == LOAD_RELOAD_BYPASS_PROXY_AND_CACHE ||
8827 loadType == LOAD_HISTORY;
8828
8829 // If it isn't a reload, the request already failed to be upgraded and
8830 // https-first is enabled then don't ask the user again for permission to
8831 // unload and just unload.
8832 bool okToUnload;
8833 if (!isHistoryOrReload && aLoadState->IsExemptFromHTTPSFirstMode() &&
8834 nsHTTPSOnlyUtils::GetUpgradeMode(isPrivateWin) ==
8835 nsHTTPSOnlyUtils::HTTPS_FIRST_MODE) {
8836 rv = mDocumentViewer->PermitUnload(
8837 nsIDocumentViewer::PermitUnloadAction::eDontPromptAndUnload,
8838 &okToUnload);
8839 } else {
8840 rv = mDocumentViewer->PermitUnload(&okToUnload);
8841 if (mIsBeingDestroyed) {
8842 // unload handler destroyed this docshell.
8843 return NS_ERROR_NOT_AVAILABLE;
8844 }
8845 }
8846
8847 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && !okToUnload) {
8848 // The user chose not to unload the page, interrupt the
8849 // load.
8850 MaybeResetInitTiming(toBeReset);
8851 return NS_OK;
8852 }
8853 }
8854
8855 if (mTiming && !isDownload) {
8856 mTiming->NotifyUnloadAccepted(mCurrentURI);
8857 }
8858
8859 // In e10s, in the parent process, we refuse to load anything other than
8860 // "safe" resources that we ship or trust enough to give "special" URLs.
8861 // Similar check will be performed by the ParentProcessDocumentChannel if in
8862 // use.
8863 if (XRE_IsE10sParentProcess() &&
8864 !DocumentChannel::CanUseDocumentChannel(aLoadState->URI()) &&
8865 !CanLoadInParentProcess(aLoadState->URI())) {
8866 return NS_ERROR_FAILURE;
8867 }
8868
8869 // Whenever a top-level browsing context is navigated, the user agent MUST
8870 // lock the orientation of the document to the document's default
8871 // orientation. We don't explicitly check for a top-level browsing context
8872 // here because orientation is only set on top-level browsing contexts.
8873 if (mBrowsingContext->GetOrientationLock() != hal::ScreenOrientation::None) {
8874 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()", "./../../../docshell/base/nsDocShell.cpp"
, 8874); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mBrowsingContext->IsTop()"
")"); do { MOZ_CrashSequence(__null, 8874); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8875 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))"
, "./../../../docshell/base/nsDocShell.cpp", 8876); AnnotateMozCrashReason
("MOZ_CRASH(" "NS_SUCCEEDED(mBrowsingContext->SetOrientationLock(hal::ScreenOrientation::None))"
")"); do { MOZ_CrashSequence(__null, 8876); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
8876 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))"
, "./../../../docshell/base/nsDocShell.cpp", 8876); AnnotateMozCrashReason
("MOZ_CRASH(" "NS_SUCCEEDED(mBrowsingContext->SetOrientationLock(hal::ScreenOrientation::None))"
")"); do { MOZ_CrashSequence(__null, 8876); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
;
8877 if (mBrowsingContext->IsActive()) {
8878 ScreenOrientation::UpdateActiveOrientationLock(
8879 hal::ScreenOrientation::None);
8880 }
8881 }
8882
8883 // Do a check so that we know if there are ongoing requests
8884 // before calling Stop() below.
8885 Document* document = GetDocument();
8886 uint32_t flags = 0;
8887 if (document && !document->CanSavePresentation(nullptr, flags, true)) {
8888 // This forces some flags into the WindowGlobalParent's mBFCacheStatus,
8889 // which we'll then use in CanonicalBrowsingContext::AllowedInBFCache,
8890 // and in particular we'll store BFCacheStatus::REQUEST if needed.
8891 // Also, we want to report all the flags to the parent process here (and
8892 // not just BFCacheStatus::NOT_ALLOWED), so that it can update the
8893 // telemetry data correctly.
8894 document->DisallowBFCaching(flags);
8895 }
8896
8897 if (aLoadState->LoadIsFromSessionHistory() &&
8898 (mLoadType & LOAD_CMD_HISTORY)) {
8899 SetOngoingNavigation(Nothing());
8900 }
8901
8902 // Don't stop current network activity for javascript: URL's since they might
8903 // not result in any data, and thus nothing should be stopped in those cases.
8904 // In the case where they do result in data, the javascript: URL channel takes
8905 // care of stopping current network activity. Similarly, downloads don't
8906 // unload this document...
8907 if (!isJavaScript && !isDownload && !isExternalProtocol) {
8908 // Stop any current network activity.
8909 // Also stop content if this is a zombie doc. otherwise
8910 // the onload will be delayed by other loads initiated in the
8911 // background by the first document that
8912 // didn't fully load before the next load was initiated.
8913 // If not a zombie, don't stop content until data
8914 // starts arriving from the new URI...
8915 if ((mDocumentViewer && mDocumentViewer->GetPreviousViewer()) ||
8916 LOAD_TYPE_HAS_FLAGS(aLoadState->LoadType(), LOAD_FLAGS_STOP_CONTENT)((aLoadState->LoadType()) & ((LOAD_FLAGS_STOP_CONTENT)
<< 16))
) {
8917 rv = StopInternal(nsIWebNavigation::STOP_ALL, UnsetOngoingNavigation::No);
8918 } else {
8919 rv = StopInternal(nsIWebNavigation::STOP_NETWORK,
8920 UnsetOngoingNavigation::No);
8921 }
8922
8923 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
8924 return rv;
8925 }
8926 }
8927
8928 mLoadType = aLoadState->LoadType();
8929
8930 if (aLoadState->LoadIsFromSessionHistory() &&
8931 (mLoadType & LOAD_CMD_HISTORY)) {
8932 if (RefPtr window = GetActiveWindow()) {
8933 if (RefPtr navigation = window->Navigation()) {
8934 if (const LoadingSessionHistoryInfo* loadingInfo =
8935 GetLoadingSessionHistoryInfo()) {
8936 navigation->CreateNavigationActivationFrom(
8937 loadingInfo->mPreviousEntry,
8938 NavigationUtils::NavigationTypeFromLoadType(mLoadType));
8939 }
8940 }
8941 }
8942
8943 // https://html.spec.whatwg.org/#history-traversal:
8944 // To traverse the history
8945 // "If entry has a different Document object than the current entry, then
8946 // run the following substeps: Remove any tasks queued by the history
8947 // traversal task source..."
8948 // Same document object case was handled already above with
8949 // HandleSameDocumentNavigation call.
8950 RefPtr<ChildSHistory> shistory = GetRootSessionHistory();
8951 if (shistory) {
8952 shistory->RemovePendingHistoryNavigations();
8953 }
8954 }
8955
8956 bool isTopLevelDoc = mBrowsingContext->IsTopContent();
8957
8958 OriginAttributes attrs = GetOriginAttributes();
8959 attrs.SetFirstPartyDomain(isTopLevelDoc, aLoadState->URI());
8960
8961 nsCOMPtr<nsIRequest> req;
8962 rv = DoURILoad(aLoadState, aCacheKey, getter_AddRefs(req));
8963
8964 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
8965 if (shouldTakeFocus) {
8966 mBrowsingContext->Focus(CallerType::System, IgnoreErrors());
8967 }
8968 }
8969
8970 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
8971 nsCOMPtr<nsIChannel> chan(do_QueryInterface(req));
8972 UnblockEmbedderLoadEventForFailure();
8973
8974 // The spec says no exception should be raised for pre-navigation check
8975 // failures.
8976 if (NS_ERROR_DOM_SECURITY_ERR == rv) {
8977 return NS_OK;
8978 }
8979
8980 nsCOMPtr<nsIURI> uri = aLoadState->URI();
8981 if (DisplayLoadError(rv, uri, nullptr, chan) &&
8982 // FIXME: At this point code was using internal load flags, but checking
8983 // non-internal load flags?
8984 aLoadState->HasLoadFlags(LOAD_FLAGS_ERROR_LOAD_CHANGES_RV)) {
8985 return NS_ERROR_LOAD_SHOWED_ERRORPAGE;
8986 }
8987
8988 // We won't report any error if this is an unknown protocol error. The
8989 // reason behind this is that it will allow enumeration of external
8990 // protocols if we report an error for each unknown protocol.
8991 if (NS_ERROR_UNKNOWN_PROTOCOL == rv) {
8992 return NS_OK;
8993 }
8994 }
8995
8996 return rv;
8997}
8998
8999/* static */
9000bool nsDocShell::CanLoadInParentProcess(nsIURI* aURI) {
9001 nsCOMPtr<nsIURI> uri = aURI;
9002 // In e10s, in the parent process, we refuse to load anything other than
9003 // "safe" resources that we ship or trust enough to give "special" URLs.
9004 bool canLoadInParent = false;
9005 if (NS_SUCCEEDED(NS_URIChainHasFlags(((bool)(__builtin_expect(!!(!NS_FAILED_impl(NS_URIChainHasFlags
( uri, nsIProtocolHandler::URI_IS_UI_RESOURCE, &canLoadInParent
))), 1)))
9006 uri, nsIProtocolHandler::URI_IS_UI_RESOURCE, &canLoadInParent))((bool)(__builtin_expect(!!(!NS_FAILED_impl(NS_URIChainHasFlags
( uri, nsIProtocolHandler::URI_IS_UI_RESOURCE, &canLoadInParent
))), 1)))
&&
9007 canLoadInParent) {
9008 // We allow UI resources.
9009 return true;
9010 }
9011 // For about: and extension-based URIs, which don't get
9012 // URI_IS_UI_RESOURCE, first remove layers of view-source:, if present.
9013 while (uri && uri->SchemeIs("view-source")) {
9014 nsCOMPtr<nsINestedURI> nested = do_QueryInterface(uri);
9015 if (nested) {
9016 nested->GetInnerURI(getter_AddRefs(uri));
9017 } else {
9018 break;
9019 }
9020 }
9021 // Allow about: URIs, execept about:srcdoc, which can include arbitrary code.
9022 // And allow moz-extension ones if we're running extension content in the
9023 // parent process.
9024 if (!uri || (uri->SchemeIs("about") && !NS_IsAboutSrcdoc(uri)) ||
9025 (!StaticPrefs::extensions_webextensions_remote() &&
9026 uri->SchemeIs("moz-extension"))) {
9027 return true;
9028 }
9029#ifdef MOZ_THUNDERBIRD
9030 if (uri->SchemeIs("imap") || uri->SchemeIs("mailbox") ||
9031 uri->SchemeIs("news") || uri->SchemeIs("nntp") ||
9032 uri->SchemeIs("snews") || uri->SchemeIs("x-moz-ews") ||
9033 uri->SchemeIs("x-moz-graph")) {
9034 return true;
9035 }
9036#endif
9037 nsAutoCString scheme;
9038 uri->GetScheme(scheme);
9039 // Allow ext+foo URIs (extension-registered custom protocols). See
9040 // https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/protocol_handlers
9041 if (StringBeginsWith(scheme, "ext+"_ns) &&
9042 !StaticPrefs::extensions_webextensions_remote()) {
9043 return true;
9044 }
9045 // Final exception for some legacy automated tests:
9046 if (xpc::IsInAutomation() &&
9047 StaticPrefs::security_allow_unsafe_parent_loads()) {
9048 return true;
9049 }
9050 return false;
9051}
9052
9053nsIPrincipal* nsDocShell::GetInheritedPrincipal(
9054 bool aConsiderCurrentDocument, bool aConsiderPartitionedPrincipal) {
9055 RefPtr<Document> document;
9056 bool inheritedFromCurrent = false;
9057
9058 if (aConsiderCurrentDocument && mDocumentViewer) {
9059 document = mDocumentViewer->GetDocument();
9060 inheritedFromCurrent = true;
9061 }
9062
9063 if (!document) {
9064 nsCOMPtr<nsIDocShellTreeItem> parentItem;
9065 GetInProcessSameTypeParent(getter_AddRefs(parentItem));
9066 if (parentItem) {
9067 document = parentItem->GetDocument();
9068 }
9069 }
9070
9071 if (!document) {
9072 if (!aConsiderCurrentDocument) {
9073 return nullptr;
9074 }
9075
9076 // Make sure we end up with _something_ as the principal no matter
9077 // what.If this fails, we'll just get a null docViewer and bail.
9078 if (!VerifyDocumentViewer()) {
9079 return nullptr;
9080 }
9081 document = mDocumentViewer->GetDocument();
9082 }
9083
9084 //-- Get the document's principal
9085 if (document) {
9086 nsIPrincipal* docPrincipal = aConsiderPartitionedPrincipal
9087 ? document->PartitionedPrincipal()
9088 : document->NodePrincipal();
9089
9090 // Don't allow loads in typeContent docShells to inherit the system
9091 // principal from existing documents.
9092 if (inheritedFromCurrent && mItemType == typeContent &&
9093 docPrincipal->IsSystemPrincipal()) {
9094 return nullptr;
9095 }
9096
9097 return docPrincipal;
9098 }
9099
9100 return nullptr;
9101}
9102
9103/* static */ nsresult nsDocShell::CreateRealChannelForDocument(
9104 nsIChannel** aChannel, nsIURI* aURI, nsILoadInfo* aLoadInfo,
9105 nsIInterfaceRequestor* aCallbacks, nsLoadFlags aLoadFlags,
9106 const nsAString& aSrcdoc, nsIURI* aBaseURI) {
9107 nsCOMPtr<nsIChannel> channel;
9108 if (aSrcdoc.IsVoid()) {
9109 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(); })
9110 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(); })
9111 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(); })
9112 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(); })
;
9113
9114 if (aBaseURI) {
9115 nsCOMPtr<nsIViewSourceChannel> vsc = do_QueryInterface(channel);
9116 if (vsc) {
9117 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))"
, "./../../../docshell/base/nsDocShell.cpp", 9117); AnnotateMozCrashReason
("MOZ_CRASH(" "NS_SUCCEEDED(vsc->SetBaseURI(aBaseURI))" ")"
); do { MOZ_CrashSequence(__null, 9117); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
;
9118 }
9119 }
9120 } else if (aURI->SchemeIs("view-source")) {
9121 // Instantiate view source handler protocol, if it doesn't exist already.
9122 nsCOMPtr<nsIIOService> io(do_GetIOService());
9123 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", "./../../../docshell/base/nsDocShell.cpp"
, 9123); AnnotateMozCrashReason("MOZ_ASSERT" "(" "io" ")"); do
{ MOZ_CrashSequence(__null, 9123); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
9124 nsCOMPtr<nsIProtocolHandler> handler;
9125 nsresult rv =
9126 io->GetProtocolHandler("view-source", getter_AddRefs(handler));
9127 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
9128 return rv;
9129 }
9130
9131 nsViewSourceHandler* vsh = nsViewSourceHandler::GetInstance();
9132 if (!vsh) {
9133 return NS_ERROR_FAILURE;
9134 }
9135
9136 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(); })
9137 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(); })
;
9138 } else {
9139 MOZ_RELEASE_ASSERT(NS_IsAboutSrcdoc(aURI))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(NS_IsAboutSrcdoc(aURI))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(NS_IsAboutSrcdoc(aURI)))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("NS_IsAboutSrcdoc(aURI)"
, "./../../../docshell/base/nsDocShell.cpp", 9139); AnnotateMozCrashReason
("MOZ_RELEASE_ASSERT" "(" "NS_IsAboutSrcdoc(aURI)" ")"); do {
MOZ_CrashSequence(__null, 9139); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
9140
9141 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(); })
9142 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(); })
9143 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(); })
;
9144 nsCOMPtr<nsIInputStreamChannel> isc = do_QueryInterface(channel);
9145 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", "./../../../docshell/base/nsDocShell.cpp"
, 9145); AnnotateMozCrashReason("MOZ_ASSERT" "(" "isc" ")"); do
{ MOZ_CrashSequence(__null, 9145); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
9146 isc->SetBaseURI(aBaseURI);
9147 }
9148
9149 if (aLoadFlags != nsIRequest::LOAD_NORMAL) {
9150 nsresult rv = channel->SetLoadFlags(aLoadFlags);
9151 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, "./../../../docshell/base/nsDocShell.cpp"
, 9151); return rv; } } while (false)
;
9152 }
9153
9154 channel.forget(aChannel);
9155 return NS_OK;
9156}
9157
9158/* static */ bool nsDocShell::CreateAndConfigureRealChannelForLoadState(
9159 BrowsingContext* aBrowsingContext, nsDocShellLoadState* aLoadState,
9160 LoadInfo* aLoadInfo, nsIInterfaceRequestor* aCallbacks,
9161 nsDocShell* aDocShell, const OriginAttributes& aOriginAttributes,
9162 nsLoadFlags aLoadFlags, uint32_t aCacheKey, nsresult& aRv,
9163 nsIChannel** aChannel) {
9164 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", "./../../../docshell/base/nsDocShell.cpp"
, 9164); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadInfo" ")"
); do { MOZ_CrashSequence(__null, 9164); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9165
9166 nsString srcdoc = VoidString();
9167 bool isSrcdoc =
9168 aLoadState->HasInternalLoadFlags(INTERNAL_LOAD_FLAGS_IS_SRCDOC);
9169 if (isSrcdoc) {
9170 srcdoc = aLoadState->SrcdocData();
9171 }
9172
9173 aLoadInfo->SetTriggeringRemoteType(
9174 aLoadState->GetEffectiveTriggeringRemoteType());
9175
9176 if (aLoadState->PrincipalToInherit()) {
9177 aLoadInfo->SetPrincipalToInherit(aLoadState->PrincipalToInherit());
9178 }
9179 aLoadInfo->SetLoadTriggeredFromExternal(
9180 aLoadState->HasLoadFlags(LOAD_FLAGS_FROM_EXTERNAL));
9181 aLoadInfo->SetForceAllowDataURI(aLoadState->HasInternalLoadFlags(
9182 INTERNAL_LOAD_FLAGS_FORCE_ALLOW_DATA_URI));
9183 aLoadInfo->SetOriginalFrameSrcLoad(
9184 aLoadState->HasInternalLoadFlags(INTERNAL_LOAD_FLAGS_ORIGINAL_FRAME_SRC));
9185 aLoadInfo->SetIsNewWindowTarget(
9186 aLoadState->HasInternalLoadFlags(INTERNAL_LOAD_FLAGS_FIRST_LOAD));
9187 aLoadInfo->SetForceMediaDocument(aLoadState->GetForceMediaDocument());
9188
9189 bool inheritAttrs = false;
9190 if (aLoadState->PrincipalToInherit()) {
9191 inheritAttrs = nsContentUtils::ChannelShouldInheritPrincipal(
9192 aLoadState->PrincipalToInherit(), aLoadState->URI(),
9193 true, // aInheritForAboutBlank
9194 isSrcdoc);
9195 }
9196
9197 // Strip the target query parameters before creating the channel.
9198 aLoadState->MaybeStripTrackerQueryStrings(aBrowsingContext);
9199
9200 OriginAttributes attrs;
9201
9202 // Inherit origin attributes from PrincipalToInherit if inheritAttrs is
9203 // true. Otherwise we just use the origin attributes from docshell.
9204 if (inheritAttrs) {
9205 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."
")", "./../../../docshell/base/nsDocShell.cpp", 9206); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aLoadState->PrincipalToInherit()" ") ("
"We should have PrincipalToInherit here." ")"); do { MOZ_CrashSequence
(__null, 9206); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
9206 "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."
")", "./../../../docshell/base/nsDocShell.cpp", 9206); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aLoadState->PrincipalToInherit()" ") ("
"We should have PrincipalToInherit here." ")"); do { MOZ_CrashSequence
(__null, 9206); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
9207 attrs = aLoadState->PrincipalToInherit()->OriginAttributesRef();
9208 // If firstPartyIsolation is not enabled, then PrincipalToInherit should
9209 // have the same origin attributes with docshell.
9210 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"
, "./../../../docshell/base/nsDocShell.cpp", 9211); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "attrs == aOriginAttributes" ")"); do { MOZ_CrashSequence
(__null, 9211); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false); } } while (false)
9211 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"
, "./../../../docshell/base/nsDocShell.cpp", 9211); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "attrs == aOriginAttributes" ")"); do { MOZ_CrashSequence
(__null, 9211); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false); } } while (false)
;
9212 } else {
9213 attrs = aOriginAttributes;
9214 attrs.SetFirstPartyDomain(IsTopLevelDoc(aBrowsingContext, aLoadInfo),
9215 aLoadState->URI());
9216 }
9217
9218 aRv = aLoadInfo->SetOriginAttributes(attrs);
9219 if (NS_WARN_IF(NS_FAILED(aRv))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(aRv
)), 0))), "NS_FAILED(aRv)", "./../../../docshell/base/nsDocShell.cpp"
, 9219)
) {
9220 return false;
9221 }
9222
9223 if (aLoadState->GetIsFromProcessingFrameAttributes()) {
9224 aLoadInfo->SetIsFromProcessingFrameAttributes();
9225 }
9226
9227 // Propagate the IsFormSubmission flag to the loadInfo.
9228 if (aLoadState->IsFormSubmission()) {
9229 aLoadInfo->SetIsFormSubmission(true);
9230 }
9231
9232 aLoadInfo->SetUnstrippedURI(aLoadState->GetUnstrippedURI());
9233
9234 nsCOMPtr<nsIChannel> channel;
9235 aRv = CreateRealChannelForDocument(getter_AddRefs(channel), aLoadState->URI(),
9236 aLoadInfo, aCallbacks, aLoadFlags, srcdoc,
9237 aLoadState->BaseURI());
9238 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, "./../../../docshell/base/nsDocShell.cpp"
, 9238); return false; } } while (false)
;
9239
9240 if (!channel) {
9241 return false;
9242 }
9243
9244 // If the HTTPS-Only mode is enabled, every insecure request gets upgraded to
9245 // HTTPS by default. This behavior can be disabled through the loadinfo flag
9246 // HTTPS_ONLY_EXEMPT.
9247 nsHTTPSOnlyUtils::TestSitePermissionAndPotentiallyAddExemption(channel);
9248
9249 // hack
9250 nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(channel));
9251 nsCOMPtr<nsIHttpChannelInternal> httpChannelInternal(
9252 do_QueryInterface(channel));
9253 nsCOMPtr<nsIURI> referrer;
9254 nsIReferrerInfo* referrerInfo = aLoadState->GetReferrerInfo();
9255 if (referrerInfo) {
9256 referrerInfo->GetOriginalReferrer(getter_AddRefs(referrer));
9257 }
9258 if (httpChannelInternal) {
9259 if (aLoadState->FirstParty()) {
9260 aRv = httpChannelInternal->SetDocumentURI(aLoadState->URI());
9261 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)))", "./../../../docshell/base/nsDocShell.cpp"
, 9261); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(aRv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 9261); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9262 } else {
9263 aRv = httpChannelInternal->SetDocumentURI(referrer);
9264 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)))", "./../../../docshell/base/nsDocShell.cpp"
, 9264); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(aRv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 9264); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9265 }
9266 aRv = httpChannelInternal->SetRedirectMode(
9267 nsIHttpChannelInternal::REDIRECT_MODE_MANUAL);
9268 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)))", "./../../../docshell/base/nsDocShell.cpp"
, 9268); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(aRv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 9268); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9269 }
9270
9271 if (httpChannel) {
9272 if (aLoadState->HeadersStream()) {
9273 aRv = AddHeadersToChannel(aLoadState->HeadersStream(), httpChannel);
9274 }
9275 // Set the referrer explicitly
9276 // Referrer is currenly only set for link clicks here.
9277 if (referrerInfo) {
9278 aRv = httpChannel->SetReferrerInfo(referrerInfo);
9279 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)))", "./../../../docshell/base/nsDocShell.cpp"
, 9279); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(aRv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 9279); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9280 }
9281
9282 // Mark the http channel as UrgentStart for top level document loading in
9283 // active tab.
9284 if (IsUrgentStart(aBrowsingContext, aLoadInfo, aLoadState->LoadType())) {
9285 nsCOMPtr<nsIClassOfService> cos(do_QueryInterface(channel));
9286 if (cos) {
9287 cos->AddClassFlags(nsIClassOfService::UrgentStart);
9288 if (StaticPrefs::dom_document_priority_incremental()) {
9289 cos->SetIncremental(true);
9290 }
9291 }
9292 }
9293 }
9294
9295 channel->SetOriginalURI(aLoadState->OriginalURI() ? aLoadState->OriginalURI()
9296 : aLoadState->URI());
9297
9298 const nsACString& typeHint = aLoadState->TypeHint();
9299 if (!typeHint.IsVoid()) {
9300 channel->SetContentType(typeHint);
9301 }
9302
9303 const nsAString& fileName = aLoadState->FileName();
9304 if (!fileName.IsVoid()) {
9305 aRv = channel->SetContentDisposition(nsIChannel::DISPOSITION_ATTACHMENT);
9306 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, "./../../../docshell/base/nsDocShell.cpp"
, 9306); return false; } } while (false)
;
9307 if (!fileName.IsEmpty()) {
9308 aRv = channel->SetContentDispositionFilename(fileName);
9309 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, "./../../../docshell/base/nsDocShell.cpp"
, 9309); return false; } } while (false)
;
9310 }
9311 }
9312
9313 if (nsCOMPtr<nsIWritablePropertyBag2> props = do_QueryInterface(channel)) {
9314 nsCOMPtr<nsIURI> referrer;
9315 nsIReferrerInfo* referrerInfo = aLoadState->GetReferrerInfo();
9316 if (referrerInfo) {
9317 referrerInfo->GetOriginalReferrer(getter_AddRefs(referrer));
9318 }
9319 // save true referrer for those who need it (e.g. xpinstall whitelisting)
9320 // Currently only http and ftp channels support this.
9321 props->SetPropertyAsInterface(u"docshell.internalReferrer"_ns, referrer);
9322 }
9323
9324 nsCOMPtr<nsICacheInfoChannel> cacheChannel(do_QueryInterface(channel));
9325 auto loadType = aLoadState->LoadType();
9326
9327 if (loadType == LOAD_RELOAD_NORMAL &&
9328 StaticPrefs::
9329 browser_soft_reload_only_force_validate_top_level_document()) {
9330 nsCOMPtr<nsICacheInfoChannel> cachingChannel = do_QueryInterface(channel);
9331 if (cachingChannel) {
9332 cachingChannel->SetForceValidateCacheContent(true);
9333 }
9334 }
9335
9336 // figure out if we need to set the post data stream on the channel...
9337 if (aLoadState->PostDataStream()) {
9338 if (nsCOMPtr<nsIFormPOSTActionChannel> postChannel =
9339 do_QueryInterface(channel)) {
9340 // XXX it's a bit of a hack to rewind the postdata stream here but
9341 // it has to be done in case the post data is being reused multiple
9342 // times.
9343 nsCOMPtr<nsISeekableStream> postDataSeekable =
9344 do_QueryInterface(aLoadState->PostDataStream());
9345 if (postDataSeekable) {
9346 aRv = postDataSeekable->Seek(nsISeekableStream::NS_SEEK_SET, 0);
9347 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, "./../../../docshell/base/nsDocShell.cpp"
, 9347); return false; } } while (false)
;
9348 }
9349
9350 // we really need to have a content type associated with this stream!!
9351 postChannel->SetUploadStream(aLoadState->PostDataStream(), ""_ns, -1);
9352
9353 // Ownership of the stream has transferred to the channel, clear our
9354 // reference.
9355 aLoadState->SetPostDataStream(nullptr);
9356 }
9357
9358 /* If there is a valid postdata *and* it is a History Load,
9359 * set up the cache key on the channel, to retrieve the
9360 * data *only* from the cache. If it is a normal reload, the
9361 * cache is free to go to the server for updated postdata.
9362 */
9363 if (cacheChannel && aCacheKey != 0) {
9364 if (loadType == LOAD_HISTORY || loadType == LOAD_RELOAD_CHARSET_CHANGE) {
9365 cacheChannel->SetCacheKey(aCacheKey);
9366 uint32_t loadFlags;
9367 if (NS_SUCCEEDED(channel->GetLoadFlags(&loadFlags))((bool)(__builtin_expect(!!(!NS_FAILED_impl(channel->GetLoadFlags
(&loadFlags))), 1)))
) {
9368 channel->SetLoadFlags(loadFlags |
9369 nsICachingChannel::LOAD_ONLY_FROM_CACHE);
9370 }
9371 } else if (loadType == LOAD_RELOAD_NORMAL) {
9372 cacheChannel->SetCacheKey(aCacheKey);
9373 }
9374 }
9375 } else {
9376 /* If there is no postdata, set the cache key on the channel, and
9377 * do not set the LOAD_ONLY_FROM_CACHE flag, so that the channel
9378 * will be free to get it from net if it is not found in cache.
9379 * New cache may use it creatively on CGI pages with GET
9380 * method and even on those that say "no-cache"
9381 */
9382 if (loadType == LOAD_HISTORY || loadType == LOAD_RELOAD_NORMAL ||
9383 loadType == LOAD_RELOAD_CHARSET_CHANGE ||
9384 loadType == LOAD_RELOAD_CHARSET_CHANGE_BYPASS_CACHE ||
9385 loadType == LOAD_RELOAD_CHARSET_CHANGE_BYPASS_PROXY_AND_CACHE) {
9386 if (cacheChannel && aCacheKey != 0) {
9387 cacheChannel->SetCacheKey(aCacheKey);
9388 }
9389 }
9390 }
9391
9392 if (nsCOMPtr<nsIScriptChannel> scriptChannel = do_QueryInterface(channel)) {
9393 // Allow execution against our context if the principals match
9394 scriptChannel->SetExecutionPolicy(nsIScriptChannel::EXECUTE_NORMAL);
9395 }
9396
9397 if (nsCOMPtr<nsITimedChannel> timedChannel = do_QueryInterface(channel)) {
9398 nsString initiatorType;
9399 switch (aLoadInfo->InternalContentPolicyType()) {
9400 case nsIContentPolicy::TYPE_INTERNAL_EMBED:
9401 initiatorType = u"embed"_ns;
9402 break;
9403 case nsIContentPolicy::TYPE_INTERNAL_OBJECT:
9404 initiatorType = u"object"_ns;
9405 break;
9406 default: {
9407 const auto& embedderElementType =
9408 aBrowsingContext->GetEmbedderElementType();
9409 if (embedderElementType) {
9410 initiatorType = *embedderElementType;
9411 }
9412 break;
9413 }
9414 }
9415
9416 if (!initiatorType.IsEmpty()) {
9417 timedChannel->SetInitiatorType(initiatorType);
9418 }
9419 }
9420
9421 nsCOMPtr<nsIURI> rpURI;
9422 aLoadInfo->GetResultPrincipalURI(getter_AddRefs(rpURI));
9423 Maybe<nsCOMPtr<nsIURI>> originalResultPrincipalURI;
9424 aLoadState->GetMaybeResultPrincipalURI(originalResultPrincipalURI);
9425 if (originalResultPrincipalURI &&
9426 (!aLoadState->KeepResultPrincipalURIIfSet() || !rpURI)) {
9427 // Unconditionally override, we want the replay to be equal to what has
9428 // been captured.
9429 aLoadInfo->SetResultPrincipalURI(originalResultPrincipalURI.ref());
9430 }
9431
9432 if (aLoadState->OriginalURI() && aLoadState->LoadReplace()) {
9433 // The LOAD_REPLACE flag and its handling here will be removed as part
9434 // of bug 1319110. For now preserve its restoration here to not break
9435 // any code expecting it being set specially on redirected channels.
9436 // If the flag has originally been set to change result of
9437 // NS_GetFinalChannelURI it won't have any effect and also won't cause
9438 // any harm.
9439 uint32_t loadFlags;
9440 aRv = channel->GetLoadFlags(&loadFlags);
9441 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, "./../../../docshell/base/nsDocShell.cpp"
, 9441); return false; } } while (false)
;
9442 channel->SetLoadFlags(loadFlags | nsIChannel::LOAD_REPLACE);
9443 }
9444
9445 nsCOMPtr<nsIPolicyContainer> policyContainer = aLoadState->PolicyContainer();
9446 if (nsCOMPtr<nsIContentSecurityPolicy> csp =
9447 PolicyContainer::GetCSP(policyContainer)) {
9448 // Navigational requests that are same origin need to be upgraded in case
9449 // upgrade-insecure-requests is present. Please note that for document
9450 // navigations that bit is re-computed in case we encounter a server
9451 // side redirect so the navigation is not same-origin anymore.
9452 bool upgradeInsecureRequests = false;
9453 csp->GetUpgradeInsecureRequests(&upgradeInsecureRequests);
9454 if (upgradeInsecureRequests) {
9455 // only upgrade if the navigation is same origin
9456 nsCOMPtr<nsIPrincipal> resultPrincipal;
9457 aRv = nsContentUtils::GetSecurityManager()->GetChannelResultPrincipal(
9458 channel, getter_AddRefs(resultPrincipal));
9459 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, "./../../../docshell/base/nsDocShell.cpp"
, 9459); return false; } } while (false)
;
9460 if (nsContentSecurityUtils::IsConsideredSameOriginForUIR(
9461 aLoadState->TriggeringPrincipal(), resultPrincipal)) {
9462 aLoadInfo->SetUpgradeInsecureRequests(true);
9463 }
9464 }
9465 }
9466
9467 if (policyContainer) {
9468 // For document loads we store the policyContainer that potentially needs to
9469 // be inherited by the new document, e.g. in case we are loading
9470 // an opaque origin like a data: URI. The actual inheritance
9471 // check happens within Document::InitPolicyContainer().
9472 // Please create an actual copy of the policyContainer (do not share the
9473 // same reference) otherwise modifications done (such as the meta CSP of the
9474 // new doc) in an opaque origin will incorrectly be propagated to the
9475 // embedding document.
9476 RefPtr policyContainerToInherit = MakeRefPtr<PolicyContainer>();
9477 policyContainerToInherit->InitFromOther(
9478 PolicyContainer::Cast(policyContainer));
9479 aLoadInfo->SetPolicyContainerToInherit(policyContainerToInherit);
9480 }
9481
9482 channel.forget(aChannel);
9483 return true;
9484}
9485
9486bool nsDocShell::ShouldDoInitialAboutBlankSyncLoad(
9487 nsIURI* aURI, nsDocShellLoadState* aLoadState,
9488 nsIPrincipal* aPrincipalToInherit) {
9489 MOZ_ASSERT(mDocumentViewer)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mDocumentViewer)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mDocumentViewer))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("mDocumentViewer"
, "./../../../docshell/base/nsDocShell.cpp", 9489); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "mDocumentViewer" ")"); do { MOZ_CrashSequence
(__null, 9489); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
9490
9491 if (!NS_IsAboutBlankAllowQueryAndFragment(aURI)) {
9492 return false;
9493 }
9494
9495 if (aLoadState->IsInitialAboutBlankHandlingProhibited()) {
9496 return false;
9497 }
9498
9499 Document* doc = mDocumentViewer->GetDocument();
9500
9501 if (mHasStartedLoadingOtherThanInitialBlankURI || !mDocumentViewer || !doc ||
9502 !doc->IsUncommittedInitialDocument()) {
9503 return false;
9504 }
9505
9506 if (!aPrincipalToInherit) {
9507 MOZ_ASSERT(do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mDocumentViewer->GetDocument()->NodePrincipal(
)->GetIsNullPrincipal())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mDocumentViewer->GetDocument
()->NodePrincipal()->GetIsNullPrincipal()))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("mDocumentViewer->GetDocument()->NodePrincipal()->GetIsNullPrincipal()"
" (" "Load looks like first load but does not want principal inheritance."
")", "./../../../docshell/base/nsDocShell.cpp", 9509); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "mDocumentViewer->GetDocument()->NodePrincipal()->GetIsNullPrincipal()"
") (" "Load looks like first load but does not want principal inheritance."
")"); do { MOZ_CrashSequence(__null, 9509); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
9508 mDocumentViewer->GetDocument()->NodePrincipal()->GetIsNullPrincipal(),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mDocumentViewer->GetDocument()->NodePrincipal(
)->GetIsNullPrincipal())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mDocumentViewer->GetDocument
()->NodePrincipal()->GetIsNullPrincipal()))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("mDocumentViewer->GetDocument()->NodePrincipal()->GetIsNullPrincipal()"
" (" "Load looks like first load but does not want principal inheritance."
")", "./../../../docshell/base/nsDocShell.cpp", 9509); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "mDocumentViewer->GetDocument()->NodePrincipal()->GetIsNullPrincipal()"
") (" "Load looks like first load but does not want principal inheritance."
")"); do { MOZ_CrashSequence(__null, 9509); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
9509 "Load looks like first load but does not want principal inheritance.")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mDocumentViewer->GetDocument()->NodePrincipal(
)->GetIsNullPrincipal())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mDocumentViewer->GetDocument
()->NodePrincipal()->GetIsNullPrincipal()))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("mDocumentViewer->GetDocument()->NodePrincipal()->GetIsNullPrincipal()"
" (" "Load looks like first load but does not want principal inheritance."
")", "./../../../docshell/base/nsDocShell.cpp", 9509); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "mDocumentViewer->GetDocument()->NodePrincipal()->GetIsNullPrincipal()"
") (" "Load looks like first load but does not want principal inheritance."
")"); do { MOZ_CrashSequence(__null, 9509); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9510 } else {
9511 if (XRE_IsContentProcess()) {
9512 RefPtr<LoadedOriginSet> loadedOrigins = CurrentLoadedOriginSet();
9513 if (!loadedOrigins->ValidatePrincipal(aPrincipalToInherit)) {
9514 // We can't directly load this principal, so we need the normal load
9515 // path to do a process switch.
9516 return false;
9517 }
9518 }
9519
9520 // If a page opens about:blank, it will have a content principal.
9521 // If it is then restored after a restart, we might not have initialized
9522 // UsesOAC for it. If this is the case, do a normal load (bug 2004165).
9523 // XXX bug 2005205 tracks removing this workaround.
9524 if (aLoadState->LoadIsFromSessionHistory() &&
9525 !mBrowsingContext->Group()
9526 ->UsesOriginAgentCluster(aPrincipalToInherit)
9527 .isSome()) {
9528 return false;
9529 }
9530
9531 // Initial about:blank from SH is kind of broken.
9532 // - The IPC round-trip in MaybeHandleSubframeHistory will make the load
9533 // async, but CompleteInitialAboutBlankLoad might at least not replace
9534 // the document. See bug 2007894.
9535 // - If an xorigin iframe navigates itself to about:blank and is then
9536 // restored during a parent document reload / traversal, we get here with
9537 // an xorigin about:blank. See bug 2021375.
9538 // So at least block xorigin initial about:blank.
9539 if (aLoadState->LoadIsFromSessionHistory() &&
9540 !aPrincipalToInherit->Equals(doc->GetPrincipal())) {
9541 return false;
9542 }
9543 }
9544
9545 return true;
9546}
9547
9548void nsDocShell::UnsuppressPaintingIfNoNavigationAwayFromAboutBlank(
9549 mozilla::PresShell* aPresShell) {
9550 if (mHasStartedLoadingOtherThanInitialBlankURI || !mDocumentViewer) {
9551 return;
9552 }
9553 Document* doc = mDocumentViewer->GetDocument();
9554 if (!doc || !doc->IsInitialDocument()) {
9555 return;
9556 }
9557 if (mDocumentViewer->GetPresShell() != aPresShell) {
9558 return;
9559 }
9560 // Our surroundings appear to remain in the same state
9561 // as before posting the runnable.
9562 aPresShell->UnsuppressPainting();
9563 // The content viewer's mPresShell could have been removed now, see bug
9564 // 378682/421432
9565 if ((aPresShell = mDocumentViewer->GetPresShell())) {
9566 aPresShell->LoadComplete();
9567 }
9568}
9569
9570nsresult nsDocShell::PerformTrustedTypesPreNavigationCheck(
9571 nsDocShellLoadState* aLoadState, nsGlobalWindowInner* aWindow) const {
9572 MOZ_ASSERT(aWindow)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aWindow)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aWindow))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aWindow", "./../../../docshell/base/nsDocShell.cpp"
, 9572); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aWindow" ")"
); do { MOZ_CrashSequence(__null, 9572); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9573 RefPtr<nsIContentSecurityPolicy> csp =
9574 PolicyContainer::GetCSP(aWindow->GetPolicyContainer());
9575 if (csp->GetRequireTrustedTypesForDirectiveState() ==
9576 RequireTrustedTypesForDirectiveState::NONE) {
9577 return NS_OK;
9578 }
9579
9580 // Exempt web extension content scripts from trusted types policies defined by
9581 // the page in which they are running.
9582 if (auto principal = BasePrincipal::Cast(aLoadState->TriggeringPrincipal())) {
9583 if (principal->ContentScriptAddonPolicyCore()) {
9584 return NS_OK;
9585 }
9586 }
9587
9588 // If disposion is enforce for require-trusted-types-for, then we return
9589 // errors in order to block navigation. If it's report-only, errors are
9590 // ignored and the URL is unchanged.
9591 bool shouldBlockOnError = csp->GetRequireTrustedTypesForDirectiveState() ==
9592 RequireTrustedTypesForDirectiveState::ENFORCE;
9593
9594 // 2. Let urlString be the result of running the URL serializer on
9595 // request’s url.
9596 nsAutoCString urlString;
9597 aLoadState->URI()->GetSpec(urlString);
9598
9599 // 3. Let encodedScriptSource be the result of removing the leading
9600 // "javascript:" from urlString.
9601 constexpr auto javascriptScheme = "javascript:"_ns;
9602 const nsDependentCSubstring encodedScriptSource =
9603 Substring(urlString, javascriptScheme.Length());
9604
9605 // 4. Let convertedScriptSource be the result of executing Process value
9606 // with a default policy algorithm
9607 Maybe<nsAutoString> compliantStringHolder;
9608 NS_ConvertUTF8toUTF16 encodedScriptSourceUTF16(encodedScriptSource);
9609 constexpr nsLiteralString sink = u"Location href"_ns;
9610 auto reportPreNavigationCheckViolations = [&csp, &sink,
9611 &encodedScriptSourceUTF16] {
9612 // Report violation the same way as for "Should sink type mismatch
9613 // violation be blocked by Content Security Policy", since that's what
9614 // other browsers do. See
9615 // https://github.com/w3c/trusted-types/issues/584.
9616 auto location = JSCallingLocation::Get();
9617 TrustedTypeUtils::ReportSinkTypeMismatchViolations(
9618 csp, nullptr /* aCSPEventListener */, location.FileName(),
9619 location.mLine, location.mColumn, sink, kTrustedTypesOnlySinkGroup,
9620 encodedScriptSourceUTF16);
9621 };
9622 ErrorResult error;
9623 auto convertedScriptSource =
9624 TrustedTypeUtils::GetConvertedScriptSourceForPreNavigationCheck(
9625 *aWindow, encodedScriptSourceUTF16, sink, compliantStringHolder,
9626 error);
9627 error.WouldReportJSException();
9628 if (error.Failed()) {
9629 reportPreNavigationCheckViolations();
9630 if (shouldBlockOnError) {
9631 RETURN_NSRESULT_ON_FAILURE(error)do { (error).WouldReportJSException(); if ((error).Failed()) {
NS_DebugBreak(NS_DEBUG_WARNING, nsPrintfCString( "RETURN_NSRESULT_ON_FAILURE(%s) failed with result 0x%X"
, "error", (error).ErrorCodeAsInt()) .get(), nullptr, "./../../../docshell/base/nsDocShell.cpp"
, 9631); return (error).StealNSResult(); } } while (0)
;
9632 }
9633 error.SuppressException();
9634 return NS_OK;
9635 }
9636
9637 // 5. Set urlString to be the result of prepending "javascript:" to
9638 // stringified convertedScriptSource.
9639 urlString = javascriptScheme + NS_ConvertUTF16toUTF8(*convertedScriptSource);
9640
9641 // 6. Let newURL be the result of running the URL parser on urlString.
9642 nsCOMPtr<nsIURI> newURL;
9643 nsresult rv = NS_NewURI(getter_AddRefs(newURL), urlString);
9644 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
9645 reportPreNavigationCheckViolations();
9646 return shouldBlockOnError ? rv : NS_OK;
9647 }
9648
9649 // 7. Set request’s url to newURL.
9650 aLoadState->SetURI(newURL);
9651 return NS_OK;
9652}
9653
9654nsresult nsDocShell::DoURILoad(nsDocShellLoadState* aLoadState,
9655 Maybe<uint32_t> aCacheKey,
9656 nsIRequest** aRequest) {
9657 // Double-check that we're still around to load this URI.
9658 if (mIsBeingDestroyed) {
9659 // Return NS_OK despite not doing anything to avoid throwing exceptions
9660 // from nsLocation::SetHref if the unload handler of the existing page
9661 // tears us down.
9662 return NS_OK;
9663 }
9664
9665 MOZ_DIAGNOSTIC_ASSERT(mInitialized, "Need to initialize before load")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mInitialized)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mInitialized))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("mInitialized" " ("
"Need to initialize before load" ")", "./../../../docshell/base/nsDocShell.cpp"
, 9665); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "mInitialized"
") (" "Need to initialize before load" ")"); do { MOZ_CrashSequence
(__null, 9665); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
9666 NS_ENSURE_TRUE(VerifyDocumentViewer(), NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(VerifyDocumentViewer())), 0))
) { NS_DebugBreak(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "VerifyDocumentViewer()"
") failed", nullptr, "./../../../docshell/base/nsDocShell.cpp"
, 9666); return NS_ERROR_FAILURE; } } while (false)
;
9667
9668 nsCOMPtr<nsIURILoader> uriLoader = components::URILoader::Service();
9669 if (NS_WARN_IF(!uriLoader)NS_warn_if_impl(!uriLoader, "!uriLoader", "./../../../docshell/base/nsDocShell.cpp"
, 9669)
) {
9670 return NS_ERROR_UNEXPECTED;
9671 }
9672
9673 // Persist and sync layout history state before we load a new uri, as this
9674 // might be our last chance to do so, in the content process.
9675 PersistLayoutHistoryState();
9676 SynchronizeLayoutHistoryState();
9677
9678 nsresult rv;
9679 nsContentPolicyType contentPolicyType = DetermineContentType();
9680
9681 auto getSourceWindowContext = [this, &aLoadState] {
9682 const MaybeDiscardedBrowsingContext& sourceBC =
9683 aLoadState->SourceBrowsingContext();
9684 if (!sourceBC.IsNullOrDiscarded()) {
9685 if (WindowContext* wc = sourceBC.get()->GetCurrentWindowContext()) {
9686 return wc;
9687 }
9688 }
9689 return mBrowsingContext->GetParentWindowContext();
9690 };
9691
9692 if (StaticPrefs::dom_security_trusted_types_enabled() &&
9693 aLoadState->URI()->SchemeIs("javascript")) {
9694 if (WindowContext* sourceWindowContext = getSourceWindowContext()) {
9695 RefPtr<nsGlobalWindowInner> window =
9696 sourceWindowContext->GetInnerWindow();
9697 rv = PerformTrustedTypesPreNavigationCheck(aLoadState, window);
9698 // Default policy might destroy the whole docshell, so check that again.
9699 if (mIsBeingDestroyed) {
9700 return NS_OK;
9701 }
9702 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
9703 return NS_ERROR_DOM_SECURITY_ERR;
9704 }
9705 }
9706 }
9707
9708 if (IsSubframe()) {
9709 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"
")", "./../../../docshell/base/nsDocShell.cpp", 9711); 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, 9711); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
9710 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"
")", "./../../../docshell/base/nsDocShell.cpp", 9711); 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, 9711); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
9711 "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"
")", "./../../../docshell/base/nsDocShell.cpp", 9711); 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, 9711); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9712 if (StaticPrefs::dom_block_external_protocol_in_iframes()) {
9713 // Only allow URLs able to return data in iframes.
9714 if (nsContentUtils::IsExternalProtocol(aLoadState->URI())) {
9715 // The context to check user-interaction with for the purposes of
9716 // popup-blocking.
9717 //
9718 // We generally want to check the context that initiated the navigation.
9719 WindowContext* sourceWindowContext = getSourceWindowContext();
9720 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"
, "./../../../docshell/base/nsDocShell.cpp", 9720); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "sourceWindowContext" ")"); do { MOZ_CrashSequence
(__null, 9720); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
9721
9722 // FIXME: We can't check user-interaction against an OOP window. This is
9723 // the next best thing we can really do. The load state keeps whether
9724 // the navigation had a user interaction in process
9725 // (aLoadState->HasValidUserGestureActivation()), but we can't really
9726 // consume it, which we want to prevent popup-spamming from the same
9727 // click event.
9728 WindowContext* context =
9729 sourceWindowContext->IsInProcess()
9730 ? sourceWindowContext
9731 : mBrowsingContext->GetCurrentWindowContext();
9732 const bool popupBlocked = [&] {
9733 const bool active = mBrowsingContext->IsActive();
9734
9735 // For same-origin-with-top windows, we grant a single free popup
9736 // without user activation, see bug 1680721.
9737 //
9738 // We consume the flag now even if there's no user activation.
9739 const bool hasFreePass = [&] {
9740 if (!active ||
9741 !(context->IsInProcess() && context->SameOriginWithTop())) {
9742 return false;
9743 }
9744 nsGlobalWindowInner* win =
9745 context->TopWindowContext()->GetInnerWindow();
9746 return win && win->TryOpenExternalProtocolIframe();
9747 }();
9748
9749 if (context->IsInProcess() &&
9750 context->ConsumeTransientUserGestureActivation()) {
9751 // If the user has interacted with the page, consume it.
9752 return false;
9753 }
9754
9755 // TODO(emilio): Can we remove this check? It seems like what prompted
9756 // this code (bug 1514547) should be covered by transient user
9757 // activation, see bug 1514547.
9758 if (active &&
9759 PopupBlocker::ConsumeTimerTokenForExternalProtocolIframe()) {
9760 return false;
9761 }
9762
9763 if (sourceWindowContext->CanShowPopup()) {
9764 return false;
9765 }
9766
9767 if (hasFreePass) {
9768 return false;
9769 }
9770
9771 return true;
9772 }();
9773
9774 // No error must be returned when iframes are blocked.
9775 if (popupBlocked) {
9776 nsAutoString message;
9777 nsresult rv = nsContentUtils::GetLocalizedString(
9778 PropertiesFile::DOM_PROPERTIES,
9779 "ExternalProtocolFrameBlockedNoUserActivation", message);
9780 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
9781 nsContentUtils::ReportToConsoleByWindowID(
9782 message, nsIScriptError::warningFlag, "DOM"_ns,
9783 context->InnerWindowId());
9784 }
9785 return NS_OK;
9786 }
9787 }
9788 }
9789
9790 // Only allow view-source scheme in top-level docshells. view-source is
9791 // the only scheme to which this applies at the moment due to potential
9792 // timing attacks to read data from cross-origin iframes. If this widens
9793 // we should add a protocol flag for whether the scheme is allowed in
9794 // frames and use something like nsNetUtil::NS_URIChainHasFlags.
9795 nsCOMPtr<nsIURI> tempURI = aLoadState->URI();
9796 nsCOMPtr<nsINestedURI> nestedURI = do_QueryInterface(tempURI);
9797 while (nestedURI) {
9798 // view-source should always be an nsINestedURI, loop and check the
9799 // scheme on this and all inner URIs that are also nested URIs.
9800 if (tempURI->SchemeIs("view-source")) {
9801 return NS_ERROR_UNKNOWN_PROTOCOL;
9802 }
9803 nestedURI->GetInnerURI(getter_AddRefs(tempURI));
9804 nestedURI = do_QueryInterface(tempURI);
9805 }
9806 } else {
9807 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"
")", "./../../../docshell/base/nsDocShell.cpp", 9808); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "contentPolicyType == nsIContentPolicy::TYPE_DOCUMENT"
") (" "DoURILoad thinks this is a document and InternalLoad does not"
")"); do { MOZ_CrashSequence(__null, 9808); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
9808 "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"
")", "./../../../docshell/base/nsDocShell.cpp", 9808); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "contentPolicyType == nsIContentPolicy::TYPE_DOCUMENT"
") (" "DoURILoad thinks this is a document and InternalLoad does not"
")"); do { MOZ_CrashSequence(__null, 9808); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9809 }
9810
9811 // We want to inherit aLoadState->PrincipalToInherit() when:
9812 // 1. ChannelShouldInheritPrincipal returns true.
9813 // 2. aLoadState->URI() is not data: URI, or data: URI is not
9814 // configured as unique opaque origin.
9815 bool inheritPrincipal = false;
9816
9817 nsCOMPtr<nsIURI> uri = aLoadState->URI();
9818 if (aLoadState->PrincipalToInherit()) {
9819 bool isSrcdoc =
9820 aLoadState->HasInternalLoadFlags(INTERNAL_LOAD_FLAGS_IS_SRCDOC);
9821 bool inheritAttrs = nsContentUtils::ChannelShouldInheritPrincipal(
9822 aLoadState->PrincipalToInherit(), uri,
9823 true, // aInheritForAboutBlank
9824 isSrcdoc);
9825
9826 inheritPrincipal = inheritAttrs && !uri->SchemeIs("data");
9827 }
9828
9829 MOZ_ASSERT_IF(NS_IsAboutBlankAllowQueryAndFragment(uri) &&do { if (NS_IsAboutBlankAllowQueryAndFragment(uri) &&
aLoadState->PrincipalToInherit()) { do { static_assert( mozilla
::detail::AssertionConditionType<decltype(inheritPrincipal
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(inheritPrincipal))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("inheritPrincipal", "./../../../docshell/base/nsDocShell.cpp"
, 9831); AnnotateMozCrashReason("MOZ_ASSERT" "(" "inheritPrincipal"
")"); do { MOZ_CrashSequence(__null, 9831); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
9830 aLoadState->PrincipalToInherit(),do { if (NS_IsAboutBlankAllowQueryAndFragment(uri) &&
aLoadState->PrincipalToInherit()) { do { static_assert( mozilla
::detail::AssertionConditionType<decltype(inheritPrincipal
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(inheritPrincipal))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("inheritPrincipal", "./../../../docshell/base/nsDocShell.cpp"
, 9831); AnnotateMozCrashReason("MOZ_ASSERT" "(" "inheritPrincipal"
")"); do { MOZ_CrashSequence(__null, 9831); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
9831 inheritPrincipal)do { if (NS_IsAboutBlankAllowQueryAndFragment(uri) &&
aLoadState->PrincipalToInherit()) { do { static_assert( mozilla
::detail::AssertionConditionType<decltype(inheritPrincipal
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(inheritPrincipal))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("inheritPrincipal", "./../../../docshell/base/nsDocShell.cpp"
, 9831); AnnotateMozCrashReason("MOZ_ASSERT" "(" "inheritPrincipal"
")"); do { MOZ_CrashSequence(__null, 9831); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
9832 // See https://bugzilla.mozilla.org/show_bug.cgi?id=1736570
9833 const bool doInitialSyncLoad = ShouldDoInitialAboutBlankSyncLoad(
9834 uri, aLoadState, aLoadState->PrincipalToInherit());
9835
9836 if (!doInitialSyncLoad && mBrowsingContext->IsContent()) {
9837 // https://wicg.github.io/document-picture-in-picture/#close-on-navigate
9838 // Two exceptions.
9839 // - The initial navigation is not per-spec and must complete.
9840 // - We also set IsDocumentPiP on chrome but the spec doesn't apply to it.
9841 if (Document* doc = GetExtantDocument()) {
9842 NS_DispatchToMainThread(NS_NewRunnableFunction(
9843 "Close PIP window on navigate",
9844 [doc = RefPtr(doc)]() MOZ_CAN_RUN_SCRIPT_BOUNDARY_LAMBDA {
9845 doc->CloseAnyAssociatedDocumentPiPWindows();
9846 }));
9847 }
9848 if (mBrowsingContext->GetIsDocumentPiP()) {
9849 return NS_OK;
9850 }
9851 }
9852
9853 // FIXME We still have a ton of codepaths that don't pass through
9854 // DocumentLoadListener, so probably need to create session history info
9855 // in more places.
9856 if (aLoadState->GetLoadingSessionHistoryInfo()) {
9857 SetLoadingSessionHistoryInfo(*aLoadState->GetLoadingSessionHistoryInfo());
9858 } else if (doInitialSyncLoad) {
9859 // Materialize LoadingSessionHistoryInfo here, because DocumentChannel
9860 // loads have it, and later history behavior depends on it existing.
9861 UniquePtr<SessionHistoryInfo> entry = MakeUnique<SessionHistoryInfo>(
9862 uri, aLoadState->TriggeringPrincipal(),
9863 aLoadState->PrincipalToInherit(),
9864 aLoadState->PartitionedPrincipalToInherit(),
9865 aLoadState->PolicyContainer(), mContentTypeHint);
9866 entry->SetTransient();
9867 mozilla::dom::LoadingSessionHistoryInfo info(*entry);
9868 if (Navigation::IsAPIEnabled()) {
9869 info.mContiguousEntries.AppendElement(*entry);
9870 }
9871 SetLoadingSessionHistoryInfo(info, true);
9872 }
9873
9874 // open a channel for the url
9875
9876 // If we have a pending channel, use the channel we've already created here.
9877 // We don't need to set up load flags for our channel, as it has already been
9878 // created.
9879
9880 if (nsCOMPtr<nsIChannel> channel =
9881 aLoadState->GetPendingRedirectedChannel()) {
9882 // If we have a request outparameter, shove our channel into it.
9883 if (aRequest) {
9884 nsCOMPtr<nsIRequest> outRequest = channel;
9885 outRequest.forget(aRequest);
9886 }
9887
9888 mHasStartedLoadingOtherThanInitialBlankURI = true;
9889 return OpenRedirectedChannel(aLoadState);
9890 }
9891
9892 // There are two cases we care about:
9893 // * Top-level load: In this case, loadingNode is null, but loadingWindow
9894 // is our mScriptGlobal. We pass null for loadingPrincipal in this case.
9895 // * Subframe load: loadingWindow is null, but loadingNode is the frame
9896 // element for the load. loadingPrincipal is the NodePrincipal of the
9897 // frame element.
9898 nsCOMPtr<nsINode> loadingNode;
9899 nsCOMPtr<nsPIDOMWindowOuter> loadingWindow;
9900 nsCOMPtr<nsIPrincipal> loadingPrincipal;
9901 nsCOMPtr<nsISupports> topLevelLoadingContext;
9902
9903 if (contentPolicyType == nsIContentPolicy::TYPE_DOCUMENT) {
9904 loadingNode = nullptr;
9905 loadingPrincipal = nullptr;
9906 loadingWindow = mScriptGlobal;
9907 if (XRE_IsContentProcess()) {
9908 // In e10s the child process doesn't have access to the element that
9909 // contains the browsing context (because that element is in the chrome
9910 // process).
9911 nsCOMPtr<nsIBrowserChild> browserChild = GetBrowserChild();
9912 topLevelLoadingContext = ToSupports(browserChild);
9913 } else {
9914 // This is for loading non-e10s tabs and toplevel windows of various
9915 // sorts.
9916 // For the toplevel window cases, requestingElement will be null.
9917 nsCOMPtr<Element> requestingElement =
9918 loadingWindow->GetFrameElementInternal();
9919 topLevelLoadingContext = requestingElement;
9920 }
9921 } else {
9922 loadingWindow = nullptr;
9923 loadingNode = mScriptGlobal->GetFrameElementInternal();
9924 if (loadingNode) {
9925 // If we have a loading node, then use that as our loadingPrincipal.
9926 loadingPrincipal = loadingNode->NodePrincipal();
9927#ifdef DEBUG1
9928 // Get the docshell type for requestingElement.
9929 RefPtr<Document> requestingDoc = loadingNode->OwnerDoc();
9930 nsCOMPtr<nsIDocShell> elementDocShell = requestingDoc->GetDocShell();
9931 // requestingElement docshell type = current docshell type.
9932 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"
")", "./../../../docshell/base/nsDocShell.cpp", 9934); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "mItemType == elementDocShell->ItemType()"
") (" "subframes should have the same docshell type as their parent"
")"); do { MOZ_CrashSequence(__null, 9934); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
9933 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"
")", "./../../../docshell/base/nsDocShell.cpp", 9934); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "mItemType == elementDocShell->ItemType()"
") (" "subframes should have the same docshell type as their parent"
")"); do { MOZ_CrashSequence(__null, 9934); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
9934 "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"
")", "./../../../docshell/base/nsDocShell.cpp", 9934); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "mItemType == elementDocShell->ItemType()"
") (" "subframes should have the same docshell type as their parent"
")"); do { MOZ_CrashSequence(__null, 9934); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9935#endif
9936 } else {
9937 if (mIsBeingDestroyed) {
9938 // If this isn't a top-level load and mScriptGlobal's frame element is
9939 // null, then the element got removed from the DOM while we were trying
9940 // to load this resource. This docshell is scheduled for destruction
9941 // already, so bail out here.
9942 return NS_OK;
9943 }
9944 // If we are not being destroyed and we do not have access to the loading
9945 // node, then we are a remote subframe. Set the loading principal
9946 // to be a null principal and then set it correctly in the parent.
9947 loadingPrincipal = NullPrincipal::Create(GetOriginAttributes(), nullptr);
9948 }
9949 }
9950
9951 if (!aLoadState->TriggeringPrincipal()) {
9952 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"
")", "./../../../docshell/base/nsDocShell.cpp", 9952); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "false" ") (" "DoURILoad needs a valid triggeringPrincipal"
")"); do { MOZ_CrashSequence(__null, 9952); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9953 return NS_ERROR_FAILURE;
9954 }
9955
9956 uint32_t sandboxFlags = mBrowsingContext->GetSandboxFlags();
9957 nsSecurityFlags securityFlags =
9958 nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_SEC_CONTEXT_IS_NULL;
9959
9960 if (mLoadType == LOAD_ERROR_PAGE) {
9961 securityFlags |= nsILoadInfo::SEC_LOAD_ERROR_PAGE;
9962 }
9963
9964 if (inheritPrincipal) {
9965 securityFlags |= nsILoadInfo::SEC_FORCE_INHERIT_PRINCIPAL;
9966 }
9967
9968 // Must never have a parent for TYPE_DOCUMENT loads
9969 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()"
, "./../../../docshell/base/nsDocShell.cpp", 9970); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!mBrowsingContext->GetParent()" ")"); do
{ MOZ_CrashSequence(__null, 9970); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false); } } while (false
)
9970 !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()"
, "./../../../docshell/base/nsDocShell.cpp", 9970); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!mBrowsingContext->GetParent()" ")"); do
{ MOZ_CrashSequence(__null, 9970); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false); } } while (false
)
;
9971 // Subdocuments must have a parent
9972 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()", "./../../../docshell/base/nsDocShell.cpp"
, 9973); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mBrowsingContext->GetParent()"
")"); do { MOZ_CrashSequence(__null, 9973); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
9973 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()", "./../../../docshell/base/nsDocShell.cpp"
, 9973); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mBrowsingContext->GetParent()"
")"); do { MOZ_CrashSequence(__null, 9973); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
9974 mBrowsingContext->SetTriggeringAndInheritPrincipals(
9975 aLoadState->TriggeringPrincipal(), aLoadState->PrincipalToInherit(),
9976 aLoadState->GetLoadIdentifier());
9977 RefPtr<LoadInfo> loadInfo;
9978 if (contentPolicyType == nsIContentPolicy::TYPE_DOCUMENT) {
9979 loadInfo = MakeRefPtr<LoadInfo>(
9980 loadingWindow, uri, aLoadState->TriggeringPrincipal(),
9981 topLevelLoadingContext, securityFlags, sandboxFlags);
9982 } else {
9983 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(); })
9984 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(); })
9985 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(); })
9986 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(); })
;
9987 }
9988 RefPtr<WindowContext> context = mBrowsingContext->GetCurrentWindowContext();
9989
9990 if (doInitialSyncLoad) {
9991 // Stay on the eagerly created document and adjust it to match what we would
9992 // be loading.
9993 return CompleteInitialAboutBlankLoad(aLoadState, loadInfo);
9994 }
9995 mHasStartedLoadingOtherThanInitialBlankURI = true;
9996
9997 if (mLoadType != LOAD_ERROR_PAGE && context && context->IsInProcess()) {
9998 if (context->HasValidTransientUserGestureActivation()) {
9999 aLoadState->SetHasValidUserGestureActivation(true);
10000 aLoadState->SetTextDirectiveUserActivation(true);
10001 }
10002 if (!aLoadState->TriggeringWindowId()) {
10003 aLoadState->SetTriggeringWindowId(context->Id());
10004 }
10005 if (!aLoadState->TriggeringStorageAccess()) {
10006 Document* contextDoc = context->GetExtantDoc();
10007 if (contextDoc) {
10008 aLoadState->SetTriggeringStorageAccess(
10009 contextDoc->UsingStorageAccess());
10010 }
10011 }
10012 }
10013
10014 // in case this docshell load was triggered by a valid transient user gesture,
10015 // or also the load originates from external, then we pass that information on
10016 // to the loadinfo, which allows e.g. setting Sec-Fetch-User request headers.
10017 if (aLoadState->HasValidUserGestureActivation() ||
10018 aLoadState->HasLoadFlags(LOAD_FLAGS_FROM_EXTERNAL)) {
10019 loadInfo->SetHasValidUserGestureActivation(true);
10020 aLoadState->SetTextDirectiveUserActivation(true);
10021 }
10022
10023 loadInfo->SetTextDirectiveUserActivation(
10024 aLoadState->GetTextDirectiveUserActivation());
10025
10026 loadInfo->SetTriggeringWindowId(aLoadState->TriggeringWindowId());
10027 loadInfo->SetTriggeringStorageAccess(aLoadState->TriggeringStorageAccess());
10028 loadInfo->SetTriggeringSandboxFlags(aLoadState->TriggeringSandboxFlags());
10029 net::ClassificationFlags flags = aLoadState->TriggeringClassificationFlags();
10030 loadInfo->SetTriggeringFirstPartyClassificationFlags(flags.firstPartyFlags);
10031 loadInfo->SetTriggeringThirdPartyClassificationFlags(flags.thirdPartyFlags);
10032 loadInfo->SetIsMetaRefresh(aLoadState->IsMetaRefresh());
10033
10034 uint32_t cacheKey = 0;
10035 if (aCacheKey) {
10036 cacheKey = *aCacheKey;
10037 } else {
10038 if (mLoadingEntry) {
10039 cacheKey = mLoadingEntry->mInfo.GetCacheKey();
10040 } else if (mActiveEntry) { // for reload cases
10041 cacheKey = mActiveEntry->GetCacheKey();
10042 }
10043 }
10044
10045 bool uriModified;
10046 if (mLoadingEntry) {
10047 uriModified = mLoadingEntry->mInfo.GetURIWasModified();
10048 } else {
10049 uriModified = false;
10050 }
10051
10052 bool isEmbeddingBlockedError = false;
10053 if (mFailedChannel) {
10054 nsresult status;
10055 mFailedChannel->GetStatus(&status);
10056 isEmbeddingBlockedError = status == NS_ERROR_XFO_VIOLATION ||
10057 status == NS_ERROR_CSP_FRAME_ANCESTOR_VIOLATION;
10058 }
10059
10060 nsLoadFlags loadFlags = aLoadState->CalculateChannelLoadFlags(
10061 mBrowsingContext, uriModified, Some(isEmbeddingBlockedError));
10062
10063 nsCOMPtr<nsIChannel> channel;
10064 if (DocumentChannel::CanUseDocumentChannel(uri)) {
10065 channel = DocumentChannel::CreateForDocument(
10066 aLoadState, loadInfo, loadFlags, this, cacheKey, uriModified,
10067 isEmbeddingBlockedError);
10068 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", "./../../../docshell/base/nsDocShell.cpp"
, 10068); AnnotateMozCrashReason("MOZ_ASSERT" "(" "channel" ")"
); do { MOZ_CrashSequence(__null, 10068); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
10069
10070 // Disable keyword fixup when using DocumentChannel, since
10071 // DocumentLoadListener will handle this for us (in the parent process).
10072 mAllowKeywordFixup = false;
10073 } else if (!CreateAndConfigureRealChannelForLoadState(
10074 mBrowsingContext, aLoadState, loadInfo, this, this,
10075 GetOriginAttributes(), loadFlags, cacheKey, rv,
10076 getter_AddRefs(channel))) {
10077 return rv;
10078 }
10079
10080 // Make sure to give the caller a channel if we managed to create one
10081 // This is important for correct error page/session history interaction
10082 if (aRequest) {
10083 NS_ADDREF(*aRequest = channel)(*aRequest = channel)->AddRef();
10084 }
10085
10086 const nsACString& typeHint = aLoadState->TypeHint();
10087 if (!typeHint.IsVoid()) {
10088 mContentTypeHint = typeHint;
10089 } else {
10090 mContentTypeHint.Truncate();
10091 }
10092
10093 // Load attributes depend on load type...
10094 if (mLoadType == LOAD_RELOAD_CHARSET_CHANGE) {
10095 // Use SetAllowStaleCacheContent (not LOAD_FROM_CACHE flag) since we
10096 // only want to force cache load for this channel, not the whole
10097 // loadGroup.
10098 nsCOMPtr<nsICacheInfoChannel> cachingChannel = do_QueryInterface(channel);
10099 if (cachingChannel) {
10100 cachingChannel->SetAllowStaleCacheContent(true);
10101 }
10102 }
10103
10104 uint32_t openFlags =
10105 nsDocShell::ComputeURILoaderFlags(mBrowsingContext, mLoadType);
10106 return OpenInitializedChannel(channel, uriLoader, openFlags);
10107}
10108
10109nsresult nsDocShell::CompleteInitialAboutBlankLoad(
10110 nsDocShellLoadState* aLoadState, nsILoadInfo* aLoadInfo) {
10111 nsresult rv;
10112 // Match the DocumentChannel case where the default for third-partiness
10113 // differs from the default in LoadInfo construction here.
10114 BrowsingContext* top = mBrowsingContext->Top();
10115 if (top == mBrowsingContext) {
10116 aLoadInfo->SetIsThirdPartyContextToTopWindow(false);
10117 } else {
10118 bool thirdParty = true;
10119 if (Document* topDoc = top->GetExtantDocument();
10120 topDoc && aLoadState->PrincipalToInherit()) {
10121 (void)topDoc->GetPrincipal()->IsThirdPartyPrincipal(
10122 aLoadState->PrincipalToInherit(), &thirdParty);
10123 }
10124 aLoadInfo->SetIsThirdPartyContextToTopWindow(thirdParty);
10125 }
10126
10127 if (!mDocumentViewer) {
10128 MOZ_ASSERT(false, "How did the viewer go away?")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "How did the viewer go away?"
")", "./../../../docshell/base/nsDocShell.cpp", 10128); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "false" ") (" "How did the viewer go away?"
")"); do { MOZ_CrashSequence(__null, 10128); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10129 return NS_ERROR_FAILURE;
10130 }
10131 RefPtr<Document> doc = mDocumentViewer->GetDocument();
10132 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]::DoURILoad sync about:blank onto initial "
"about:blank. Document[%p]\n", this, doc.get()); } } while (
0)
10133 ("nsDocShell[%p]::DoURILoad sync about:blank onto initial "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]::DoURILoad sync about:blank onto initial "
"about:blank. Document[%p]\n", this, doc.get()); } } while (
0)
10134 "about:blank. Document[%p]\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]::DoURILoad sync about:blank onto initial "
"about:blank. Document[%p]\n", this, doc.get()); } } while (
0)
10135 this, doc.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]::DoURILoad sync about:blank onto initial "
"about:blank. Document[%p]\n", this, doc.get()); } } while (
0)
;
10136 if (!doc) {
10137 MOZ_ASSERT(false, "How did the document go away?")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "How did the document go away?"
")", "./../../../docshell/base/nsDocShell.cpp", 10137); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "false" ") (" "How did the document go away?"
")"); do { MOZ_CrashSequence(__null, 10137); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10138 return NS_ERROR_FAILURE;
10139 }
10140
10141 // Get the load event fired for the initial about:blank without starting
10142 // a real load from a channel. We still need a channel object even though
10143 // we don't care about reading from the channel.
10144 nsCOMPtr<nsIChannel> aboutBlankChannel;
10145 rv = NS_NewChannelInternal(getter_AddRefs(aboutBlankChannel),
10146 aLoadState->URI(), aLoadInfo, nullptr, mLoadGroup,
10147 nullptr, nsIChannel::LOAD_DOCUMENT_URI);
10148 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
10149 return rv;
10150 }
10151 if (!aboutBlankChannel) {
10152 return NS_ERROR_FAILURE;
10153 }
10154
10155 nsCOMPtr<nsIPrincipal> expectedPrincipal = aLoadState->PrincipalToInherit();
10156 nsCOMPtr<nsIPrincipal> expectedPartitionedPrincipal = expectedPrincipal;
10157 // If we don't have a content principal, also use it as partitioned principal
10158 if (expectedPrincipal && expectedPrincipal->GetIsContentPrincipal()) {
10159 // The partitioned content principal is always isolated.
10160 StoragePrincipalHelper::Create(
10161 aboutBlankChannel, expectedPrincipal, /* aForceIsolation */ true,
10162 getter_AddRefs(expectedPartitionedPrincipal));
10163 }
10164
10165 const bool principalMismatch =
10166 expectedPrincipal && !expectedPrincipal->Equals(doc->GetPrincipal());
10167 MOZ_ASSERT_IF(!expectedPrincipal, doc->GetPrincipal()->GetIsNullPrincipal())do { if (!expectedPrincipal) { do { static_assert( mozilla::detail
::AssertionConditionType<decltype(doc->GetPrincipal()->
GetIsNullPrincipal())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(doc->GetPrincipal()->GetIsNullPrincipal
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("doc->GetPrincipal()->GetIsNullPrincipal()", "./../../../docshell/base/nsDocShell.cpp"
, 10167); AnnotateMozCrashReason("MOZ_ASSERT" "(" "doc->GetPrincipal()->GetIsNullPrincipal()"
")"); do { MOZ_CrashSequence(__null, 10167); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false); } } while
(false)
;
10168
10169 // The channel would sandbox aLoadState->PrincipalToInherit(). Even if
10170 // the document already has a null principal, we don't know if it's the right
10171 // sandboxed one. So be safe and clobber.
10172 const uint32_t sandboxFlags =
10173 mBrowsingContext->GetHasLoadedNonInitialDocument()
10174 ? mBrowsingContext->GetSandboxFlags()
10175 : mBrowsingContext->GetInitialSandboxFlags();
10176 const bool shouldBeSandboxed = sandboxFlags & SANDBOXED_ORIGIN;
10177 MOZ_ASSERT_IF(shouldBeSandboxed, expectedPrincipal)do { if (shouldBeSandboxed) { do { static_assert( mozilla::detail
::AssertionConditionType<decltype(expectedPrincipal)>::
isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(expectedPrincipal))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("expectedPrincipal", "./../../../docshell/base/nsDocShell.cpp"
, 10177); AnnotateMozCrashReason("MOZ_ASSERT" "(" "expectedPrincipal"
")"); do { MOZ_CrashSequence(__null, 10177); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false); } } while
(false)
;
10178
10179 // Clobber document before completing the synchronous load if it doesn't have
10180 // the right principal (bug 1979032)
10181 if (principalMismatch || shouldBeSandboxed) {
10182 // This will sandbox the principals as needed
10183 nsCOMPtr<nsIPolicyContainer> policyContainer =
10184 aLoadState->PolicyContainer();
10185 nsCOMPtr<nsIURI> base = doc->GetDocBaseURI();
10186 rv = CreateAboutBlankDocumentViewer(
10187 expectedPrincipal, expectedPartitionedPrincipal, policyContainer, base,
10188 /* aIsInitialDocument */ true);
10189 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, "./../../../docshell/base/nsDocShell.cpp"
, 10189); return rv; } } while (false)
;
10190
10191 doc = mDocumentViewer->GetDocument();
10192 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", "./../../../docshell/base/nsDocShell.cpp"
, 10192); AnnotateMozCrashReason("MOZ_ASSERT" "(" "doc" ")");
do { MOZ_CrashSequence(__null, 10192); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
10193 MOZ_LOG(gDocShellLog, LogLevel::Warning,do { const ::mozilla::LogModule* moz_real_module = gDocShellLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Warning)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Warning, "nsDocShell[%p] sync about:blank principals don't match, create "
"new document. Document[%p] \n", this, doc.get()); } } while
(0)
10194 ("nsDocShell[%p] sync about:blank principals don't match, create "do { const ::mozilla::LogModule* moz_real_module = gDocShellLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Warning)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Warning, "nsDocShell[%p] sync about:blank principals don't match, create "
"new document. Document[%p] \n", this, doc.get()); } } while
(0)
10195 "new document. Document[%p] \n",do { const ::mozilla::LogModule* moz_real_module = gDocShellLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Warning)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Warning, "nsDocShell[%p] sync about:blank principals don't match, create "
"new document. Document[%p] \n", this, doc.get()); } } while
(0)
10196 this, doc.get()))do { const ::mozilla::LogModule* moz_real_module = gDocShellLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Warning)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Warning, "nsDocShell[%p] sync about:blank principals don't match, create "
"new document. Document[%p] \n", this, doc.get()); } } while
(0)
;
10197 }
10198
10199 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()"
" (" "How come the doc is no longer the initial one?" ")", "./../../../docshell/base/nsDocShell.cpp"
, 10200); AnnotateMozCrashReason("MOZ_ASSERT" "(" "doc->IsInitialDocument()"
") (" "How come the doc is no longer the initial one?" ")");
do { MOZ_CrashSequence(__null, 10200); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
10200 "How come the doc is no longer the initial one?")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()"
" (" "How come the doc is no longer the initial one?" ")", "./../../../docshell/base/nsDocShell.cpp"
, 10200); AnnotateMozCrashReason("MOZ_ASSERT" "(" "doc->IsInitialDocument()"
") (" "How come the doc is no longer the initial one?" ")");
do { MOZ_CrashSequence(__null, 10200); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
10201
10202 MOZ_ASSERT(doc->GetReadyStateEnum() == Document::READYSTATE_COMPLETE)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(doc->GetReadyStateEnum() == Document::READYSTATE_COMPLETE
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(doc->GetReadyStateEnum() == Document::READYSTATE_COMPLETE
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"doc->GetReadyStateEnum() == Document::READYSTATE_COMPLETE"
, "./../../../docshell/base/nsDocShell.cpp", 10202); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "doc->GetReadyStateEnum() == Document::READYSTATE_COMPLETE"
")"); do { MOZ_CrashSequence(__null, 10202); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10203 MOZ_ASSERT(!mIsLoadingDocument)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mIsLoadingDocument)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mIsLoadingDocument))), 0)))
{ do { } while (false); MOZ_ReportAssertionFailure("!mIsLoadingDocument"
, "./../../../docshell/base/nsDocShell.cpp", 10203); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!mIsLoadingDocument" ")"); do { MOZ_CrashSequence
(__null, 10203); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
10204
10205 if (nsIContentSecurityPolicy* csp =
10206 PolicyContainer::GetCSP(doc->GetPolicyContainer())) {
10207 // We do this here rather than when inheriting the CSP in
10208 // CreateAboutBlankDocumentViewer so that client source and parsed policies
10209 // use the parent's URI as self (bug 2021482, 2035423).
10210 MOZ_TRY(csp->SetRequestContextWithDocument(doc))__extension__({ auto mozTryVarTempResult = ::mozilla::ToResult
(csp->SetRequestContextWithDocument(doc)); if ((__builtin_expect
(!!(mozTryVarTempResult.isErr()), 0))) { return mozTryVarTempResult
.propagateErr(); } mozTryVarTempResult.unwrap(); })
;
10211 }
10212 doc->ApplyCspFromLoadInfo(aLoadInfo);
10213 doc->ApplySettingsFromCSP(false);
10214 doc->RecomputeResistFingerprinting();
10215
10216 rv = doc->GetWindowContext()->SetIsOriginalFrameSource(
10217 aLoadState->HasInternalLoadFlags(INTERNAL_LOAD_FLAGS_ORIGINAL_FRAME_SRC));
10218 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, "./../../../docshell/base/nsDocShell.cpp"
, 10218); return rv; } } while (false)
;
10219
10220 nsPIDOMWindowInner* innerWindow = doc->GetInnerWindow();
10221 if (innerWindow) {
10222 mozilla::dom::ClientSource* clientSource =
10223 nsGlobalWindowInner::Cast(innerWindow)->GetClientSource();
10224 // See if we don't have a controller but the parent has gained a
10225 // controller.
10226 if (clientSource && clientSource->GetController().isNothing()) {
10227 MaybeInheritController(
10228 clientSource,
10229 StoragePrincipalHelper::ShouldUsePartitionPrincipalForServiceWorker(
10230 this)
10231 ? doc->PartitionedPrincipal()
10232 : doc->GetPrincipal());
10233 }
10234 }
10235
10236 MOZ_ASSERT(!mIsLoadingDocument)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mIsLoadingDocument)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mIsLoadingDocument))), 0)))
{ do { } while (false); MOZ_ReportAssertionFailure("!mIsLoadingDocument"
, "./../../../docshell/base/nsDocShell.cpp", 10236); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!mIsLoadingDocument" ")"); do { MOZ_CrashSequence
(__null, 10236); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
10237 MOZ_ASSERT(!mDocumentRequest)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mDocumentRequest)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mDocumentRequest))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("!mDocumentRequest"
, "./../../../docshell/base/nsDocShell.cpp", 10237); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!mDocumentRequest" ")"); do { MOZ_CrashSequence
(__null, 10237); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
10238
10239 // Call OnStartRequest so that nsDocLoader sets mIsLoadingDocument and fire
10240 // state start
10241 OnStartRequest(aboutBlankChannel);
10242
10243 MOZ_ASSERT(mIsLoadingDocument)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mIsLoadingDocument)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mIsLoadingDocument))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("mIsLoadingDocument"
, "./../../../docshell/base/nsDocShell.cpp", 10243); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "mIsLoadingDocument" ")"); do { MOZ_CrashSequence
(__null, 10243); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
10244 MOZ_ASSERT(mDocumentRequest == aboutBlankChannel)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mDocumentRequest == aboutBlankChannel)>::isValid,
"invalid assertion condition"); if ((__builtin_expect(!!(!(!
!(mDocumentRequest == aboutBlankChannel))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("mDocumentRequest == aboutBlankChannel"
, "./../../../docshell/base/nsDocShell.cpp", 10244); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "mDocumentRequest == aboutBlankChannel" ")"
); do { MOZ_CrashSequence(__null, 10244); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
10245 MOZ_ASSERT(!doc->InitialAboutBlankLoadCompleting())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!doc->InitialAboutBlankLoadCompleting())>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(!doc->InitialAboutBlankLoadCompleting()))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("!doc->InitialAboutBlankLoadCompleting()"
, "./../../../docshell/base/nsDocShell.cpp", 10245); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!doc->InitialAboutBlankLoadCompleting()"
")"); do { MOZ_CrashSequence(__null, 10245); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10246
10247 doc->BeginInitialAboutBlankLoadCompleting(aboutBlankChannel);
10248 auto resetLoadCompleting =
10249 MakeScopeExit([&] { doc->EndInitialAboutBlankLoadCompleting(); });
10250
10251 mCurrentURI = aLoadState->URI();
10252 doc->SetDocumentURI(aLoadState->URI());
10253
10254 // Normal documents fire the location change at content viewer creation.
10255 // The initial about:blank does not do that at content viewer creation,
10256 // so that the UI isn't bothered about the initial about:blank if there's
10257 // immediate navigation away. However, now that the initial about:blank is
10258 // going to remain in this docshell, we need to let to the UI know about it
10259 // (at least in the top-level case).
10260 FireOnLocationChange(this, aboutBlankChannel, aLoadState->URI(), 0);
10261
10262 MoveLoadingToActiveEntry(false, 0, nullptr);
10263
10264 doc->BeginLoad();
10265
10266 nsContentUtils::AddScriptRunner(
10267 MakeAndAddRef<nsDocElementCreatedNotificationRunner>(doc));
10268 // When scripts are not blocked (are they ever blocked here?), the runnable
10269 // runs immediately, so let's check if this docshell got destroyed or the
10270 // document got swapped. Unclear if this ever happens; this is a defensive
10271 // check.
10272 if (mIsBeingDestroyed || !mDocumentViewer ||
10273 doc != mDocumentViewer->GetDocument()) {
10274 return NS_OK;
10275 }
10276
10277 // Initialize the presShell here in the window.open() case.
10278 RefPtr<PresShell> presShell = doc->GetPresShell();
10279 if (presShell && !presShell->DidInitialize()) {
10280 rv = presShell->Initialize();
10281 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, "./../../../docshell/base/nsDocShell.cpp"
, 10281); return rv; } } while (false)
;
10282 }
10283
10284 doc->SetScrollToRef(doc->GetDocumentURI());
10285
10286 OnStopRequest(aboutBlankChannel, NS_OK);
10287
10288 // Mechanisms in Document will force a load from EndLoad()
10289 // even if there are still blockers.
10290 doc->EndLoad();
10291 // Can't assert any postcondition, because the load event
10292 // handler may have started loading something new in this
10293 // docshell.
10294
10295 return NS_OK;
10296}
10297
10298static nsresult AppendSegmentToString(nsIInputStream* aIn, void* aClosure,
10299 const char* aFromRawSegment,
10300 uint32_t aToOffset, uint32_t aCount,
10301 uint32_t* aWriteCount) {
10302 // aFromSegment now contains aCount bytes of data.
10303
10304 nsAutoCString* buf = static_cast<nsAutoCString*>(aClosure);
10305 buf->Append(aFromRawSegment, aCount);
10306
10307 // Indicate that we have consumed all of aFromSegment
10308 *aWriteCount = aCount;
10309 return NS_OK;
10310}
10311
10312/* static */ nsresult nsDocShell::AddHeadersToChannel(
10313 nsIInputStream* aHeadersData, nsIChannel* aGenericChannel) {
10314 nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(aGenericChannel);
10315 NS_ENSURE_STATE(httpChannel)do { if ((__builtin_expect(!!(!(httpChannel)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "httpChannel" ") failed"
, nullptr, "./../../../docshell/base/nsDocShell.cpp", 10315);
return NS_ERROR_UNEXPECTED; } } while (false)
;
10316
10317 uint32_t numRead;
10318 nsAutoCString headersString;
10319 nsresult rv = aHeadersData->ReadSegments(
10320 AppendSegmentToString, &headersString, UINT32_MAX(4294967295U), &numRead);
10321 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, "./../../../docshell/base/nsDocShell.cpp"
, 10321); return rv; } } while (false)
;
10322
10323 // used during the manipulation of the String from the InputStream
10324 nsAutoCString headerName;
10325 nsAutoCString headerValue;
10326 int32_t crlf;
10327 int32_t colon;
10328
10329 //
10330 // Iterate over the headersString: for each "\r\n" delimited chunk,
10331 // add the value as a header to the nsIHttpChannel
10332 //
10333
10334 static const char kWhitespace[] = "\b\t\r\n ";
10335 while (true) {
10336 crlf = headersString.Find("\r\n");
10337 if (crlf == kNotFound) {
10338 return NS_OK;
10339 }
10340
10341 const nsACString& oneHeader = StringHead(headersString, crlf);
10342
10343 colon = oneHeader.FindChar(':');
10344 if (colon == kNotFound) {
10345 return NS_ERROR_UNEXPECTED;
10346 }
10347
10348 headerName = StringHead(oneHeader, colon);
10349 headerValue = Substring(oneHeader, colon + 1);
10350
10351 headerName.Trim(kWhitespace);
10352 headerValue.Trim(kWhitespace);
10353
10354 headersString.Cut(0, crlf + 2);
10355
10356 //
10357 // FINALLY: we can set the header!
10358 //
10359
10360 rv = httpChannel->SetRequestHeader(headerName, headerValue, true);
10361 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, "./../../../docshell/base/nsDocShell.cpp"
, 10361); return rv; } } while (false)
;
10362 }
10363
10364 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" ")", "./../../../docshell/base/nsDocShell.cpp", 10364
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") (" "MOZ_ASSERT_UNREACHABLE: "
"oops" ")"); do { MOZ_CrashSequence(__null, 10364); __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
;
10365 return NS_ERROR_UNEXPECTED;
10366}
10367
10368/* static */ uint32_t nsDocShell::ComputeURILoaderFlags(
10369 BrowsingContext* aBrowsingContext, uint32_t aLoadType,
10370 bool aIsDocumentLoad) {
10371 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"
, "./../../../docshell/base/nsDocShell.cpp", 10371); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aBrowsingContext" ")"); do { MOZ_CrashSequence
(__null, 10371); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
10372
10373 uint32_t openFlags = 0;
10374 if (aLoadType == LOAD_LINK) {
10375 openFlags |= nsIURILoader::IS_CONTENT_PREFERRED;
10376 }
10377 if (!aBrowsingContext->GetAllowContentRetargeting()) {
10378 openFlags |= nsIURILoader::DONT_RETARGET;
10379 }
10380
10381 if (!aIsDocumentLoad) {
10382 openFlags |= nsIURILoader::IS_OBJECT_EMBED;
10383
10384 // Unless the pref is set, object/embed loads always specify DONT_RETARGET.
10385 // See bug 1868001 for details.
10386 if (!StaticPrefs::dom_navigation_object_embed_allow_retargeting()) {
10387 openFlags |= nsIURILoader::DONT_RETARGET;
10388 }
10389 }
10390
10391 return openFlags;
10392}
10393
10394nsresult nsDocShell::OpenInitializedChannel(nsIChannel* aChannel,
10395 nsIURILoader* aURILoader,
10396 uint32_t aOpenFlags) {
10397 nsresult rv = NS_OK;
10398
10399 // If anything fails here, make sure to clear our initial ClientSource.
10400 auto cleanupInitialClient =
10401 MakeScopeExit([&] { mInitialClientSource.reset(); });
10402
10403 nsCOMPtr<nsPIDOMWindowOuter> win = GetWindow();
10404 NS_ENSURE_TRUE(win, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(win)), 0))) { NS_DebugBreak(NS_DEBUG_WARNING
, "NS_ENSURE_TRUE(" "win" ") failed", nullptr, "./../../../docshell/base/nsDocShell.cpp"
, 10404); return NS_ERROR_FAILURE; } } while (false)
;
10405
10406 MaybeCreateInitialClientSource();
10407
10408 // Let the client channel helper know if we are using DocumentChannel,
10409 // since redirects get handled in the parent process in that case.
10410 RefPtr<net::DocumentChannel> docChannel = do_QueryObject(aChannel);
10411 if (docChannel && XRE_IsContentProcess()) {
10412 // Tell the content process nsDocumentOpenInfo to not try to do
10413 // any sort of targeting.
10414 aOpenFlags |= nsIURILoader::DONT_RETARGET;
10415 }
10416
10417 // Since we are loading a document we need to make sure the proper reserved
10418 // and initial client data is stored on the nsILoadInfo. The
10419 // ClientChannelHelper does this and ensures that it is propagated properly
10420 // on redirects. We pass no reserved client here so that the helper will
10421 // create the reserved ClientSource if necessary.
10422 Maybe<ClientInfo> noReservedClient;
10423 if (docChannel) {
10424 // When using DocumentChannel, all redirect handling is done in the parent,
10425 // so we just need the child variant to watch for the internal redirect
10426 // to the final channel.
10427 rv = AddClientChannelHelperInChild(aChannel,
10428 GetMainThreadSerialEventTarget());
10429 docChannel->SetInitialClientInfo(GetInitialClientInfo());
10430 } else {
10431 rv = AddClientChannelHelper(aChannel, std::move(noReservedClient),
10432 GetInitialClientInfo(),
10433 GetMainThreadSerialEventTarget());
10434 }
10435 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, "./../../../docshell/base/nsDocShell.cpp"
, 10435); return rv; } } while (false)
;
10436
10437 rv = aURILoader->OpenURI(aChannel, aOpenFlags, this);
10438 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, "./../../../docshell/base/nsDocShell.cpp"
, 10438); return rv; } } while (false)
;
10439
10440 // We're about to load a new page and it may take time before necko
10441 // gives back any data, so main thread might have a chance to process a
10442 // collector slice
10443 nsJSContext::MaybeRunNextCollectorSlice(this, JS::GCReason::DOCSHELL);
10444
10445 // Success. Keep the initial ClientSource if it exists.
10446 cleanupInitialClient.release();
10447
10448 return NS_OK;
10449}
10450
10451nsresult nsDocShell::OpenRedirectedChannel(nsDocShellLoadState* aLoadState) {
10452 nsCOMPtr<nsIChannel> channel = aLoadState->GetPendingRedirectedChannel();
10453 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", "./../../../docshell/base/nsDocShell.cpp"
, 10453); AnnotateMozCrashReason("MOZ_ASSERT" "(" "channel" ")"
); do { MOZ_CrashSequence(__null, 10453); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
10454
10455 // If anything fails here, make sure to clear our initial ClientSource.
10456 auto cleanupInitialClient =
10457 MakeScopeExit([&] { mInitialClientSource.reset(); });
10458
10459 nsCOMPtr<nsPIDOMWindowOuter> win = GetWindow();
10460 NS_ENSURE_TRUE(win, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(win)), 0))) { NS_DebugBreak(NS_DEBUG_WARNING
, "NS_ENSURE_TRUE(" "win" ") failed", nullptr, "./../../../docshell/base/nsDocShell.cpp"
, 10460); return NS_ERROR_FAILURE; } } while (false)
;
10461
10462 MaybeCreateInitialClientSource();
10463
10464 nsCOMPtr<nsILoadInfo> loadInfo = channel->LoadInfo();
10465
10466 LoadInfo* li = static_cast<LoadInfo*>(loadInfo.get());
10467 if (loadInfo->GetExternalContentPolicyType() ==
10468 ExtContentPolicy::TYPE_DOCUMENT) {
10469 li->UpdateBrowsingContextID(mBrowsingContext->Id());
10470 } else if (loadInfo->GetExternalContentPolicyType() ==
10471 ExtContentPolicy::TYPE_SUBDOCUMENT) {
10472 li->UpdateFrameBrowsingContextID(mBrowsingContext->Id());
10473 }
10474
10475 // If we did a process switch, then we should have an existing allocated
10476 // ClientInfo, so we just need to allocate a corresponding ClientSource.
10477 CreateReservedSourceIfNeeded(channel, GetMainThreadSerialEventTarget());
10478
10479 uint32_t documentOpenInfoFlags = nsIURILoader::DONT_RETARGET;
10480 if (loadInfo->GetExternalContentPolicyType() ==
10481 ExtContentPolicy::TYPE_OBJECT) {
10482 documentOpenInfoFlags |= nsIURILoader::IS_OBJECT_EMBED;
10483 }
10484
10485 RefPtr loader =
10486 MakeRefPtr<nsDocumentOpenInfo>(this, documentOpenInfoFlags, nullptr);
10487 channel->SetLoadGroup(mLoadGroup);
10488
10489 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())"
, "./../../../docshell/base/nsDocShell.cpp", 10489); AnnotateMozCrashReason
("MOZ_CRASH(" "NS_SUCCEEDED(loader->Prepare())" ")"); do {
MOZ_CrashSequence(__null, 10489); __attribute__((nomerge)) ::
abort(); } while (false); } while (false); } } while (false)
;
10490
10491 nsresult rv = NS_OK;
10492 if (XRE_IsParentProcess()) {
10493 // If we're in the parent, the we don't have an nsIChildChannel, just
10494 // the original channel, which is already open in this process.
10495
10496 // DocumentLoadListener expects to get an nsIParentChannel, so
10497 // we create a wrapper around the channel and nsIStreamListener
10498 // that forwards functionality as needed, and then we register
10499 // it under the provided identifier.
10500 RefPtr wrapper = MakeRefPtr<ParentChannelWrapper>(channel, loader);
10501 // We're in the parent process, so the redirect is owned by the parent
10502 // process (ContentParentId 0).
10503 wrapper->Register(aLoadState->GetPendingRedirectChannelRegistrarId(), 0);
10504
10505 mLoadGroup->AddRequest(channel, nullptr);
10506 } else if (nsCOMPtr<nsIChildChannel> childChannel =
10507 do_QueryInterface(channel)) {
10508 // Our channel was redirected from another process, so doesn't need to
10509 // be opened again. However, it does need its listener hooked up
10510 // correctly.
10511 rv = childChannel->CompleteRedirectSetup(loader);
10512 } else {
10513 // It's possible for the redirected channel to not implement
10514 // nsIChildChannel and be entirely local (like srcdoc). In that case we
10515 // can just open the local instance and it will work.
10516 rv = channel->AsyncOpen(loader);
10517 }
10518 if (rv == NS_ERROR_NO_CONTENT) {
10519 return NS_OK;
10520 }
10521 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, "./../../../docshell/base/nsDocShell.cpp"
, 10521); return rv; } } while (false)
;
10522
10523 // Success. Keep the initial ClientSource if it exists.
10524 cleanupInitialClient.release();
10525 return NS_OK;
10526}
10527
10528// https://html.spec.whatwg.org/#scrolling-to-a-fragment
10529nsresult nsDocShell::ScrollToAnchor(bool aCurHasRef, bool aNewHasRef,
10530 nsACString& aNewHash, uint32_t aLoadType) {
10531 if (!mCurrentURI) {
10532 return NS_OK;
10533 }
10534
10535 RefPtr<PresShell> presShell = GetPresShell();
10536 if (!presShell) {
10537 // If we failed to get the shell, or if there is no shell,
10538 // nothing left to do here.
10539 return NS_OK;
10540 }
10541
10542 ScrollContainerFrame* rootScroll = presShell->GetRootScrollContainerFrame();
10543 if (rootScroll) {
10544 rootScroll->ClearDidHistoryRestore();
10545 }
10546
10547 // If it's a load from history, we don't have any anchor jumping to do.
10548 // Scrollbar position will be restored by the caller based on positions stored
10549 // in session history.
10550 bool scroll = aLoadType != LOAD_HISTORY && aLoadType != LOAD_RELOAD_NORMAL;
10551 // If the load contains text directives, try to apply them. This may fail if
10552 // the load is a same-document load that was initiated before the document was
10553 // fully loaded and the target is not yet included in the DOM tree.
10554 // For this case, the `uninvokedTextDirectives` are not cleared, so that
10555 // `Document::ScrollToRef()` can re-apply the text directive.
10556 // `Document::ScrollToRef()` is (presumably) the second "async" call mentioned
10557 // in sec. 7.4.2.3.3 in the HTML spec, "Fragment navigations":
10558 // https://html.spec.whatwg.org/#scroll-to-fragid:~:text=This%20algorithm%20will%20be%20called%20twice
10559
10560 const RefPtr fragmentDirective = GetDocument()->FragmentDirective();
10561 const nsTArray<RefPtr<nsRange>> textDirectiveRanges =
10562 fragmentDirective->FindTextFragmentsInDocument();
10563 fragmentDirective->HighlightTextDirectives(textDirectiveRanges);
10564 const bool scrollToTextDirective =
10565 !textDirectiveRanges.IsEmpty() &&
10566 fragmentDirective->IsTextDirectiveAllowedToBeScrolledTo();
10567 const RefPtr<nsRange> textDirectiveToScroll =
10568 scrollToTextDirective ? textDirectiveRanges[0] : nullptr;
10569
10570 // If we have no new anchor, we do not want to scroll, unless there is a
10571 // current anchor and we are doing a history load. So return if we have no
10572 // new anchor, and there is no current anchor or the load is not a history
10573 // load.
10574 if ((!aCurHasRef || aLoadType != LOAD_HISTORY) && !aNewHasRef &&
10575 !scrollToTextDirective) {
10576 return NS_OK;
10577 }
10578
10579 // Both the new and current URIs refer to the same page. We can now
10580 // browse to the hash stored in the new URI.
10581
10582 if (aNewHash.IsEmpty() && !scrollToTextDirective) {
10583 // 2. If fragment is the empty string, then return the special value top of
10584 // the document.
10585 //
10586 // Tell the shell it's at an anchor without scrolling.
10587 presShell->GoToAnchor(u""_ns, nullptr, false);
10588
10589 if (scroll) {
10590 // Scroll to the top of the page. Ignore the return value; failure to
10591 // scroll here (e.g. if there is no root scrollframe) is not grounds for
10592 // canceling the load!
10593 SetCurScrollPosEx(0, 0);
10594 }
10595
10596 return NS_OK;
10597 }
10598
10599 // 3. Let potentialIndicatedElement be the result of finding a potential
10600 // indicated element given document and fragment.
10601 NS_ConvertUTF8toUTF16 uStr(aNewHash);
10602
10603 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"
, "./../../../docshell/base/nsDocShell.cpp", 10603); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!uStr.IsEmpty() || scrollToTextDirective" ")"
); do { MOZ_CrashSequence(__null, 10603); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
10604
10605 auto rv = presShell->GoToAnchor(uStr, textDirectiveToScroll, scroll,
10606 ScrollFlags::ScrollSmoothAuto);
10607
10608 // 4. If potentialIndicatedElement is not null, then return
10609 // potentialIndicatedElement.
10610 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
10611 return NS_OK;
10612 }
10613
10614 // 5. Let fragmentBytes be the result of percent-decoding fragment.
10615 nsAutoCString fragmentBytes;
10616 const bool unescaped = NS_UnescapeURL(aNewHash.Data(), aNewHash.Length(),
10617 /* aFlags = */ 0, fragmentBytes);
10618
10619 if (!unescaped) {
10620 // Another attempt is only necessary if characters were unescaped.
10621 return NS_OK;
10622 }
10623
10624 if (fragmentBytes.IsEmpty()) {
10625 // When aNewHash contains "%00", the unescaped string may be empty, and
10626 // GoToAnchor asserts if we ask it to scroll to an empty ref.
10627 presShell->GoToAnchor(u""_ns, nullptr, false);
10628 return NS_OK;
10629 }
10630
10631 // 6. Let decodedFragment be the result of running UTF-8 decode without BOM on
10632 // fragmentBytes.
10633 nsAutoString decodedFragment;
10634 rv = UTF_8_ENCODING->DecodeWithoutBOMHandling(fragmentBytes, decodedFragment);
10635 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, "./../../../docshell/base/nsDocShell.cpp"
, 10635); return rv; } } while (false)
;
10636
10637 // 7. Set potentialIndicatedElement to the result of finding a potential
10638 // indicated element given document and decodedFragment.
10639 //
10640 // Ignore the return value of GoToAnchor, since it will return an error if
10641 // there is no such anchor in the document, which is actually a success
10642 // condition for us (we want to update the session history with the new URI no
10643 // matter whether we actually scrolled somewhere).
10644 presShell->GoToAnchor(decodedFragment, nullptr, scroll,
10645 ScrollFlags::ScrollSmoothAuto);
10646
10647 return NS_OK;
10648}
10649
10650bool nsDocShell::OnNewURI(nsIURI* aURI, nsIChannel* aChannel,
10651 nsIPrincipal* aTriggeringPrincipal,
10652 nsIPrincipal* aPrincipalToInherit,
10653 nsIPrincipal* aPartitionedPrincipalToInherit,
10654 nsIPolicyContainer* aPolicyContainer,
10655 bool aAddToGlobalHistory, bool aCloneSHChildren) {
10656 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" ")", "./../../../docshell/base/nsDocShell.cpp"
, 10656); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aURI" ") ("
"uri is null" ")"); do { MOZ_CrashSequence(__null, 10656); __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
;
10657 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"
")", "./../../../docshell/base/nsDocShell.cpp", 10657); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!aChannel || !aTriggeringPrincipal" ") (" "Shouldn't have both set"
")"); do { MOZ_CrashSequence(__null, 10657); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10658
10659 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)"
, "./../../../docshell/base/nsDocShell.cpp", 10660); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!aPrincipalToInherit || (aPrincipalToInherit && aTriggeringPrincipal)"
")"); do { MOZ_CrashSequence(__null, 10660); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
10660 (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)"
, "./../../../docshell/base/nsDocShell.cpp", 10660); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!aPrincipalToInherit || (aPrincipalToInherit && aTriggeringPrincipal)"
")"); do { MOZ_CrashSequence(__null, 10660); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10661
10662#if defined(DEBUG1)
10663 if (MOZ_LOG_TEST(gDocShellLog, LogLevel::Debug)(__builtin_expect(!!(mozilla::detail::log_test(gDocShellLog, LogLevel
::Debug)), 0))
) {
10664 nsAutoCString chanName;
10665 if (aChannel) {
10666 aChannel->GetName(chanName);
10667 } else {
10668 chanName.AssignLiteral("<no channel>");
10669 }
10670
10671 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)
10672 ("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)
10673 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)
;
10674 }
10675#endif
10676
10677 bool equalUri = false;
10678
10679 // Get the post data and the HTTP response code from the channel.
10680 uint32_t responseStatus = 0;
10681 nsCOMPtr<nsIInputStream> inputStream;
10682 if (aChannel) {
10683 nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(aChannel));
10684
10685 // Check if the HTTPChannel is hiding under a multiPartChannel
10686 if (!httpChannel) {
10687 GetHttpChannel(aChannel, getter_AddRefs(httpChannel));
10688 }
10689
10690 if (httpChannel) {
10691 nsCOMPtr<nsIUploadChannel> uploadChannel(do_QueryInterface(httpChannel));
10692 if (uploadChannel) {
10693 uploadChannel->GetUploadStream(getter_AddRefs(inputStream));
10694 }
10695 }
10696 }
10697
10698 // Determine if this type of load should update history.
10699 bool updateGHistory = ShouldUpdateGlobalHistory(mLoadType);
10700
10701 // We don't update session history on reload unless we're loading
10702 // an iframe in shift-reload case.
10703 [[maybe_unused]]
10704 bool updateSHistory = mBrowsingContext->ShouldUpdateSessionHistory(mLoadType);
10705
10706 // Create SH Entry (mLSHE) only if there is a SessionHistory object in the
10707 // root browsing context.
10708 // FIXME If session history in the parent is enabled then we only do this if
10709 // the session history object is in process, otherwise we can't really
10710 // use the mLSHE anyway. Once session history is only stored in the
10711 // parent then this code will probably be removed anyway.
10712 RefPtr<ChildSHistory> rootSH = GetRootSessionHistory();
10713 if (!rootSH) {
10714 updateSHistory = false;
10715 updateGHistory = false; // XXX Why global history too?
10716 }
10717
10718 // Check if the url to be loaded is the same as the one already loaded.
10719 if (mCurrentURI) {
10720 aURI->Equals(mCurrentURI, &equalUri);
10721 }
10722
10723#ifdef DEBUG1
10724 bool shAvailable = (rootSH != nullptr);
10725
10726 // XXX This log message is almost useless because |updateSHistory|
10727 // and |updateGHistory| are not correct at this point.
10728
10729 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)
10730 (" 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)
10731 " 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)
10732 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)
;
10733#endif
10734
10735 /* If the url to be loaded is the same as the one already there,
10736 * and the original loadType is LOAD_NORMAL, LOAD_LINK, or
10737 * LOAD_STOP_CONTENT, set loadType to LOAD_NORMAL_REPLACE so that
10738 * AddToSessionHistory() won't mess with the current SHEntry and
10739 * if this page has any frame children, it also will be handled
10740 * properly. see bug 83684
10741 *
10742 * NB: If mOSHE is null but we have a current URI, then it probably
10743 * means that we must be at the transient about:blank content viewer;
10744 * we should let the normal load continue, since there's nothing to
10745 * replace. Sometimes this happens after a session restore (eg process
10746 * switch) and mCurrentURI is not about:blank; we assume we can let the load
10747 * continue (Bug 1301399).
10748 *
10749 * XXX Hopefully changing the loadType at this time will not hurt
10750 * anywhere. The other way to take care of sequentially repeating
10751 * frameset pages is to add new methods to nsIDocShellTreeItem.
10752 * Hopefully I don't have to do that.
10753 */
10754 if (equalUri && mActiveEntry &&
10755 (mLoadType == LOAD_NORMAL || mLoadType == LOAD_LINK ||
10756 mLoadType == LOAD_STOP_CONTENT) &&
10757 !inputStream) {
10758 mLoadType = LOAD_NORMAL_REPLACE;
10759 }
10760
10761 /* If the user pressed shift-reload, cache will create a new cache key
10762 * for the page. Save the new cacheKey in Session History.
10763 * see bug 90098
10764 */
10765 if (aChannel && IsForceReloadType(mLoadType)) {
10766 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!" ")", "./../../../docshell/base/nsDocShell.cpp"
, 10768); 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, 10768); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
10767 "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!" ")", "./../../../docshell/base/nsDocShell.cpp"
, 10768); 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, 10768); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
10768 " 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!" ")", "./../../../docshell/base/nsDocShell.cpp"
, 10768); 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, 10768); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10769
10770 nsCOMPtr<nsICacheInfoChannel> cacheChannel(do_QueryInterface(aChannel));
10771 uint32_t cacheKey = 0;
10772 // Get the Cache Key and store it in SH.
10773 if (cacheChannel) {
10774 cacheChannel->GetCacheKey(&cacheKey);
10775 }
10776 // If we already have a loading history entry, store the new cache key
10777 // in it. Otherwise, since we're doing a reload and won't be updating
10778 // our history entry, store the cache key in our current history entry.
10779 SetCacheKeyOnHistoryEntry(cacheKey);
10780 }
10781
10782 if (ShouldAddURIVisit(aChannel) && updateGHistory && aAddToGlobalHistory) {
10783 nsCOMPtr<nsIURI> previousURI;
10784 uint32_t previousFlags = 0;
10785
10786 if (mLoadType & LOAD_CMD_RELOAD) {
10787 // On a reload request, we don't set redirecting flags.
10788 previousURI = aURI;
10789 } else {
10790 ExtractLastVisit(aChannel, getter_AddRefs(previousURI), &previousFlags);
10791 }
10792
10793 AddURIVisit(aURI, previousURI, previousFlags, responseStatus,
10794 net::ChannelIsPost(aChannel));
10795 }
10796
10797 // aCloneSHChildren exactly means "we are not loading a new document".
10798 uint32_t locationFlags =
10799 aCloneSHChildren ? uint32_t(LOCATION_CHANGE_SAME_DOCUMENT) : 0;
10800
10801 bool onLocationChangeNeeded =
10802 SetCurrentURI(aURI, aChannel, false,
10803 /* aIsInitialAboutBlank */ false, locationFlags);
10804 // Make sure to store the referrer from the channel, if any
10805 nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(aChannel));
10806 if (httpChannel) {
10807 mReferrerInfo = httpChannel->GetReferrerInfo();
10808 }
10809 return onLocationChangeNeeded;
10810}
10811
10812Maybe<Wireframe> nsDocShell::GetWireframe() {
10813 const bool collectWireFrame =
10814 StaticPrefs::browser_history_collectWireframes() &&
10815 mBrowsingContext->IsTopContent() && mActiveEntry;
10816
10817 if (!collectWireFrame) {
10818 return Nothing();
10819 }
10820
10821 RefPtr<Document> doc = mDocumentViewer->GetDocument();
10822 Nullable<Wireframe> wireframe;
10823 doc->GetWireframeWithoutFlushing(false, wireframe);
10824 if (wireframe.IsNull()) {
10825 return Nothing();
10826 }
10827 return Some(wireframe.Value());
10828}
10829
10830bool nsDocShell::CollectWireframe() {
10831 Maybe<Wireframe> wireframe = GetWireframe();
10832 if (wireframe.isNothing()) {
10833 return false;
10834 }
10835
10836 if (XRE_IsParentProcess()) {
10837 SessionHistoryEntry* entry =
10838 mBrowsingContext->Canonical()->GetActiveSessionHistoryEntry();
10839 if (entry) {
10840 entry->SetWireframe(wireframe);
10841 }
10842 } else {
10843 (void)ContentChild::GetSingleton()->SendSessionHistoryEntryWireframe(
10844 mBrowsingContext, wireframe.ref());
10845 }
10846
10847 return true;
10848}
10849
10850//*****************************************************************************
10851// nsDocShell: Session History
10852//*****************************************************************************
10853
10854NS_IMETHODIMPnsresult
10855nsDocShell::AddState(JS::Handle<JS::Value> aData, const nsAString& aTitle,
10856 const nsAString& aURL, bool aReplace, JSContext* aCx) {
10857 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)
10858 ("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)
10859 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)
10860 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)
;
10861 // Implements History.pushState and History.replaceState
10862
10863 // Here's what we do, roughly in the order specified by HTML5. The specific
10864 // steps we are executing are at
10865 // <https://html.spec.whatwg.org/multipage/history.html#dom-history-pushstate>,
10866 // <https://html.spec.whatwg.org/#shared-history-push/replace-state-steps>,
10867 // and
10868 // <https://html.spec.whatwg.org/multipage/history.html#url-and-history-update-steps>.
10869 // This function basically implements #dom-history-pushstate and
10870 // UpdateURLAndHistory implements #url-and-history-update-steps.
10871 //
10872 // A. Serialize aData using structured clone. This is #dom-history-pushstate
10873 // step 5.
10874 // B. If the third argument is present, #dom-history-pushstate step 7.
10875 // 7.1. Resolve the url, relative to our document.
10876 // 7.2. If (a) fails, raise a SECURITY_ERR
10877 // 7.4. Compare the resulting absolute URL to the document's address. If
10878 // any part of the URLs difer other than the <path>, <query>, and
10879 // <fragment> components, raise a SECURITY_ERR and abort.
10880 // C. If !aReplace, #url-and-history-update-steps steps 2.1-2.3:
10881 // Remove from the session history all entries after the current entry,
10882 // as we would after a regular navigation, and save the current
10883 // entry's scroll position (bug 590573).
10884 // D. #url-and-history-update-steps step 2.4 or step 3. As apropriate,
10885 // either add a state object entry to the session history after the
10886 // current entry with the following properties, or modify the current
10887 // session history entry to set
10888 // a. cloned data as the state object,
10889 // b. if the third argument was present, the absolute URL found in
10890 // step 2
10891 // Also clear the new history entry's POST data (see bug 580069).
10892 // E. If aReplace is false (i.e. we're doing a pushState instead of a
10893 // replaceState), notify bfcache that we've navigated to a new page.
10894 // F. If the third argument is present, set the document's current address
10895 // to the absolute URL found in step B. This is
10896 // #url-and-history-update-steps step 4.
10897 //
10898 // It's important that this function not run arbitrary scripts after step A
10899 // and before completing step E. For example, if a script called
10900 // history.back() before we completed step E, bfcache might destroy an
10901 // active content viewer. Since EvictOutOfRangeDocumentViewers at the end of
10902 // step E might run script, we can't just put a script blocker around the
10903 // critical section.
10904 //
10905 // Note that we completely ignore the aTitle parameter.
10906
10907 nsresult rv;
10908
10909 RefPtr<Document> document = GetDocument();
10910 NS_ENSURE_TRUE(document, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(document)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "document" ") failed", nullptr
, "./../../../docshell/base/nsDocShell.cpp", 10910); return NS_ERROR_FAILURE
; } } while (false)
;
10911
10912 // Don't clobber the load type of an existing network load.
10913 Maybe<AutoRestore<uint32_t>> loadTypeResetter;
10914 if (StaticPrefs::
10915 docshell_shistory_sameDocumentNavigationOverridesLoadType() &&
10916 !document->NodePrincipal()->IsURIInPrefList(
10917 "docshell.shistory.sameDocumentNavigationOverridesLoadType."
10918 "forceDisable")) {
10919 loadTypeResetter.emplace(mLoadType);
10920 }
10921
10922 // pushState effectively becomes replaceState when we've started a network
10923 // load but haven't adopted its document yet. This mirrors what we do with
10924 // changes to the hash at this stage of the game.
10925 if (JustStartedNetworkLoad()) {
10926 if (!loadTypeResetter.isSome()) {
10927 loadTypeResetter.emplace(mLoadType);
10928 }
10929 aReplace = true;
10930 }
10931
10932 // Step A: Serialize aData using structured clone.
10933 // https://html.spec.whatwg.org/multipage/history.html#dom-history-pushstate
10934 // step 5.
10935 nsCOMPtr<nsIStructuredCloneContainer> scContainer;
10936
10937 // scContainer->Init might cause arbitrary JS to run, and this code might
10938 // navigate the page we're on, potentially to a different origin! (bug
10939 // 634834) To protect against this, we abort if our principal changes due
10940 // to the InitFromJSVal() call.
10941 {
10942 RefPtr<Document> origDocument = GetDocument();
10943 if (!origDocument) {
10944 return NS_ERROR_DOM_SECURITY_ERR;
10945 }
10946 nsCOMPtr<nsIPrincipal> origPrincipal = origDocument->NodePrincipal();
10947
10948 scContainer = new nsStructuredCloneContainer();
10949 rv = scContainer->InitFromJSVal(aData, aCx);
10950 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, "./../../../docshell/base/nsDocShell.cpp"
, 10950); return rv; } } while (false)
;
10951
10952 RefPtr<Document> newDocument = GetDocument();
10953 if (!newDocument) {
10954 return NS_ERROR_DOM_SECURITY_ERR;
10955 }
10956 nsCOMPtr<nsIPrincipal> newPrincipal = newDocument->NodePrincipal();
10957
10958 bool principalsEqual = false;
10959 origPrincipal->Equals(newPrincipal, &principalsEqual);
10960 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, "./../../../docshell/base/nsDocShell.cpp", 10960);
return NS_ERROR_DOM_SECURITY_ERR; } } while (false)
;
10961 }
10962
10963 // Check that the state object isn't too long.
10964 int32_t maxStateObjSize = StaticPrefs::browser_history_maxStateObjectSize();
10965 if (maxStateObjSize < 0) {
10966 maxStateObjSize = 0;
10967 }
10968
10969 uint64_t scSize;
10970 rv = scContainer->GetSerializedNBytes(&scSize);
10971 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, "./../../../docshell/base/nsDocShell.cpp"
, 10971); return rv; } } while (false)
;
10972
10973 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, "./../../../docshell/base/nsDocShell.cpp"
, 10973); return NS_ERROR_ILLEGAL_VALUE; } } while (false)
;
10974
10975 // Step B: Resolve aURL.
10976 // https://html.spec.whatwg.org/multipage/history.html#dom-history-pushstate
10977 // step 7.
10978 bool equalURIs = true;
10979 nsCOMPtr<nsIURI> currentURI;
10980 if (mCurrentURI) {
10981 currentURI = nsIOService::CreateExposableURI(mCurrentURI);
10982 } else {
10983 currentURI = mCurrentURI;
10984 }
10985 nsCOMPtr<nsIURI> newURI;
10986 if (aURL.Length() == 0) {
10987 newURI = currentURI;
10988 } else {
10989 // 7.1: Resolve aURL relative to mURI
10990
10991 nsIURI* docBaseURI = document->GetDocBaseURI();
10992 if (!docBaseURI) {
10993 return NS_ERROR_FAILURE;
10994 }
10995
10996 nsAutoCString spec;
10997 docBaseURI->GetSpec(spec);
10998
10999 rv = NS_NewURI(getter_AddRefs(newURI), aURL,
11000 document->GetDocumentCharacterSet(), docBaseURI);
11001
11002 // 7.2: If 2a fails, raise a SECURITY_ERR
11003 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
11004 return NS_ERROR_DOM_SECURITY_ERR;
11005 }
11006
11007 if (!document->CanRewriteURL(newURI)) {
11008 return NS_ERROR_DOM_SECURITY_ERR;
11009 }
11010
11011 if (currentURI) {
11012 currentURI->Equals(newURI, &equalURIs);
11013 } else {
11014 equalURIs = false;
11015 }
11016
11017 } // end of same-origin check
11018
11019 // https://html.spec.whatwg.org/#shared-history-push/replace-state-steps
11020 // Step 8
11021 if (nsCOMPtr<nsPIDOMWindowInner> window = document->GetInnerWindow()) {
11022 if (RefPtr<Navigation> navigation = window->Navigation()) {
11023 bool shouldContinue = navigation->FirePushReplaceReloadNavigateEvent(
11024 aCx, aReplace ? NavigationType::Replace : NavigationType::Push,
11025 newURI,
11026 /* aIsSameDocument */ true,
11027 /* aUserInvolvement */ Nothing(),
11028 /* aSourceElement */ nullptr, /* aFormDataEntryList */ nullptr,
11029 /* aNavigationAPIState */ nullptr, scContainer);
11030
11031 // Step 9
11032 if (!shouldContinue) {
11033 return NS_OK;
11034 }
11035 }
11036 }
11037
11038 // Step 10
11039 // Run #url-and-history-update-steps
11040 rv = UpdateURLAndHistory(document, newURI, scContainer,
11041 aReplace ? NavigationHistoryBehavior::Replace
11042 : NavigationHistoryBehavior::Push,
11043 currentURI, equalURIs);
11044 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, "./../../../docshell/base/nsDocShell.cpp"
, 11044); return rv; } } while (false)
;
11045
11046 return NS_OK;
11047}
11048
11049nsresult nsDocShell::UpdateURLAndHistory(
11050 Document* aDocument, nsIURI* aNewURI, nsIStructuredCloneContainer* aData,
11051 NavigationHistoryBehavior aHistoryHandling, nsIURI* aCurrentURI,
11052 bool aEqualURIs, bool aFiredNavigateEvent) {
11053 MOZ_LOG_FMT(gNavigationAPILog, LogLevel::Debug, "UpdateURLAndHistory {}",do { const ::mozilla::LogModule* moz_real_module = gNavigationAPILog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print_fmt(moz_real_module
, LogLevel::Debug, "UpdateURLAndHistory {}", aHistoryHandling
); } } while (0)
11054 aHistoryHandling)do { const ::mozilla::LogModule* moz_real_module = gNavigationAPILog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print_fmt(moz_real_module
, LogLevel::Debug, "UpdateURLAndHistory {}", aHistoryHandling
); } } while (0)
;
11055
11056 // Implements
11057 // https://html.spec.whatwg.org/multipage/history.html#url-and-history-update-steps
11058 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"
, "./../../../docshell/base/nsDocShell.cpp", 11058); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aHistoryHandling != NavigationHistoryBehavior::Auto"
")"); do { MOZ_CrashSequence(__null, 11058); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11059 bool isReplace = aHistoryHandling == NavigationHistoryBehavior::Replace;
11060
11061 // If we have a pending title change, handle it before creating a new entry.
11062 aDocument->DoNotifyPossibleTitleChange();
11063
11064 // Step 2, if aReplace is false: Create a new entry in the session
11065 // history. This will erase all SHEntries after the new entry and make this
11066 // entry the current one.
11067 NS_ENSURE_TRUE(mActiveEntry || isReplace, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(mActiveEntry || isReplace)), 0
))) { NS_DebugBreak(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "mActiveEntry || isReplace"
") failed", nullptr, "./../../../docshell/base/nsDocShell.cpp"
, 11067); return NS_ERROR_FAILURE; } } while (false)
;
11068
11069 // If this push/replaceState changed the document's current URI and the new
11070 // URI differs from the old URI in more than the hash, or if the old
11071 // SHEntry's URI was modified in this way by a push/replaceState call
11072 // set URIWasModified to true for the current SHEntry (bug 669671).
11073 bool sameExceptHashes = true;
11074 aNewURI->EqualsExceptRef(aCurrentURI, &sameExceptHashes);
11075 bool uriWasModified;
11076 if (sameExceptHashes) {
11077 uriWasModified = mActiveEntry && mActiveEntry->GetURIWasModified();
11078 } else {
11079 uriWasModified = true;
11080 }
11081
11082 mLoadType = LOAD_PUSHSTATE;
11083
11084 RefPtr<SessionHistoryEntry> newSHEntry;
11085 if (!isReplace) {
11086 // Step 2.
11087
11088 // Step 2.2, "Remove any tasks queued by the history traversal task
11089 // source that are associated with any Document objects in the
11090 // top-level browsing context's document family." This is very hard in
11091 // SessionHistoryInParent since we can't synchronously access the
11092 // pending navigations that are already sent to the parent. We can
11093 // abort any AsyncGo navigations that are waiting to be sent. If we
11094 // send a message to the parent, it would be processed after any
11095 // navigations previously sent. So long as we consider the "history
11096 // traversal task source" to be the list in this process we match the
11097 // spec. If we move the entire list to the parent, we can handle the
11098 // aborting of loads there, but we don't have a way to synchronously
11099 // remove entries as we do here for non-SHIP.
11100 RefPtr<ChildSHistory> shistory = GetRootSessionHistory();
11101 if (shistory) {
11102 shistory->RemovePendingHistoryNavigations();
11103 }
11104
11105 nsPoint scrollPos = GetCurScrollPos();
11106
11107 bool scrollRestorationIsManual;
11108 // FIXME Need to save the current scroll position on mActiveEntry.
11109 scrollRestorationIsManual = mActiveEntry->GetScrollRestorationIsManual();
11110
11111 nsCOMPtr<nsIPolicyContainer> policyContainer =
11112 aDocument->GetPolicyContainer();
11113
11114 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)
11115 ("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)
;
11116
11117 nsString title(mActiveEntry->GetTitle());
11118 nsCOMPtr<nsIReferrerInfo> referrerInfo = mActiveEntry->GetReferrerInfo();
11119
11120 UpdateActiveEntry(false,
11121 /* aPreviousScrollPos = */ Some(scrollPos), aNewURI,
11122 /* aOriginalURI = */ nullptr,
11123 /* aReferrerInfo = */ referrerInfo,
11124 /* aTriggeringPrincipal = */ aDocument->NodePrincipal(),
11125 policyContainer, title, scrollRestorationIsManual, aData,
11126 uriWasModified);
11127 } else {
11128 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)
11129 ("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)
11130 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)
;
11131 // Setting the resultPrincipalURI to nullptr is fine here: it will cause
11132 // NS_GetFinalChannelURI to use the originalURI as the URI, which is aNewURI
11133 // in our case. We could also set it to aNewURI, with the same result.
11134 // We don't use aTitle here, see bug 544535.
11135 nsString title;
11136 nsCOMPtr<nsIReferrerInfo> referrerInfo;
11137 if (mActiveEntry) {
11138 title = mActiveEntry->GetTitle();
11139 referrerInfo = mActiveEntry->GetReferrerInfo();
11140 } else {
11141 referrerInfo = nullptr;
11142 }
11143 UpdateActiveEntry(
11144 true, /* aPreviousScrollPos = */ Nothing(), aNewURI, aNewURI,
11145 /* aReferrerInfo = */ referrerInfo, aDocument->NodePrincipal(),
11146 aDocument->GetPolicyContainer(), title,
11147 mActiveEntry && mActiveEntry->GetScrollRestorationIsManual(), aData,
11148 uriWasModified);
11149 }
11150
11151 // Step 4: If the document's URI changed, update document's URI and update
11152 // global history.
11153 //
11154 // We need to call FireOnLocationChange so that the browser's address bar
11155 // gets updated and the back button is enabled, but we only need to
11156 // explicitly call FireOnLocationChange if we're not calling SetCurrentURI,
11157 // since SetCurrentURI will call FireOnLocationChange for us.
11158 //
11159 // Both SetCurrentURI(...) and FireDummyOnLocationChange() pass
11160 // nullptr for aRequest param to FireOnLocationChange(...). Such an update
11161 // notification is allowed only when we know docshell is not loading a new
11162 // document and it requires LOCATION_CHANGE_SAME_DOCUMENT flag. Otherwise,
11163 // FireOnLocationChange(...) breaks security UI.
11164 //
11165 // If the docshell is shutting down, don't update the document URI, as we
11166 // can't load into a docshell that is being destroyed.
11167 if (!aEqualURIs && !mIsBeingDestroyed) {
11168 aDocument->SetDocumentURI(aNewURI);
11169 SetCurrentURI(aNewURI, nullptr, /* aFireLocationChange */ true,
11170 /* aIsInitialAboutBlank */ false,
11171 GetSameDocumentNavigationFlags(aNewURI));
11172
11173 AddURIVisit(aNewURI, aCurrentURI, 0);
11174
11175 // AddURIVisit doesn't set the title for the new URI in global history,
11176 // so do that here.
11177 UpdateGlobalHistoryTitle(aNewURI);
11178
11179 // Inform the favicon service that our old favicon applies to this new
11180 // URI.
11181 CopyFavicon(aCurrentURI, aNewURI, UsePrivateBrowsing());
11182 } else {
11183 FireDummyOnLocationChange();
11184 }
11185 aDocument->SetStateObject(aData);
11186
11187 if (RefPtr navigation = aDocument->GetInnerWindow()->Navigation()) {
11188 MOZ_LOG(gNavigationAPILog, LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = gNavigationAPILog
; 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)
11189 ("nsDocShell %p triggering a navigation event for a same-document "do { const ::mozilla::LogModule* moz_real_module = gNavigationAPILog
; 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)
11190 "navigation from UpdateURLAndHistory -> isReplace: %s",do { const ::mozilla::LogModule* moz_real_module = gNavigationAPILog
; 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)
11191 this, isReplace ? "true" : "false"))do { const ::mozilla::LogModule* moz_real_module = gNavigationAPILog
; 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)
;
11192 // Step 11: Update the navigation API entries for a same-document
11193 // navigation given document's relevant global object's navigation API,
11194 // newEntry, and historyHandling.
11195 navigation->UpdateEntriesForSameDocumentNavigation(
11196 mActiveEntry.get(),
11197 isReplace ? NavigationType::Replace : NavigationType::Push,
11198 aFiredNavigateEvent);
11199 }
11200
11201 return NS_OK;
11202}
11203
11204NS_IMETHODIMPnsresult
11205nsDocShell::GetCurrentScrollRestorationIsManual(bool* aIsManual) {
11206 *aIsManual = mActiveEntry && mActiveEntry->GetScrollRestorationIsManual();
11207 return NS_OK;
11208}
11209
11210NS_IMETHODIMPnsresult
11211nsDocShell::SetCurrentScrollRestorationIsManual(bool aIsManual) {
11212 SetScrollRestorationIsManualOnHistoryEntry(aIsManual);
11213
11214 return NS_OK;
11215}
11216
11217void nsDocShell::SetScrollRestorationIsManualOnHistoryEntry(bool aIsManual) {
11218 if (mActiveEntry && mBrowsingContext) {
11219 mActiveEntry->SetScrollRestorationIsManual(aIsManual);
11220 if (XRE_IsParentProcess()) {
11221 SessionHistoryEntry* entry =
11222 mBrowsingContext->Canonical()->GetActiveSessionHistoryEntry();
11223 if (entry) {
11224 entry->SetScrollRestorationIsManual(aIsManual);
11225 }
11226 } else {
11227 (void)ContentChild::GetSingleton()
11228 ->SendSessionHistoryEntryScrollRestorationIsManual(mBrowsingContext,
11229 aIsManual);
11230 }
11231 }
11232}
11233
11234void nsDocShell::SetCacheKeyOnHistoryEntry(uint32_t aCacheKey) {
11235 if (mActiveEntry && mBrowsingContext) {
11236 mActiveEntry->SetCacheKey(aCacheKey);
11237 if (XRE_IsParentProcess()) {
11238 SessionHistoryEntry* entry =
11239 mBrowsingContext->Canonical()->GetActiveSessionHistoryEntry();
11240 if (entry) {
11241 entry->SetCacheKey(aCacheKey);
11242 }
11243 } else {
11244 (void)ContentChild::GetSingleton()->SendSessionHistoryEntryCacheKey(
11245 mBrowsingContext, aCacheKey);
11246 }
11247 }
11248}
11249
11250void nsDocShell::UpdateActiveEntry(
11251 bool aReplace, const Maybe<nsPoint>& aPreviousScrollPos, nsIURI* aURI,
11252 nsIURI* aOriginalURI, nsIReferrerInfo* aReferrerInfo,
11253 nsIPrincipal* aTriggeringPrincipal, nsIPolicyContainer* aPolicyContainer,
11254 const nsAString& aTitle, bool aScrollRestorationIsManual,
11255 nsIStructuredCloneContainer* aData, bool aURIWasModified) {
11256 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" ")", "./../../../docshell/base/nsDocShell.cpp"
, 11256); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aURI" ") ("
"uri is null" ")"); do { MOZ_CrashSequence(__null, 11256); __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
;
11257 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" ")", "./../../../docshell/base/nsDocShell.cpp"
, 11258); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mLoadType == LOAD_PUSHSTATE"
") (" "This code only deals with pushState" ")"); do { MOZ_CrashSequence
(__null, 11258); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
11258 "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" ")", "./../../../docshell/base/nsDocShell.cpp"
, 11258); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mLoadType == LOAD_PUSHSTATE"
") (" "This code only deals with pushState" ")"); do { MOZ_CrashSequence
(__null, 11258); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
11259 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", "./../../../docshell/base/nsDocShell.cpp", 11259
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aReplace" ")"); do
{ MOZ_CrashSequence(__null, 11259); __attribute__((nomerge))
::abort(); } while (false); } } while (false); } } while (false
)
;
11260
11261 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)
11262 ("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)
11263 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)
;
11264
11265 // Even if we're replacing an existing entry we create new a
11266 // SessionHistoryInfo. In the parent process we'll keep the existing
11267 // SessionHistoryEntry, but just replace its SessionHistoryInfo, that way the
11268 // entry keeps identity but its data is replaced.
11269 bool replace = aReplace && mActiveEntry;
11270
11271 if (!replace) {
11272 CollectWireframe();
11273 }
11274
11275 UniquePtr<SessionHistoryInfo> previousActiveEntry(mActiveEntry.release());
11276 if (previousActiveEntry) {
11277 // Link this entry to the previous active entry.
11278 mActiveEntry = MakeUnique<SessionHistoryInfo>(*previousActiveEntry, aURI);
11279 } else {
11280 Document* doc = GetDocument();
11281 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", "./../../../docshell/base/nsDocShell.cpp"
, 11281); AnnotateMozCrashReason("MOZ_ASSERT" "(" "doc" ")");
do { MOZ_CrashSequence(__null, 11281); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
11282 mActiveEntry = MakeUnique<SessionHistoryInfo>(
11283 aURI, aTriggeringPrincipal, doc->NodePrincipal(), nullptr,
11284 aPolicyContainer, mContentTypeHint);
11285 }
11286 mActiveEntry->SetOriginalURI(aOriginalURI);
11287 mActiveEntry->SetUnstrippedURI(nullptr);
11288 mActiveEntry->SetReferrerInfo(aReferrerInfo);
11289 mActiveEntry->SetTitle(aTitle);
11290 mActiveEntry->SetStateData(static_cast<nsStructuredCloneContainer*>(aData));
11291 mActiveEntry->SetURIWasModified(aURIWasModified);
11292 mActiveEntry->SetScrollRestorationIsManual(aScrollRestorationIsManual);
11293
11294 if (replace) {
11295 mActiveEntry->NavigationKey() = previousActiveEntry->NavigationKey();
11296 mBrowsingContext->ReplaceActiveSessionHistoryEntry(mActiveEntry.get());
11297 } else {
11298 mBrowsingContext->IncrementHistoryEntryCountForBrowsingContext();
11299 // FIXME We should probably just compute mChildOffset in the parent
11300 // instead of passing it over IPC here.
11301 mBrowsingContext->SetActiveSessionHistoryEntry(
11302 aPreviousScrollPos, mActiveEntry.get(), previousActiveEntry.get(),
11303 mLoadType,
11304 /* aCacheKey = */ 0);
11305 // FIXME Do we need to update mPreviousEntryIndex and mLoadedEntryIndex?
11306 }
11307}
11308
11309nsresult nsDocShell::LoadHistoryEntry(const LoadingSessionHistoryInfo& aEntry,
11310 uint32_t aLoadType, bool aUserActivation,
11311 bool aNotifiedBeforeUnloadListeners,
11312 bool aIsResumingInterceptedNavigation) {
11313 RefPtr<nsDocShellLoadState> loadState = aEntry.CreateLoadInfo();
11314 loadState->SetHasValidUserGestureActivation(
11315 loadState->HasValidUserGestureActivation() || aUserActivation);
11316
11317 loadState->SetTextDirectiveUserActivation(
11318 loadState->GetTextDirectiveUserActivation() || aUserActivation);
11319
11320 loadState->SetNotifiedBeforeUnloadListeners(aNotifiedBeforeUnloadListeners);
11321
11322 loadState->SetIsResumingInterceptedNavigation(
11323 aIsResumingInterceptedNavigation);
11324
11325 return LoadHistoryEntry(loadState, aLoadType, aEntry.mLoadingCurrentEntry);
11326}
11327
11328void nsDocShell::MaybeFireTraverseHistory(nsDocShellLoadState* aLoadState) {
11329 if (!Navigation::IsAPIEnabled()) {
11330 return;
11331 }
11332
11333 BrowsingContext* browsingContext = GetBrowsingContext();
11334 if (!browsingContext || browsingContext->IsTop()) {
11335 return;
11336 }
11337
11338 if (!mActiveEntry || !aLoadState->GetLoadingSessionHistoryInfo() ||
11339 aLoadState->IsResumingInterceptedNavigation()) {
11340 return;
11341 }
11342 if (mActiveEntry->NavigationKey() ==
11343 aLoadState->GetLoadingSessionHistoryInfo()->mInfo.NavigationKey()) {
11344 return;
11345 }
11346
11347 nsCOMPtr activeURI = mActiveEntry->GetURIOrInheritedForAboutBlank();
11348 nsCOMPtr<nsIURI> loadingURI = aLoadState->GetLoadingSessionHistoryInfo()
11349 ->mInfo.GetURIOrInheritedForAboutBlank();
11350 if (NS_FAILED(nsContentUtils::GetSecurityManager()->CheckSameOriginURI(((bool)(__builtin_expect(!!(NS_FAILED_impl(nsContentUtils::GetSecurityManager
()->CheckSameOriginURI( activeURI, loadingURI, false, false
))), 0)))
11351 activeURI, loadingURI,((bool)(__builtin_expect(!!(NS_FAILED_impl(nsContentUtils::GetSecurityManager
()->CheckSameOriginURI( activeURI, loadingURI, false, false
))), 0)))
11352 /*reportError=*/false,((bool)(__builtin_expect(!!(NS_FAILED_impl(nsContentUtils::GetSecurityManager
()->CheckSameOriginURI( activeURI, loadingURI, false, false
))), 0)))
11353 /*fromPrivateWindow=*/false))((bool)(__builtin_expect(!!(NS_FAILED_impl(nsContentUtils::GetSecurityManager
()->CheckSameOriginURI( activeURI, loadingURI, false, false
))), 0)))
) {
11354 return;
11355 }
11356
11357 if (RefPtr window = GetActiveWindow()) {
11358 if (RefPtr navigation = window->Navigation()) {
11359 if (AutoJSAPI jsapi; jsapi.Init(window)) {
11360 // This should send the correct user involvment. See bug 1903552.
11361 navigation->FireTraverseNavigateEvent(jsapi.cx(), aLoadState,
11362 Nothing());
11363 }
11364 }
11365 }
11366}
11367
11368nsIDocumentViewer::PermitUnloadResult
11369nsDocShell::MaybeFireTraversableTraverseHistory(
11370 nsDocShellLoadState* aLoadState,
11371 Maybe<UserNavigationInvolvement> aUserInvolvement) {
11372 MOZ_DIAGNOSTIC_ASSERT(GetBrowsingContext())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(GetBrowsingContext())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(GetBrowsingContext()))), 0))
) { do { } while (false); MOZ_ReportAssertionFailure("GetBrowsingContext()"
, "./../../../docshell/base/nsDocShell.cpp", 11372); AnnotateMozCrashReason
("MOZ_DIAGNOSTIC_ASSERT" "(" "GetBrowsingContext()" ")"); do {
MOZ_CrashSequence(__null, 11372); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
11373 MOZ_DIAGNOSTIC_ASSERT(GetBrowsingContext()->IsTop())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(GetBrowsingContext()->IsTop())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(GetBrowsingContext()->IsTop
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("GetBrowsingContext()->IsTop()", "./../../../docshell/base/nsDocShell.cpp"
, 11373); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "GetBrowsingContext()->IsTop()"
")"); do { MOZ_CrashSequence(__null, 11373); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11374
11375 SetOngoingNavigation(Some(OngoingNavigation::Traversal));
11376
11377 nsIDocumentViewer::PermitUnloadResult finalStatus =
11378 nsIDocumentViewer::eContinue;
11379 if (RefPtr<nsPIDOMWindowInner> activeWindow = GetActiveWindow()) {
11380 if (RefPtr navigation = activeWindow->Navigation()) {
11381 if (AutoJSAPI jsapi; jsapi.Init(activeWindow)) {
11382 bool shouldContinue = navigation->FireTraverseNavigateEvent(
11383 jsapi.cx(), aLoadState, aUserInvolvement);
11384
11385 if (!shouldContinue) {
11386 finalStatus = nsIDocumentViewer::eCanceledByNavigate;
11387 }
11388 }
11389 }
11390 }
11391
11392 return finalStatus;
11393}
11394
11395nsresult nsDocShell::LoadHistoryEntry(nsDocShellLoadState* aLoadState,
11396 uint32_t aLoadType,
11397 bool aLoadingCurrentEntry) {
11398 if (!IsNavigationAllowed()) {
11399 return NS_OK;
11400 }
11401
11402 // https://html.spec.whatwg.org/#navigate-to-a-javascript:-url
11403 // Step 13: historyEntry should store entryToReplace's URL.
11404 if (aLoadState->URI()->SchemeIs("javascript")) {
11405 MOZ_ASSERT_UNREACHABLE("javascript: URIs should not enter session history")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: "
"javascript: URIs should not enter session history" ")", "./../../../docshell/base/nsDocShell.cpp"
, 11405); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "javascript: URIs should not enter session history"
")"); do { MOZ_CrashSequence(__null, 11405); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11406 return NS_ERROR_FAILURE;
11407 }
11408
11409 // We are setting load type afterwards so we don't have to
11410 // send it in an IPC message
11411 aLoadState->SetLoadType(aLoadType);
11412
11413 SetOngoingNavigation(Some(OngoingNavigation::Traversal));
11414
11415 /* If there is a valid postdata *and* the user pressed
11416 * reload or shift-reload, take user's permission before we
11417 * repost the data to the server.
11418 */
11419 if ((aLoadType & LOAD_CMD_RELOAD) && aLoadState->PostDataStream()) {
11420 bool repost;
11421 nsresult rv = ConfirmRepost(&repost);
11422 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
11423 return rv;
11424 }
11425
11426 // If the user pressed cancel in the dialog, return. We're done here.
11427 if (!repost) {
11428 return NS_BINDING_ABORTED;
11429 }
11430 }
11431
11432 // If there is no valid triggeringPrincipal, we deny the load
11433 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"
")", "./../../../docshell/base/nsDocShell.cpp", 11434); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aLoadState->TriggeringPrincipal()" ") ("
"need a valid triggeringPrincipal to load from history" ")")
; do { MOZ_CrashSequence(__null, 11434); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
11434 "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"
")", "./../../../docshell/base/nsDocShell.cpp", 11434); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aLoadState->TriggeringPrincipal()" ") ("
"need a valid triggeringPrincipal to load from history" ")")
; do { MOZ_CrashSequence(__null, 11434); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
11435 if (!aLoadState->TriggeringPrincipal()) {
11436 return NS_ERROR_FAILURE;
11437 }
11438
11439 MaybeFireTraverseHistory(aLoadState);
11440
11441 return InternalLoad(aLoadState); // No nsIRequest
11442}
11443
11444NS_IMETHODIMPnsresult
11445nsDocShell::PersistLayoutHistoryState() {
11446 nsresult rv = NS_OK;
11447
11448 if (mActiveEntry) {
11449 bool scrollRestorationIsManual =
11450 mActiveEntry->GetScrollRestorationIsManual();
11451 nsCOMPtr<nsILayoutHistoryState> layoutState;
11452 if (RefPtr<PresShell> presShell = GetPresShell()) {
11453 rv = presShell->CaptureHistoryState(getter_AddRefs(layoutState));
11454 } else if (scrollRestorationIsManual) {
11455 // Even if we don't have layout anymore, we may want to reset the
11456 // current scroll state in layout history.
11457 GetLayoutHistoryState(getter_AddRefs(layoutState));
11458 }
11459
11460 if (scrollRestorationIsManual && layoutState) {
11461 layoutState->ResetScrollState();
11462 }
11463 }
11464
11465 return rv;
11466}
11467
11468already_AddRefed<ChildSHistory> nsDocShell::GetRootSessionHistory() {
11469 RefPtr<ChildSHistory> childSHistory =
11470 mBrowsingContext->Top()->GetChildSessionHistory();
11471 return childSHistory.forget();
11472}
11473
11474nsresult nsDocShell::GetHttpChannel(nsIChannel* aChannel,
11475 nsIHttpChannel** aReturn) {
11476 NS_ENSURE_ARG_POINTER(aReturn)do { if ((__builtin_expect(!!(!(aReturn)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aReturn" ") failed", nullptr
, "./../../../docshell/base/nsDocShell.cpp", 11476); return NS_ERROR_INVALID_POINTER
; } } while (false)
;
11477 if (!aChannel) {
11478 return NS_ERROR_FAILURE;
11479 }
11480
11481 nsCOMPtr<nsIMultiPartChannel> multiPartChannel(do_QueryInterface(aChannel));
11482 if (multiPartChannel) {
11483 nsCOMPtr<nsIChannel> baseChannel;
11484 multiPartChannel->GetBaseChannel(getter_AddRefs(baseChannel));
11485 nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(baseChannel));
11486 *aReturn = httpChannel;
11487 NS_IF_ADDREF(*aReturn)ns_if_addref(*aReturn);
11488 }
11489 return NS_OK;
11490}
11491
11492bool nsDocShell::ShouldDiscardLayoutState(nsIHttpChannel* aChannel) {
11493 // By default layout State will be saved.
11494 if (!aChannel) {
11495 return false;
11496 }
11497
11498 // figure out if SH should be saving layout state
11499 bool noStore = false;
11500 (void)aChannel->IsNoStoreResponse(&noStore);
11501 return noStore;
11502}
11503
11504NS_IMETHODIMPnsresult
11505nsDocShell::GetEditor(nsIEditor** aEditor) {
11506 NS_ENSURE_ARG_POINTER(aEditor)do { if ((__builtin_expect(!!(!(aEditor)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aEditor" ") failed", nullptr
, "./../../../docshell/base/nsDocShell.cpp", 11506); return NS_ERROR_INVALID_POINTER
; } } while (false)
;
11507 RefPtr<HTMLEditor> htmlEditor = GetHTMLEditorInternal();
11508 htmlEditor.forget(aEditor);
11509 return NS_OK;
11510}
11511
11512NS_IMETHODIMPnsresult
11513nsDocShell::SetEditor(nsIEditor* aEditor) {
11514 HTMLEditor* htmlEditor = aEditor ? aEditor->GetAsHTMLEditor() : nullptr;
11515 // If TextEditor comes, throw an error.
11516 if (aEditor && !htmlEditor) {
11517 return NS_ERROR_INVALID_ARG;
11518 }
11519 return SetHTMLEditorInternal(htmlEditor);
11520}
11521
11522HTMLEditor* nsDocShell::GetHTMLEditorInternal() {
11523 return mEditorData ? mEditorData->GetHTMLEditor() : nullptr;
11524}
11525
11526nsresult nsDocShell::SetHTMLEditorInternal(HTMLEditor* aHTMLEditor) {
11527 if (!aHTMLEditor && !mEditorData) {
11528 return NS_OK;
11529 }
11530
11531 nsresult rv = EnsureEditorData();
11532 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
11533 return rv;
11534 }
11535
11536 return mEditorData->SetHTMLEditor(aHTMLEditor);
11537}
11538
11539NS_IMETHODIMPnsresult
11540nsDocShell::GetEditable(bool* aEditable) {
11541 NS_ENSURE_ARG_POINTER(aEditable)do { if ((__builtin_expect(!!(!(aEditable)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aEditable" ") failed", nullptr
, "./../../../docshell/base/nsDocShell.cpp", 11541); return NS_ERROR_INVALID_POINTER
; } } while (false)
;
11542 *aEditable = mEditorData && mEditorData->GetEditable();
11543 return NS_OK;
11544}
11545
11546NS_IMETHODIMPnsresult
11547nsDocShell::GetHasEditingSession(bool* aHasEditingSession) {
11548 NS_ENSURE_ARG_POINTER(aHasEditingSession)do { if ((__builtin_expect(!!(!(aHasEditingSession)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aHasEditingSession" ") failed"
, nullptr, "./../../../docshell/base/nsDocShell.cpp", 11548);
return NS_ERROR_INVALID_POINTER; } } while (false)
;
11549
11550 if (mEditorData) {
11551 *aHasEditingSession = !!mEditorData->GetEditingSession();
11552 } else {
11553 *aHasEditingSession = false;
11554 }
11555
11556 return NS_OK;
11557}
11558
11559NS_IMETHODIMPnsresult
11560nsDocShell::MakeEditable(bool aInWaitForUriLoad) {
11561 nsresult rv = EnsureEditorData();
11562 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
11563 return rv;
11564 }
11565
11566 return mEditorData->MakeEditable(aInWaitForUriLoad);
11567}
11568
11569/* static */ bool nsDocShell::ShouldAddURIVisit(nsIChannel* aChannel) {
11570 bool needToAddURIVisit = true;
11571 nsCOMPtr<nsIPropertyBag2> props(do_QueryInterface(aChannel));
11572 if (props) {
11573 (void)props->GetPropertyAsBool(u"docshell.needToAddURIVisit"_ns,
11574 &needToAddURIVisit);
11575 }
11576
11577 return needToAddURIVisit;
11578}
11579
11580/* static */ void nsDocShell::ExtractLastVisit(
11581 nsIChannel* aChannel, nsIURI** aURI, uint32_t* aChannelRedirectFlags) {
11582 nsCOMPtr<nsIPropertyBag2> props(do_QueryInterface(aChannel));
11583 if (!props) {
11584 return;
11585 }
11586
11587 nsresult rv;
11588 nsCOMPtr<nsIURI> uri(do_GetProperty(props, u"docshell.previousURI"_ns, &rv));
11589 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
11590 uri.forget(aURI);
11591
11592 rv = props->GetPropertyAsUint32(u"docshell.previousFlags"_ns,
11593 aChannelRedirectFlags);
11594
11595 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)", "./../../../docshell/base/nsDocShell.cpp"
, 11597); } } while (false)
11596 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)", "./../../../docshell/base/nsDocShell.cpp"
, 11597); } } while (false)
11597 "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)", "./../../../docshell/base/nsDocShell.cpp"
, 11597); } } while (false)
;
11598
11599 } else {
11600 // There is no last visit for this channel, so this must be the first
11601 // link. Link the visit to the referrer of this request, if any.
11602 // Treat referrer as null if there is an error getting it.
11603 NS_GetReferrerFromChannel(aChannel, aURI);
11604 }
11605}
11606
11607void nsDocShell::SaveLastVisit(nsIChannel* aChannel, nsIURI* aURI,
11608 uint32_t aChannelRedirectFlags) {
11609 nsCOMPtr<nsIWritablePropertyBag2> props(do_QueryInterface(aChannel));
11610 if (!props || !aURI) {
11611 return;
11612 }
11613
11614 props->SetPropertyAsInterface(u"docshell.previousURI"_ns, aURI);
11615 props->SetPropertyAsUint32(u"docshell.previousFlags"_ns,
11616 aChannelRedirectFlags);
11617}
11618
11619/* static */ void nsDocShell::InternalAddURIVisit(
11620 nsIURI* aURI, nsIURI* aPreviousURI, uint32_t aChannelRedirectFlags,
11621 uint32_t aResponseStatus, BrowsingContext* aBrowsingContext,
11622 nsIWidget* aWidget, uint32_t aLoadType, bool aWasUpgraded, bool aIsPost) {
11623 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!"
")", "./../../../docshell/base/nsDocShell.cpp", 11623); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aURI" ") (" "Visited URI is null!" ")"); do
{ MOZ_CrashSequence(__null, 11623); __attribute__((nomerge))
::abort(); } while (false); } } while (false)
;
11624 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" ")"
, "./../../../docshell/base/nsDocShell.cpp", 11625); 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, 11625); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
11625 "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" ")"
, "./../../../docshell/base/nsDocShell.cpp", 11625); 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, 11625); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
11626
11627 bool usePrivateBrowsing = false;
11628 aBrowsingContext->GetUsePrivateBrowsing(&usePrivateBrowsing);
11629
11630 // Only content-type docshells save URI visits. Also don't do
11631 // anything here if we're not supposed to use global history.
11632 if (!aBrowsingContext->IsContent() ||
11633 !aBrowsingContext->GetUseGlobalHistory() || usePrivateBrowsing) {
11634 return;
11635 }
11636
11637 nsCOMPtr<IHistory> history = components::History::Service();
11638
11639 if (history) {
11640 uint32_t visitURIFlags = 0;
11641
11642 if (aBrowsingContext->IsTop()) {
11643 visitURIFlags |= IHistory::TOP_LEVEL;
11644 }
11645
11646 if (aChannelRedirectFlags & nsIChannelEventSink::REDIRECT_TEMPORARY) {
11647 visitURIFlags |= IHistory::REDIRECT_TEMPORARY;
11648 } else if (aChannelRedirectFlags &
11649 nsIChannelEventSink::REDIRECT_PERMANENT) {
11650 visitURIFlags |= IHistory::REDIRECT_PERMANENT;
11651 } else {
11652 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." ")", "./../../../docshell/base/nsDocShell.cpp"
, 11654); 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, 11654); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
11653 "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." ")", "./../../../docshell/base/nsDocShell.cpp"
, 11654); 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, 11654); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
11654 "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." ")", "./../../../docshell/base/nsDocShell.cpp"
, 11654); 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, 11654); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
11655 }
11656
11657 if (aResponseStatus >= 300 && aResponseStatus < 400) {
11658 visitURIFlags |= IHistory::REDIRECT_SOURCE;
11659 if (aResponseStatus == 301 || aResponseStatus == 308) {
11660 visitURIFlags |= IHistory::REDIRECT_SOURCE_PERMANENT;
11661 }
11662 }
11663 // Errors 400-501 and 505 are considered unrecoverable, in the sense a
11664 // simple retry attempt by the user is unlikely to solve them.
11665 // 408 is special cased, since may actually indicate a temporary
11666 // connection problem.
11667 else if (aResponseStatus != 408 &&
11668 ((aResponseStatus >= 400 && aResponseStatus <= 501) ||
11669 aResponseStatus == 505)) {
11670 visitURIFlags |= IHistory::UNRECOVERABLE_ERROR;
11671 }
11672
11673 if (aWasUpgraded) {
11674 visitURIFlags |=
11675 IHistory::REDIRECT_SOURCE | IHistory::REDIRECT_SOURCE_UPGRADED;
11676 }
11677
11678 if (aIsPost) {
11679 visitURIFlags |= IHistory::SOURCE_IS_POST_RESPONSE;
11680 }
11681
11682 (void)history->VisitURI(aWidget, aURI, aPreviousURI, visitURIFlags,
11683 aBrowsingContext->BrowserId());
11684 }
11685}
11686
11687void nsDocShell::AddURIVisit(nsIURI* aURI, nsIURI* aPreviousURI,
11688 uint32_t aChannelRedirectFlags,
11689 uint32_t aResponseStatus, bool aIsPost) {
11690 nsPIDOMWindowOuter* outer = GetWindow();
11691 nsCOMPtr<nsIWidget> widget = widget::WidgetUtils::DOMWindowToWidget(outer);
11692
11693 InternalAddURIVisit(aURI, aPreviousURI, aChannelRedirectFlags,
11694 aResponseStatus, mBrowsingContext, widget, mLoadType,
11695 false, aIsPost);
11696}
11697
11698//*****************************************************************************
11699// nsDocShell: Helper Routines
11700//*****************************************************************************
11701
11702NS_IMETHODIMPnsresult
11703nsDocShell::SetLoadType(uint32_t aLoadType) {
11704 mLoadType = aLoadType;
11705 return NS_OK;
11706}
11707
11708NS_IMETHODIMPnsresult
11709nsDocShell::GetLoadType(uint32_t* aLoadType) {
11710 *aLoadType = mLoadType;
11711 return NS_OK;
11712}
11713
11714nsresult nsDocShell::ConfirmRepost(bool* aRepost) {
11715 if (StaticPrefs::dom_confirm_repost_testing_always_accept()) {
11716 *aRepost = true;
11717 return NS_OK;
11718 }
11719
11720 nsCOMPtr<nsIPromptCollection> prompter =
11721 do_GetService("@mozilla.org/embedcomp/prompt-collection;1");
11722 if (!prompter) {
11723 return NS_ERROR_NOT_AVAILABLE;
11724 }
11725
11726 return prompter->ConfirmRepost(mBrowsingContext, aRepost);
11727}
11728
11729nsresult nsDocShell::GetPromptAndStringBundle(nsIPrompt** aPrompt,
11730 nsIStringBundle** aStringBundle) {
11731 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, "./../../../docshell/base/nsDocShell.cpp"
, 11732); return NS_ERROR_FAILURE; } } while (false)
11732 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, "./../../../docshell/base/nsDocShell.cpp"
, 11732); return NS_ERROR_FAILURE; } } while (false)
;
11733
11734 nsCOMPtr<nsIStringBundleService> stringBundleService =
11735 mozilla::components::StringBundle::Service();
11736 NS_ENSURE_TRUE(stringBundleService, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(stringBundleService)), 0))) {
NS_DebugBreak(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "stringBundleService"
") failed", nullptr, "./../../../docshell/base/nsDocShell.cpp"
, 11736); return NS_ERROR_FAILURE; } } while (false)
;
11737
11738 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, "./../../../docshell/base/nsDocShell.cpp"
, 11740); return NS_ERROR_FAILURE; } } while (false)
11739 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, "./../../../docshell/base/nsDocShell.cpp"
, 11740); return NS_ERROR_FAILURE; } } while (false)
11740 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, "./../../../docshell/base/nsDocShell.cpp"
, 11740); return NS_ERROR_FAILURE; } } while (false)
;
11741
11742 return NS_OK;
11743}
11744
11745ScrollContainerFrame* nsDocShell::GetRootScrollContainerFrame() {
11746 PresShell* presShell = GetPresShell();
11747 NS_ENSURE_TRUE(presShell, nullptr)do { if ((__builtin_expect(!!(!(presShell)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "presShell" ") failed", nullptr
, "./../../../docshell/base/nsDocShell.cpp", 11747); return nullptr
; } } while (false)
;
11748
11749 return presShell->GetRootScrollContainerFrame();
11750}
11751
11752nsresult nsDocShell::EnsureScriptEnvironment() {
11753 if (mScriptGlobal) {
11754 return NS_OK;
11755 }
11756
11757 if (mIsBeingDestroyed) {
11758 return NS_ERROR_NOT_AVAILABLE;
11759 }
11760
11761#ifdef DEBUG1
11762 NS_ASSERTION(!mInEnsureScriptEnv,do { if (!(!mInEnsureScriptEnv)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "Infinite loop! Calling EnsureScriptEnvironment() from " "within EnsureScriptEnvironment()!"
, "!mInEnsureScriptEnv", "./../../../docshell/base/nsDocShell.cpp"
, 11764); MOZ_PretendNoReturn(); } } while (0)
11763 "Infinite loop! Calling EnsureScriptEnvironment() from "do { if (!(!mInEnsureScriptEnv)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "Infinite loop! Calling EnsureScriptEnvironment() from " "within EnsureScriptEnvironment()!"
, "!mInEnsureScriptEnv", "./../../../docshell/base/nsDocShell.cpp"
, 11764); MOZ_PretendNoReturn(); } } while (0)
11764 "within EnsureScriptEnvironment()!")do { if (!(!mInEnsureScriptEnv)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "Infinite loop! Calling EnsureScriptEnvironment() from " "within EnsureScriptEnvironment()!"
, "!mInEnsureScriptEnv", "./../../../docshell/base/nsDocShell.cpp"
, 11764); MOZ_PretendNoReturn(); } } while (0)
;
11765
11766 // Yeah, this isn't re-entrant safe, but that's ok since if we
11767 // re-enter this method, we'll infinitely loop...
11768 AutoRestore<bool> boolSetter(mInEnsureScriptEnv);
11769 mInEnsureScriptEnv = true;
11770#endif
11771
11772 nsCOMPtr<nsIWebBrowserChrome> browserChrome(do_GetInterface(mTreeOwner));
11773 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, "./../../../docshell/base/nsDocShell.cpp", 11773);
return NS_ERROR_NOT_AVAILABLE; } } while (false)
;
11774
11775 uint32_t chromeFlags;
11776 browserChrome->GetChromeFlags(&chromeFlags);
11777
11778 // If our window is modal and we're not opened as chrome, make
11779 // this window a modal content window.
11780 mScriptGlobal = nsGlobalWindowOuter::Create(this, mItemType == typeChrome);
11781 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",
"./../../../docshell/base/nsDocShell.cpp", 11781); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "mScriptGlobal" ")"); do { MOZ_CrashSequence
(__null, 11781); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
11782
11783 // Ensure the script object is set up to run script.
11784 return mScriptGlobal->EnsureScriptEnvironment();
11785}
11786
11787nsresult nsDocShell::EnsureEditorData() {
11788 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"
, "./../../../docshell/base/nsDocShell.cpp", 11788); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!mIsBeingDestroyed" ")"); do { MOZ_CrashSequence
(__null, 11788); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
11789
11790 bool openDocHasDetachedEditor = false;
11791 if (!mEditorData && !mIsBeingDestroyed && !openDocHasDetachedEditor) {
11792 // We shouldn't recreate the editor data if it already exists, or
11793 // we're shutting down, or we already have a detached editor data
11794 // stored in the session history. We should only have one editordata
11795 // per docshell.
11796 mEditorData = MakeUnique<nsDocShellEditorData>(this);
11797 }
11798
11799 return mEditorData ? NS_OK : NS_ERROR_NOT_AVAILABLE;
11800}
11801
11802nsresult nsDocShell::EnsureFind() {
11803 if (!mFind) {
11804 mFind = MakeRefPtr<nsWebBrowserFind>();
11805 }
11806
11807 // we promise that the nsIWebBrowserFind that we return has been set
11808 // up to point to the focused, or content window, so we have to
11809 // set that up each time.
11810
11811 nsIScriptGlobalObject* scriptGO = GetScriptGlobalObject();
11812 NS_ENSURE_TRUE(scriptGO, NS_ERROR_UNEXPECTED)do { if ((__builtin_expect(!!(!(scriptGO)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "scriptGO" ") failed", nullptr
, "./../../../docshell/base/nsDocShell.cpp", 11812); return NS_ERROR_UNEXPECTED
; } } while (false)
;
11813
11814 // default to our window
11815 nsCOMPtr<nsPIDOMWindowOuter> ourWindow = do_QueryInterface(scriptGO);
11816 nsCOMPtr<nsPIDOMWindowOuter> windowToSearch;
11817 nsFocusManager::GetFocusedDescendant(ourWindow,
11818 nsFocusManager::eIncludeAllDescendants,
11819 getter_AddRefs(windowToSearch));
11820
11821 nsCOMPtr<nsIWebBrowserFindInFrames> findInFrames = do_QueryInterface(mFind);
11822 if (!findInFrames) {
11823 return NS_ERROR_NO_INTERFACE;
11824 }
11825
11826 nsresult rv = findInFrames->SetRootSearchFrame(ourWindow);
11827 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
11828 return rv;
11829 }
11830 rv = findInFrames->SetCurrentSearchFrame(windowToSearch);
11831 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
11832 return rv;
11833 }
11834
11835 return NS_OK;
11836}
11837
11838NS_IMETHODIMPnsresult
11839nsDocShell::IsBeingDestroyed(bool* aDoomed) {
11840 NS_ENSURE_ARG(aDoomed)do { if ((__builtin_expect(!!(!(aDoomed)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aDoomed" ") failed", nullptr
, "./../../../docshell/base/nsDocShell.cpp", 11840); return NS_ERROR_INVALID_ARG
; } } while (false)
;
11841 *aDoomed = mIsBeingDestroyed;
11842 return NS_OK;
11843}
11844
11845NS_IMETHODIMPnsresult
11846nsDocShell::GetIsExecutingOnLoadHandler(bool* aResult) {
11847 NS_ENSURE_ARG(aResult)do { if ((__builtin_expect(!!(!(aResult)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aResult" ") failed", nullptr
, "./../../../docshell/base/nsDocShell.cpp", 11847); return NS_ERROR_INVALID_ARG
; } } while (false)
;
11848 *aResult = mIsExecutingOnLoadHandler;
11849 return NS_OK;
11850}
11851
11852NS_IMETHODIMPnsresult
11853nsDocShell::GetLayoutHistoryState(nsILayoutHistoryState** aLayoutHistoryState) {
11854 nsCOMPtr<nsILayoutHistoryState> state;
11855 if (mActiveEntry) {
11856 state = mActiveEntry->GetLayoutHistoryState();
11857 }
11858 state.forget(aLayoutHistoryState);
11859 return NS_OK;
11860}
11861
11862NS_IMETHODIMPnsresult
11863nsDocShell::SetLayoutHistoryState(nsILayoutHistoryState* aLayoutHistoryState) {
11864 if (mActiveEntry) {
11865 mActiveEntry->SetLayoutHistoryState(aLayoutHistoryState);
11866 }
11867 return NS_OK;
11868}
11869
11870nsDocShell::InterfaceRequestorProxy::InterfaceRequestorProxy(
11871 nsIInterfaceRequestor* aRequestor) {
11872 if (aRequestor) {
11873 mWeakPtr = do_GetWeakReference(aRequestor);
11874 }
11875}
11876
11877nsDocShell::InterfaceRequestorProxy::~InterfaceRequestorProxy() {
11878 mWeakPtr = nullptr;
11879}
11880
11881NS_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" ")", "./../../../docshell/base/nsDocShell.cpp"
, 11881); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { MOZ_CrashSequence(__null, 11881
); __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" ")", "./../../../docshell/base/nsDocShell.cpp"
, 11881); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"nsDocShell::InterfaceRequestorProxy\" != nullptr"
") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__null
, 11881); __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" ")", "./../../../docshell/base/nsDocShell.cpp"
, 11881); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { MOZ_CrashSequence(__null, 11881
); __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" ")", "./../../../docshell/base/nsDocShell.cpp"
, 11881); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"nsDocShell::InterfaceRequestorProxy\" != nullptr"
") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__null
, 11881); __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"
, "./../../../docshell/base/nsDocShell.cpp", 11881); 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; }
11882
11883NS_IMETHODIMPnsresult
11884nsDocShell::InterfaceRequestorProxy::GetInterface(const nsIID& aIID,
11885 void** aSink) {
11886 NS_ENSURE_ARG_POINTER(aSink)do { if ((__builtin_expect(!!(!(aSink)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aSink" ") failed", nullptr
, "./../../../docshell/base/nsDocShell.cpp", 11886); return NS_ERROR_INVALID_POINTER
; } } while (false)
;
11887 nsCOMPtr<nsIInterfaceRequestor> ifReq = do_QueryReferent(mWeakPtr);
11888 if (ifReq) {
11889 return ifReq->GetInterface(aIID, aSink);
11890 }
11891 *aSink = nullptr;
11892 return NS_NOINTERFACE;
11893}
11894
11895//*****************************************************************************
11896// nsDocShell::nsIAuthPromptProvider
11897//*****************************************************************************
11898
11899NS_IMETHODIMPnsresult
11900nsDocShell::GetAuthPrompt(uint32_t aPromptReason, const nsIID& aIID,
11901 void** aResult) {
11902 // a priority prompt request will override a false mAllowAuth setting
11903 bool priorityPrompt = (aPromptReason == PROMPT_PROXY);
11904
11905 if (!mAllowAuth && !priorityPrompt) {
11906 return NS_ERROR_NOT_AVAILABLE;
11907 }
11908
11909 // we're either allowing auth, or it's a proxy request
11910 nsresult rv;
11911 nsCOMPtr<nsIPromptFactory> wwatch =
11912 do_GetService(NS_WINDOWWATCHER_CONTRACTID"@mozilla.org/embedcomp/window-watcher;1", &rv);
11913 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, "./../../../docshell/base/nsDocShell.cpp"
, 11913); return rv; } } while (false)
;
11914
11915 rv = EnsureScriptEnvironment();
11916 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, "./../../../docshell/base/nsDocShell.cpp"
, 11916); return rv; } } while (false)
;
11917
11918 // Get the an auth prompter for our window so that the parenting
11919 // of the dialogs works as it should when using tabs.
11920
11921 return wwatch->GetPrompt(mScriptGlobal, aIID,
11922 reinterpret_cast<void**>(aResult));
11923}
11924
11925//*****************************************************************************
11926// nsDocShell::nsILoadContext
11927//*****************************************************************************
11928
11929NS_IMETHODIMPnsresult
11930nsDocShell::GetAssociatedWindow(mozIDOMWindowProxy** aWindow) {
11931 CallGetInterface(this, aWindow);
11932 return NS_OK;
11933}
11934
11935NS_IMETHODIMPnsresult
11936nsDocShell::GetTopWindow(mozIDOMWindowProxy** aWindow) {
11937 return mBrowsingContext->GetTopWindow(aWindow);
11938}
11939
11940NS_IMETHODIMPnsresult
11941nsDocShell::GetTopFrameElement(Element** aElement) {
11942 return mBrowsingContext->GetTopFrameElement(aElement);
11943}
11944
11945NS_IMETHODIMPnsresult
11946nsDocShell::GetUseTrackingProtection(bool* aUseTrackingProtection) {
11947 return mBrowsingContext->GetUseTrackingProtection(aUseTrackingProtection);
11948}
11949
11950NS_IMETHODIMPnsresult
11951nsDocShell::SetUseTrackingProtection(bool aUseTrackingProtection) {
11952 return mBrowsingContext->SetUseTrackingProtection(aUseTrackingProtection);
11953}
11954
11955NS_IMETHODIMPnsresult
11956nsDocShell::GetIsContent(bool* aIsContent) {
11957 *aIsContent = (mItemType == typeContent);
11958 return NS_OK;
11959}
11960
11961bool nsDocShell::IsOKToLoadURI(nsIURI* aURI) {
11962 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!" ")"
, "./../../../docshell/base/nsDocShell.cpp", 11962); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aURI" ") (" "Must have a URI!" ")"); do { MOZ_CrashSequence
(__null, 11962); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
11963
11964 if (!mFiredUnloadEvent) {
11965 return true;
11966 }
11967
11968 if (!mLoadingURI) {
11969 return false;
11970 }
11971
11972 bool isPrivateWin = false;
11973 Document* doc = GetDocument();
11974 if (doc) {
11975 isPrivateWin =
11976 doc->NodePrincipal()->OriginAttributesRef().IsPrivateBrowsing();
11977 }
11978
11979 nsCOMPtr<nsIScriptSecurityManager> secMan =
11980 do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID"@mozilla.org/scriptsecuritymanager;1");
11981 return secMan && NS_SUCCEEDED(secMan->CheckSameOriginURI(((bool)(__builtin_expect(!!(!NS_FAILED_impl(secMan->CheckSameOriginURI
( aURI, mLoadingURI, false, isPrivateWin))), 1)))
11982 aURI, mLoadingURI, false, isPrivateWin))((bool)(__builtin_expect(!!(!NS_FAILED_impl(secMan->CheckSameOriginURI
( aURI, mLoadingURI, false, isPrivateWin))), 1)))
;
11983}
11984
11985//
11986// Routines for selection and clipboard
11987//
11988nsresult nsDocShell::GetControllerForCommand(const char* aCommand,
11989 nsIController** aResult) {
11990 NS_ENSURE_ARG_POINTER(aResult)do { if ((__builtin_expect(!!(!(aResult)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aResult" ") failed", nullptr
, "./../../../docshell/base/nsDocShell.cpp", 11990); return NS_ERROR_INVALID_POINTER
; } } while (false)
;
11991 *aResult = nullptr;
11992
11993 NS_ENSURE_TRUE(mScriptGlobal, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(mScriptGlobal)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "mScriptGlobal" ") failed"
, nullptr, "./../../../docshell/base/nsDocShell.cpp", 11993);
return NS_ERROR_FAILURE; } } while (false)
;
11994
11995 nsCOMPtr<nsPIWindowRoot> root = mScriptGlobal->GetTopWindowRoot();
11996 NS_ENSURE_TRUE(root, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(root)), 0))) { NS_DebugBreak(
NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "root" ") failed", nullptr
, "./../../../docshell/base/nsDocShell.cpp", 11996); return NS_ERROR_FAILURE
; } } while (false)
;
11997
11998 return root->GetControllerForCommand(aCommand, false /* for any window */,
11999 aResult);
12000}
12001
12002NS_IMETHODIMPnsresult
12003nsDocShell::IsCommandEnabled(const char* aCommand, bool* aResult) {
12004 NS_ENSURE_ARG_POINTER(aResult)do { if ((__builtin_expect(!!(!(aResult)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aResult" ") failed", nullptr
, "./../../../docshell/base/nsDocShell.cpp", 12004); return NS_ERROR_INVALID_POINTER
; } } while (false)
;
12005 *aResult = false;
12006
12007 nsresult rv = NS_ERROR_FAILURE;
12008
12009 nsCOMPtr<nsIController> controller;
12010 rv = GetControllerForCommand(aCommand, getter_AddRefs(controller));
12011 if (controller) {
12012 rv = controller->IsCommandEnabled(aCommand, aResult);
12013 }
12014
12015 return rv;
12016}
12017
12018NS_IMETHODIMPnsresult
12019nsDocShell::DoCommand(const char* aCommand) {
12020 nsresult rv = NS_ERROR_FAILURE;
12021
12022 nsCOMPtr<nsIController> controller;
12023 rv = GetControllerForCommand(aCommand, getter_AddRefs(controller));
12024 if (controller) {
12025 rv = controller->DoCommand(aCommand);
12026 }
12027
12028 return rv;
12029}
12030
12031NS_IMETHODIMPnsresult
12032nsDocShell::DoCommandWithParams(const char* aCommand,
12033 nsICommandParams* aParams) {
12034 nsCOMPtr<nsIController> controller;
12035 nsresult rv = GetControllerForCommand(aCommand, getter_AddRefs(controller));
12036 if (NS_WARN_IF(NS_FAILED(rv))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(rv
)), 0))), "NS_FAILED(rv)", "./../../../docshell/base/nsDocShell.cpp"
, 12036)
) {
12037 return rv;
12038 }
12039
12040 nsCOMPtr<nsICommandController> commandController =
12041 do_QueryInterface(controller, &rv);
12042 if (NS_WARN_IF(NS_FAILED(rv))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(rv
)), 0))), "NS_FAILED(rv)", "./../../../docshell/base/nsDocShell.cpp"
, 12042)
) {
12043 return rv;
12044 }
12045
12046 return commandController->DoCommandWithParams(aCommand, aParams);
12047}
12048
12049nsresult nsDocShell::EnsureCommandHandler() {
12050 if (!mCommandManager) {
12051 if (nsCOMPtr<nsPIDOMWindowOuter> domWindow = GetWindow()) {
12052 mCommandManager = MakeRefPtr<nsCommandManager>(domWindow);
12053 }
12054 }
12055 return mCommandManager ? NS_OK : NS_ERROR_FAILURE;
12056}
12057
12058// link handling
12059
12060class OnLinkClickEvent : public CancelableRunnable, public SupportsWeakPtr {
12061 public:
12062 OnLinkClickEvent(nsDocShell* aHandler, nsIContent* aContent,
12063 nsDocShellLoadState* aLoadState, bool aNoOpenerImplied,
12064 nsIPrincipal* aTriggeringPrincipal);
12065
12066 NS_IMETHODvirtual nsresult Run() override {
12067 if (mCancelled) {
12068 return NS_OK;
12069 }
12070
12071 // We need to set up an AutoJSAPI here for the following reason: When we
12072 // do OnLinkClickSync we'll eventually end up in
12073 // nsGlobalWindow::OpenInternal which only does popup blocking if
12074 // !LegacyIsCallerChromeOrNativeCode(). So we need to fake things so that
12075 // we don't look like native code as far as LegacyIsCallerNativeCode() is
12076 // concerned. (Bug 1930445)
12077 AutoJSAPI jsapi;
12078 if (jsapi.Init(mContent->OwnerDoc()->GetScopeObject())) {
12079 // For form submissions, the source element is set to the submitter,
12080 // and we don't want to overwrite it with the <form> element here.
12081 if (!mLoadState->HasSourceElement()) {
12082 mLoadState->SetSourceElement(mContent->AsElement());
12083 }
12084 mHandler->OnLinkClickSync(mContent, mLoadState, mNoOpenerImplied,
12085 mTriggeringPrincipal);
12086 }
12087 return NS_OK;
12088 }
12089
12090 nsresult Cancel() override final {
12091 mCancelled = true;
12092 // Don't clear mLoadState, etc. here since this can be called
12093 // from the OnLinkClickSync() above, and we might be holding
12094 // the last references to them.
12095 return NS_OK;
12096 }
12097
12098 private:
12099 RefPtr<nsDocShell> mHandler;
12100 nsCOMPtr<nsIContent> mContent;
12101 RefPtr<nsDocShellLoadState> mLoadState;
12102 nsCOMPtr<nsIPrincipal> mTriggeringPrincipal;
12103 bool mNoOpenerImplied;
12104 bool mCancelled = false;
12105};
12106
12107OnLinkClickEvent::OnLinkClickEvent(nsDocShell* aHandler, nsIContent* aContent,
12108 nsDocShellLoadState* aLoadState,
12109 bool aNoOpenerImplied,
12110 nsIPrincipal* aTriggeringPrincipal)
12111 : mozilla::CancelableRunnable("OnLinkClickEvent"),
12112 mHandler(aHandler),
12113 mContent(aContent),
12114 mLoadState(aLoadState),
12115 mTriggeringPrincipal(aTriggeringPrincipal),
12116 mNoOpenerImplied(aNoOpenerImplied) {}
12117
12118Result<RefPtr<OnLinkClickEvent>, nsresult> nsDocShell::OnLinkClickWithLoadState(
12119 nsIContent* aContent, nsDocShellLoadState* aLoadState,
12120 bool aNoOpenerImplied, nsIPrincipal* aTriggeringPrincipal) {
12121 if (StaticPrefs::dom_forms_submit_async_navigation()) {
12122 // Determine BC to target synchronously, for consistency with other browsers
12123 // (Guarding this behind dom.forms.submit_async_navigation since this change
12124 // is necessary for async form navigation, and it may cause regressions.)
12125 ComputeNamedTargetBrowsingContext(aLoadState);
12126 if (aContent->IsHTMLElement(nsGkAtoms::form)) {
12127 // https://html.spec.whatwg.org/#form-submission-algorithm
12128 // 25. If form document equals targetNavigable's active document, and form
12129 // document has not yet completely loaded, then set historyHandling to
12130 // "replace".
12131 const MaybeDiscarded<BrowsingContext>& bc =
12132 aLoadState->TargetBrowsingContext();
12133 Document* formDocument = aContent->OwnerDoc();
12134 if ((bc.IsNull() || bc == formDocument->GetBrowsingContext()) &&
12135 !formDocument->IsCompletelyLoaded()) {
12136 aLoadState->SetHistoryBehavior(NavigationHistoryBehavior::Replace);
12137 }
12138 }
12139 }
12140 RefPtr ev = MakeRefPtr<OnLinkClickEvent>(
12141 this, aContent, aLoadState, aNoOpenerImplied, aTriggeringPrincipal);
12142 RefPtr<nsIRunnable> runnable = ev;
12143 nsresult rv = Dispatch(runnable.forget());
12144 NS_ENSURE_SUCCESS(rv, Err(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", "Err(rv)", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "./../../../docshell/base/nsDocShell.cpp"
, 12144); return Err(rv); } } while (false)
;
12145 return ev;
12146}
12147
12148nsresult nsDocShell::OnFormSubmit(HTMLFormElement* aForm,
12149 nsDocShellLoadState* aLoadState) {
12150 // Need to do this here, since it's ordinarily done in OnLinkClick.
12151 if (ShouldBlockLoadingForBackButton()) {
12152 return NS_OK;
12153 }
12154 if (!StaticPrefs::dom_forms_submit_async_navigation()) {
12155 return OnLinkClickSync(aForm, aLoadState, false, aForm->NodePrincipal());
12156 }
12157
12158 auto result = OnLinkClickWithLoadState(aForm, aLoadState, false,
12159 aForm->NodePrincipal());
12160 if (result.isErr()) {
12161 return result.unwrapErr();
12162 }
12163 nsDocShell* targetDocShell = this;
12164 if (!aLoadState->Target().IsEmpty()) {
12165 const MaybeDiscarded<BrowsingContext>& targetBC =
12166 aLoadState->TargetBrowsingContext();
12167 targetDocShell =
12168 targetBC.IsNullOrDiscarded()
12169 ? nullptr
12170 : static_cast<nsDocShell*>(targetBC.get()->GetDocShell());
12171 }
12172 if (targetDocShell) {
12173 targetDocShell->CancelPlannedFormNavigation();
12174 // Chrome stops pending javascript: navigations here.
12175 // https://github.com/whatwg/html/issues/12607
12176 targetDocShell->StopPendingJavascriptURLNavigations();
12177 targetDocShell->mPlannedFormNavigation = result.unwrap().get();
12178 }
12179 return NS_OK;
12180}
12181
12182nsresult nsDocShell::CancelPlannedFormNavigation() {
12183 if (mPlannedFormNavigation) {
12184 mPlannedFormNavigation->Cancel();
12185 mPlannedFormNavigation = nullptr;
12186 }
12187 return NS_OK;
12188}
12189
12190nsresult nsDocShell::OnLinkClick(
12191 nsIContent* aContent, nsIURI* aURI, const nsAString& aTargetSpec,
12192 const nsAString& aFileName, nsIInputStream* aPostDataStream,
12193 nsIInputStream* aHeadersDataStream, bool aIsUserTriggered,
12194 UserNavigationInvolvement aUserInvolvement,
12195 nsIPrincipal* aTriggeringPrincipal, nsIPolicyContainer* aPolicyContainer) {
12196#ifndef ANDROID
12197 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" ")", "./../../../docshell/base/nsDocShell.cpp"
, 12197); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aTriggeringPrincipal"
") (" "Need a valid triggeringPrincipal" ")"); do { MOZ_CrashSequence
(__null, 12197); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
12198#endif
12199 NS_ASSERTION(NS_IsMainThread(), "wrong thread")do { if (!(NS_IsMainThread())) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "wrong thread", "NS_IsMainThread()", "./../../../docshell/base/nsDocShell.cpp"
, 12199); MOZ_PretendNoReturn(); } } while (0)
;
12200
12201 if (!IsNavigationAllowed() || !IsOKToLoadURI(aURI)) {
12202 return NS_OK;
12203 }
12204
12205 // On history navigation through Back/Forward buttons, don't execute
12206 // automatic JavaScript redirection such as |anchorElement.click()| or
12207 // |formElement.submit()|.
12208 //
12209 // XXX |formElement.submit()| bypasses this checkpoint because it calls
12210 // nsDocShell::OnLinkClickSync(...) instead.
12211 if (ShouldBlockLoadingForBackButton()) {
12212 return NS_OK;
12213 }
12214
12215 if (aContent->IsEditable()) {
12216 return NS_OK;
12217 }
12218
12219 RefPtr<Document> ownerDoc = aContent->OwnerDoc();
12220 if (nsContentUtils::IsExternalProtocol(aURI)) {
12221 ownerDoc->EnsureNotEnteringAndExitFullscreen();
12222 }
12223
12224 bool noOpenerImplied = false;
12225 nsAutoString target(aTargetSpec);
12226 if (aFileName.IsVoid() &&
12227 ShouldOpenInBlankTarget(aTargetSpec, aURI, aContent, aIsUserTriggered)) {
12228 target = u"_blank";
12229 if (!aTargetSpec.Equals(target)) {
12230 noOpenerImplied = true;
12231 }
12232 }
12233
12234 // https://html.spec.whatwg.org/#downloading-hyperlinks
12235 // Step 6, step 6.1, step 6.2
12236 // aFileName not being void implies a download attribute, since we've already
12237 // checked if the attribute is present in `nsContentUtils::TriggerLinkClick`
12238 // and made it void otherwise.
12239 if (!aFileName.IsVoid() &&
12240 aUserInvolvement != UserNavigationInvolvement::BrowserUI) {
12241 if (nsCOMPtr<nsPIDOMWindowInner> window = ownerDoc->GetInnerWindow()) {
12242 if (RefPtr<Navigation> navigation = window->Navigation()) {
12243 AutoJSAPI jsapi;
12244 if (jsapi.Init(window)) {
12245 RefPtr element = aContent->AsElement();
12246 // Step 6.4
12247 bool shouldContinue = navigation->FireDownloadRequestNavigateEvent(
12248 jsapi.cx(), aURI, aUserInvolvement, element, aFileName);
12249
12250 // Step 6.5
12251 if (!shouldContinue) {
12252 return NS_OK;
12253 }
12254 }
12255 }
12256 }
12257 }
12258
12259 RefPtr loadState = MakeRefPtr<nsDocShellLoadState>(aURI);
12260 loadState->SetTarget(target);
12261 loadState->SetFileName(aFileName);
12262 loadState->SetPostDataStream(aPostDataStream);
12263 loadState->SetHeadersStream(aHeadersDataStream);
12264 loadState->SetFirstParty(true);
12265 loadState->SetTriggeringPrincipal(
12266 aTriggeringPrincipal ? aTriggeringPrincipal : aContent->NodePrincipal());
12267 loadState->SetPrincipalToInherit(aContent->NodePrincipal());
12268 loadState->SetPolicyContainer(
12269 aPolicyContainer ? aPolicyContainer : aContent->GetPolicyContainer());
12270 loadState->SetAllowFocusMove(UserActivation::IsHandlingUserInput());
12271
12272 const bool hasValidUserGestureActivation =
12273 ownerDoc->HasValidTransientUserGestureActivation();
12274 loadState->SetHasValidUserGestureActivation(hasValidUserGestureActivation);
12275
12276 // For protocols that would launch without a prompt (e.g. mailto), consume the
12277 // transient user gesture activation so a single gesture can't chain multiple
12278 // launches. Do this here, at the same point the activation value is captured
12279 // on the load state, rather than later in OnLinkClickSync: that runs
12280 // asynchronously, and consuming there would be inconsistent with the scripted
12281 // navigation path (see BrowsingContext::Navigate). The pre-consume value is
12282 // already recorded on the load state above. See bug 299116.
12283 if (nsAutoCString scheme; NS_SUCCEEDED(aURI->GetScheme(scheme))((bool)(__builtin_expect(!!(!NS_FAILED_impl(aURI->GetScheme
(scheme))), 1)))
) {
12284 nsExternalHelperAppService::MaybeConsumeUserActivationForExternalScheme(
12285 ownerDoc->GetWindowContext(), loadState->TriggeringPrincipal(), scheme);
12286 }
12287
12288 loadState->SetTextDirectiveUserActivation(
12289 ownerDoc->ConsumeTextDirectiveUserActivation() ||
12290 hasValidUserGestureActivation);
12291 loadState->SetUserNavigationInvolvement(aUserInvolvement);
12292 loadState->SetTriggeringClassificationFlags(
12293 ownerDoc->GetScriptTrackingFlags());
12294 loadState->SetHistoryBehavior(NavigationHistoryBehavior::Auto);
12295
12296 auto result = OnLinkClickWithLoadState(aContent, loadState, noOpenerImplied,
12297 aTriggeringPrincipal);
12298 return result.isErr() ? result.unwrapErr() : NS_OK;
12299}
12300
12301bool nsDocShell::ShouldOpenInBlankTarget(const nsAString& aOriginalTarget,
12302 nsIURI* aLinkURI, nsIContent* aContent,
12303 bool aIsUserTriggered) {
12304 if (aLinkURI->SchemeIs("javascript")) {
12305 return false;
12306 }
12307
12308 // External links from within app tabs should always open in new tabs
12309 // instead of replacing the app tab's page (Bug 575561)
12310 // nsIURI.host can throw for non-nsStandardURL nsIURIs. If we fail to
12311 // get either host, just return false to use the original target.
12312 nsAutoCString linkHost;
12313 if (NS_FAILED(aLinkURI->GetHost(linkHost))((bool)(__builtin_expect(!!(NS_FAILED_impl(aLinkURI->GetHost
(linkHost))), 0)))
) {
12314 return false;
12315 }
12316
12317 // The targetTopLevelLinkClicksToBlank property on BrowsingContext allows
12318 // privileged code to change the default targeting behaviour. In particular,
12319 // if a user-initiated link click for the (or targetting the) top-level frame
12320 // is detected, we default the target to "_blank" to give it a new
12321 // top-level BrowsingContext.
12322 if (mBrowsingContext->TargetTopLevelLinkClicksToBlank() && aIsUserTriggered &&
12323 ((aOriginalTarget.IsEmpty() && mBrowsingContext->IsTop()) ||
12324 aOriginalTarget == u"_top"_ns)) {
12325 return true;
12326 }
12327
12328 // Don't modify non-default targets.
12329 if (!aOriginalTarget.IsEmpty()) {
12330 return false;
12331 }
12332
12333 // Only check targets that are in extension panels or app tabs.
12334 // (isAppTab will be false for app tab subframes).
12335 nsString mmGroup = mBrowsingContext->Top()->GetMessageManagerGroup();
12336 if (!mmGroup.EqualsLiteral("webext-browsers") &&
12337 !mBrowsingContext->IsAppTab()) {
12338 return false;
12339 }
12340
12341 nsCOMPtr<nsIURI> docURI = aContent->OwnerDoc()->GetDocumentURIObject();
12342 if (!docURI) {
12343 return false;
12344 }
12345
12346 nsAutoCString docHost;
12347 if (NS_FAILED(docURI->GetHost(docHost))((bool)(__builtin_expect(!!(NS_FAILED_impl(docURI->GetHost
(docHost))), 0)))
) {
12348 return false;
12349 }
12350
12351 if (linkHost.Equals(docHost)) {
12352 return false;
12353 }
12354
12355 // Special case: ignore "www" prefix if it is part of host string
12356 return linkHost.Length() < docHost.Length()
12357 ? !docHost.Equals("www."_ns + linkHost)
12358 : !linkHost.Equals("www."_ns + docHost);
12359}
12360
12361static bool ElementCanHaveNoopener(nsIContent* aContent) {
12362 // Make sure we are dealing with either an <A>, <AREA>, or <FORM> element in
12363 // the HTML, XHTML, or SVG namespace.
12364 return aContent->IsAnyOfHTMLElements(nsGkAtoms::a, nsGkAtoms::area,
12365 nsGkAtoms::form) ||
12366 aContent->IsSVGElement(nsGkAtoms::a);
12367}
12368
12369nsresult nsDocShell::OnLinkClickSync(nsIContent* aContent,
12370 nsDocShellLoadState* aLoadState,
12371 bool aNoOpenerImplied,
12372 nsIPrincipal* aTriggeringPrincipal) {
12373 if (!IsNavigationAllowed() || !IsOKToLoadURI(aLoadState->URI())) {
12374 return NS_OK;
12375 }
12376
12377 if (aContent->IsEditable()) {
12378 return NS_OK;
12379 }
12380
12381 // if the triggeringPrincipal is not passed explicitly, then we
12382 // fall back to using doc->NodePrincipal() as the triggeringPrincipal.
12383 nsCOMPtr<nsIPrincipal> triggeringPrincipal =
12384 aTriggeringPrincipal ? aTriggeringPrincipal : aContent->NodePrincipal();
12385
12386 {
12387 // defer to an external protocol handler if necessary...
12388 nsCOMPtr<nsIExternalProtocolService> extProtService =
12389 do_GetService(NS_EXTERNALPROTOCOLSERVICE_CONTRACTID"@mozilla.org/uriloader/external-protocol-service;1");
12390 if (extProtService) {
12391 nsAutoCString scheme;
12392 aLoadState->URI()->GetScheme(scheme);
12393 if (!scheme.IsEmpty()) {
12394 // if the URL scheme does not correspond to an exposed protocol, then
12395 // we need to hand this link click over to the external protocol
12396 // handler.
12397 bool isExposed;
12398 nsresult rv =
12399 extProtService->IsExposedProtocol(scheme.get(), &isExposed);
12400 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && !isExposed) {
12401 // Use the activation captured on the load state at click/submit time
12402 // (OnLinkClick, HTMLFormElement::SubmitSubmission), rather than
12403 // re-reading from the document here: this runs asynchronously, by
12404 // which point the transient activation may have expired. Consumption
12405 // of the activation (for gated schemes like mailto) also happens at
12406 // that capture point. See bug 299116.
12407 bool hasValidUserGestureActivation =
12408 aLoadState->HasValidUserGestureActivation();
12409 return extProtService->LoadURI(aLoadState->URI(), triggeringPrincipal,
12410 nullptr, mBrowsingContext,
12411 /* aTriggeredExternally */
12412 false, hasValidUserGestureActivation,
12413 /* aNewWindowTarget */ false);
12414 }
12415 }
12416 }
12417 }
12418 uint32_t triggeringSandboxFlags = 0;
12419 uint64_t triggeringWindowId = 0;
12420 bool triggeringStorageAccess = false;
12421 if (mBrowsingContext) {
12422 triggeringSandboxFlags = aContent->OwnerDoc()->GetSandboxFlags();
12423 triggeringWindowId = aContent->OwnerDoc()->InnerWindowID();
12424 triggeringStorageAccess = aContent->OwnerDoc()->UsingStorageAccess();
12425 }
12426
12427 uint32_t flags = INTERNAL_LOAD_FLAGS_NONE;
12428 bool elementCanHaveNoopener = ElementCanHaveNoopener(aContent);
12429 bool triggeringPrincipalIsSystemPrincipal =
12430 aLoadState->TriggeringPrincipal()->IsSystemPrincipal();
12431 if (elementCanHaveNoopener) {
12432 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()"
, "./../../../docshell/base/nsDocShell.cpp", 12432); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aContent->IsHTMLElement() || aContent->IsSVGElement()"
")"); do { MOZ_CrashSequence(__null, 12432); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12433 nsAutoString relString;
12434 aContent->AsElement()->GetAttr(nsGkAtoms::rel, relString);
12435 nsWhitespaceTokenizerTemplate<nsContentUtils::IsHTMLWhitespace> tok(
12436 relString);
12437
12438 bool targetBlank = aLoadState->Target().LowerCaseEqualsLiteral("_blank");
12439 bool explicitOpenerSet = false;
12440
12441 // The opener behaviour follows a hierarchy, such that if a higher
12442 // priority behaviour is specified, it always takes priority. That
12443 // priority is currently: norefrerer > noopener > opener > default
12444
12445 while (tok.hasMoreTokens()) {
12446 const nsAString& token = tok.nextToken();
12447 if (token.LowerCaseEqualsLiteral("noreferrer")) {
12448 flags |= INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER |
12449 INTERNAL_LOAD_FLAGS_NO_OPENER;
12450 // noreferrer cannot be overwritten by a 'rel=opener'.
12451 explicitOpenerSet = true;
12452 break;
12453 }
12454
12455 if (token.LowerCaseEqualsLiteral("noopener")) {
12456 flags |= INTERNAL_LOAD_FLAGS_NO_OPENER;
12457 explicitOpenerSet = true;
12458 }
12459
12460 if (targetBlank && StaticPrefs::dom_targetBlankNoOpener_enabled() &&
12461 token.LowerCaseEqualsLiteral("opener") && !explicitOpenerSet) {
12462 explicitOpenerSet = true;
12463 }
12464 }
12465
12466 if (targetBlank && StaticPrefs::dom_targetBlankNoOpener_enabled() &&
12467 !explicitOpenerSet && !triggeringPrincipalIsSystemPrincipal) {
12468 flags |= INTERNAL_LOAD_FLAGS_NO_OPENER;
12469 }
12470
12471 if (aNoOpenerImplied) {
12472 flags |= INTERNAL_LOAD_FLAGS_NO_OPENER;
12473 }
12474 }
12475
12476 // Get the owner document of the link that was clicked, this will be
12477 // the document that the link is in, or the last document that the
12478 // link was in. From that document, we'll get the URI to use as the
12479 // referrer, since the current URI in this docshell may be a
12480 // new document that we're in the process of loading.
12481 RefPtr<Document> referrerDoc = aContent->OwnerDoc();
12482
12483 // Now check that the referrerDoc's inner window is the current inner
12484 // window for mScriptGlobal. If it's not, then we don't want to
12485 // follow this link.
12486 nsPIDOMWindowInner* referrerInner = referrerDoc->GetInnerWindow();
12487 if (!mScriptGlobal || !referrerInner ||
12488 mScriptGlobal->GetCurrentInnerWindow() != referrerInner) {
12489 // We're no longer the current inner window
12490 return NS_OK;
12491 }
12492
12493 // referrer could be null here in some odd cases, but that's ok,
12494 // we'll just load the link w/o sending a referrer in those cases.
12495
12496 uint32_t loadType = LOAD_LINK;
12497 if (aLoadState->IsFormSubmission()) {
12498 if (aLoadState->Target().IsEmpty()) {
12499 // We set the right load type here for form submissions with an empty
12500 // target. Form submission with a non-empty target are handled in
12501 // nsDocShell::PerformRetargeting after we've selected the correct target
12502 // BC.
12503 loadType = GetLoadTypeForFormSubmission(GetBrowsingContext(), aLoadState);
12504 }
12505 } else {
12506 // Link click can be triggered inside an onload handler, and we don't want
12507 // to add history entry in this case.
12508 bool inOnLoadHandler = false;
12509 GetIsExecutingOnLoadHandler(&inOnLoadHandler);
12510 if (inOnLoadHandler) {
12511 loadType = LOAD_NORMAL_REPLACE;
12512 }
12513 }
12514
12515 RefPtr referrerInfo = elementCanHaveNoopener
12516 ? MakeRefPtr<ReferrerInfo>(*aContent->AsElement())
12517 : MakeRefPtr<ReferrerInfo>(*referrerDoc);
12518
12519 aLoadState->SetTriggeringSandboxFlags(triggeringSandboxFlags);
12520 aLoadState->SetTriggeringWindowId(triggeringWindowId);
12521 aLoadState->SetTriggeringStorageAccess(triggeringStorageAccess);
12522 aLoadState->SetReferrerInfo(referrerInfo);
12523 aLoadState->SetInternalLoadFlags(flags);
12524 aLoadState->SetLoadType(loadType);
12525 aLoadState->SetSourceBrowsingContext(mBrowsingContext);
12526
12527 nsresult rv = InternalLoad(aLoadState);
12528
12529 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
12530 nsPingListener::DispatchPings(this, aContent, aLoadState->URI(),
12531 referrerInfo);
12532 }
12533
12534 return rv;
12535}
12536
12537nsresult nsDocShell::OnOverLink(nsIContent* aContent, nsIURI* aURI,
12538 const nsAString& aTargetSpec) {
12539 if (aContent->IsEditable()) {
12540 return NS_OK;
12541 }
12542
12543 nsresult rv = NS_ERROR_FAILURE;
12544
12545 nsCOMPtr<nsIWebBrowserChrome> browserChrome = do_GetInterface(mTreeOwner);
12546 if (!browserChrome) {
12547 return rv;
12548 }
12549
12550 nsCOMPtr<nsIURI> exposableURI = nsIOService::CreateExposableURI(aURI);
12551 nsAutoCString spec;
12552 rv = exposableURI->GetDisplaySpec(spec);
12553 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, "./../../../docshell/base/nsDocShell.cpp"
, 12553); return rv; } } while (false)
;
12554
12555 NS_ConvertUTF8toUTF16 uStr(spec);
12556
12557 // The speculative connect used to go through the predictor, but we don't
12558 // need all that just to initiate a speculative connect.
12559 if ((StaticPrefs::network_predictor_enable_hover_on_ssl() &&
12560 mCurrentURI->SchemeIs("https")) ||
12561 mCurrentURI->SchemeIs("http")) {
12562 if (nsCOMPtr<nsISpeculativeConnect> specService =
12563 mozilla::components::IO::Service()) {
12564 // This would be a navigation, so if this is cross origin the speculative
12565 // connection needs to have the origin of the URL not the current page.
12566 nsCOMPtr<nsIPrincipal> principal = BasePrincipal::CreateContentPrincipal(
12567 aURI, aContent->NodePrincipal()->OriginAttributesRef());
12568
12569 specService->SpeculativeConnect(aURI, principal, this, false);
12570 }
12571 }
12572
12573 rv = browserChrome->SetLinkStatus(uStr);
12574 return rv;
12575}
12576
12577nsresult nsDocShell::OnLeaveLink() {
12578 nsCOMPtr<nsIWebBrowserChrome> browserChrome(do_GetInterface(mTreeOwner));
12579 nsresult rv = NS_ERROR_FAILURE;
12580
12581 if (browserChrome) {
12582 rv = browserChrome->SetLinkStatus(u""_ns);
12583 }
12584 return rv;
12585}
12586
12587bool nsDocShell::ShouldBlockLoadingForBackButton() {
12588 if (!(mLoadType & LOAD_CMD_HISTORY) ||
12589 UserActivation::IsHandlingUserInput() ||
12590 !Preferences::GetBool("accessibility.blockjsredirection")) {
12591 return false;
12592 }
12593
12594 bool canGoForward = false;
12595 GetCanGoForward(&canGoForward);
12596 return canGoForward;
12597}
12598
12599//----------------------------------------------------------------------
12600// Web Shell Services API
12601
12602// This functions is only called when a new charset is detected in loading a
12603// document.
12604nsresult nsDocShell::CharsetChangeReloadDocument(
12605 mozilla::NotNull<const mozilla::Encoding*> aEncoding, int32_t aSource) {
12606 // XXX hack. keep the aCharset and aSource wait to pick it up
12607 nsCOMPtr<nsIDocumentViewer> viewer;
12608 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, "./../../../docshell/base/nsDocShell.cpp"
, 12608); return NS_ERROR_FAILURE; } } while (false)
;
12609 if (viewer) {
12610 int32_t source;
12611 (void)viewer->GetReloadEncodingAndSource(&source);
12612 if (aSource > source) {
12613 viewer->SetReloadEncodingAndSource(aEncoding, aSource);
12614 if (eCharsetReloadRequested != mCharsetReloadState) {
12615 mCharsetReloadState = eCharsetReloadRequested;
12616 switch (mLoadType) {
12617 case LOAD_RELOAD_BYPASS_PROXY_AND_CACHE:
12618 return Reload(LOAD_FLAGS_CHARSET_CHANGE | LOAD_FLAGS_BYPASS_CACHE |
12619 LOAD_FLAGS_BYPASS_PROXY);
12620 case LOAD_RELOAD_BYPASS_CACHE:
12621 return Reload(LOAD_FLAGS_CHARSET_CHANGE | LOAD_FLAGS_BYPASS_CACHE);
12622 default:
12623 return Reload(LOAD_FLAGS_CHARSET_CHANGE);
12624 }
12625 }
12626 }
12627 }
12628 // return failure if this request is not accepted due to mCharsetReloadState
12629 return NS_ERROR_DOCSHELL_REQUEST_REJECTED;
12630}
12631
12632nsresult nsDocShell::CharsetChangeStopDocumentLoad() {
12633 if (eCharsetReloadRequested != mCharsetReloadState) {
12634 Stop(nsIWebNavigation::STOP_ALL);
12635 return NS_OK;
12636 }
12637 // return failer if this request is not accepted due to mCharsetReloadState
12638 return NS_ERROR_DOCSHELL_REQUEST_REJECTED;
12639}
12640
12641NS_IMETHODIMPnsresult nsDocShell::ExitPrintPreview() {
12642#ifdef NS_PRINTING1
12643 nsCOMPtr<nsIWebBrowserPrint> viewer = do_QueryInterface(mDocumentViewer);
12644 MOZ_TRY(viewer->ExitPrintPreview())__extension__({ auto mozTryVarTempResult = ::mozilla::ToResult
(viewer->ExitPrintPreview()); if ((__builtin_expect(!!(mozTryVarTempResult
.isErr()), 0))) { return mozTryVarTempResult.propagateErr(); }
mozTryVarTempResult.unwrap(); })
;
12645#endif
12646 return NS_OK;
12647}
12648
12649/* [infallible] */
12650NS_IMETHODIMPnsresult nsDocShell::GetIsTopLevelContentDocShell(
12651 bool* aIsTopLevelContentDocShell) {
12652 *aIsTopLevelContentDocShell = false;
12653
12654 if (mItemType == typeContent) {
12655 *aIsTopLevelContentDocShell = mBrowsingContext->IsTopContent();
12656 }
12657
12658 return NS_OK;
12659}
12660
12661// Implements nsILoadContext.originAttributes
12662NS_IMETHODIMPnsresult
12663nsDocShell::GetScriptableOriginAttributes(JSContext* aCx,
12664 JS::MutableHandle<JS::Value> aVal) {
12665 return mBrowsingContext->GetScriptableOriginAttributes(aCx, aVal);
12666}
12667
12668// Implements nsIDocShell.GetOriginAttributes()
12669NS_IMETHODIMPnsresult
12670nsDocShell::GetOriginAttributes(JSContext* aCx,
12671 JS::MutableHandle<JS::Value> aVal) {
12672 return mBrowsingContext->GetScriptableOriginAttributes(aCx, aVal);
12673}
12674
12675bool nsDocShell::ServiceWorkerAllowedToControlWindow(nsIPrincipal* aPrincipal,
12676 nsIURI* aURI) {
12677 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", "./../../../docshell/base/nsDocShell.cpp"
, 12677); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPrincipal"
")"); do { MOZ_CrashSequence(__null, 12677); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12678 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", "./../../../docshell/base/nsDocShell.cpp"
, 12678); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aURI" ")")
; do { MOZ_CrashSequence(__null, 12678); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
12679
12680 if (UsePrivateBrowsing() || mBrowsingContext->GetSandboxFlags()) {
12681 return false;
12682 }
12683
12684 nsCOMPtr<nsIDocShellTreeItem> parent;
12685 GetInProcessSameTypeParent(getter_AddRefs(parent));
12686 nsPIDOMWindowOuter* parentOuter = parent ? parent->GetWindow() : nullptr;
12687 nsPIDOMWindowInner* parentInner =
12688 parentOuter ? parentOuter->GetCurrentInnerWindow() : nullptr;
12689
12690 StorageAccess storage =
12691 StorageAllowedForNewWindow(aPrincipal, aURI, parentInner);
12692
12693 // A service worker is allowed to control the window if partition is enabled.
12694 if (parentInner) {
12695 RefPtr<Document> doc = parentInner->GetExtantDoc();
12696
12697 if (doc && StoragePartitioningEnabled(storage, doc->CookieJarSettings())) {
12698 return true;
12699 }
12700 }
12701
12702 return storage == StorageAccess::eAllow;
12703}
12704
12705nsresult nsDocShell::SetOriginAttributes(const OriginAttributes& aAttrs) {
12706 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"
, "./../../../docshell/base/nsDocShell.cpp", 12706); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!mIsBeingDestroyed" ")"); do { MOZ_CrashSequence
(__null, 12706); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
12707 return mBrowsingContext->SetOriginAttributes(aAttrs);
12708}
12709
12710NS_IMETHODIMPnsresult
12711nsDocShell::ResumeRedirectedLoad(uint64_t aIdentifier) {
12712 RefPtr<nsDocShell> self = this;
12713 RefPtr<ChildProcessChannelListener> cpcl =
12714 ChildProcessChannelListener::GetSingleton();
12715
12716 // Call into InternalLoad with the pending channel when it is received.
12717 cpcl->RegisterCallback(
12718 aIdentifier, [self](nsDocShellLoadState* aLoadState,
12719 nsTArray<Endpoint<extensions::PStreamFilterParent>>&&
12720 aStreamFilterEndpoints,
12721 nsDOMNavigationTiming* aTiming) {
12722 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()"
, "./../../../docshell/base/nsDocShell.cpp", 12722); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aLoadState->GetPendingRedirectedChannel()"
")"); do { MOZ_CrashSequence(__null, 12722); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12723 if (NS_WARN_IF(self->mIsBeingDestroyed)NS_warn_if_impl(self->mIsBeingDestroyed, "self->mIsBeingDestroyed"
, "./../../../docshell/base/nsDocShell.cpp", 12723)
) {
12724 aLoadState->GetPendingRedirectedChannel()->CancelWithReason(
12725 NS_BINDING_ABORTED, "nsDocShell::mIsBeingDestroyed"_ns);
12726 return NS_BINDING_ABORTED;
12727 }
12728
12729 self->mLoadType = aLoadState->LoadType();
12730 nsCOMPtr<nsIURI> previousURI;
12731 uint32_t previousFlags = 0;
12732 ExtractLastVisit(aLoadState->GetPendingRedirectedChannel(),
12733 getter_AddRefs(previousURI), &previousFlags);
12734 self->SaveLastVisit(aLoadState->GetPendingRedirectedChannel(),
12735 previousURI, previousFlags);
12736
12737 if (aTiming) {
12738 self->mTiming = new nsDOMNavigationTiming(self, aTiming);
12739 self->mBlankTiming = false;
12740 }
12741
12742 // Prohibit initial about:blank handling e.g. for when a cross-process
12743 // iframe loads about:blank and becomes same-process. Conceptually, the
12744 // browsing context isn't new despite the docshell being newly created.
12745 aLoadState->ProhibitInitialAboutBlankHandling();
12746
12747 self->InternalLoad(aLoadState);
12748
12749 if (aLoadState->GetOriginalURIString().isSome()) {
12750 // Save URI string in case it's needed later when
12751 // sending to search engine service in EndPageLoad()
12752 self->mOriginalUriString = *aLoadState->GetOriginalURIString();
12753 }
12754
12755 for (auto& endpoint : aStreamFilterEndpoints) {
12756 extensions::StreamFilterParent::Attach(
12757 aLoadState->GetPendingRedirectedChannel(), std::move(endpoint));
12758 }
12759
12760 // If the channel isn't pending, then it means that InternalLoad
12761 // never connected it, and we shouldn't try to continue. This
12762 // can happen even if InternalLoad returned NS_OK.
12763 bool pending = false;
12764 aLoadState->GetPendingRedirectedChannel()->IsPending(&pending);
12765 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", "./../../../docshell/base/nsDocShell.cpp", 12765
); MOZ_PretendNoReturn(); } } while (0)
;
12766 if (!pending) {
12767 return NS_BINDING_ABORTED;
12768 }
12769 return NS_OK;
12770 });
12771 return NS_OK;
12772}
12773
12774NS_IMETHODIMPnsresult
12775nsDocShell::SetOriginAttributes(JS::Handle<JS::Value> aOriginAttributes,
12776 JSContext* aCx) {
12777 OriginAttributes attrs;
12778 if (!aOriginAttributes.isObject() || !attrs.Init(aCx, aOriginAttributes)) {
12779 return NS_ERROR_INVALID_ARG;
12780 }
12781
12782 return SetOriginAttributes(attrs);
12783}
12784
12785NS_IMETHODIMPnsresult
12786nsDocShell::GetAsyncPanZoomEnabled(bool* aOut) {
12787 if (PresShell* presShell = GetPresShell()) {
12788 *aOut = presShell->AsyncPanZoomEnabled();
12789 return NS_OK;
12790 }
12791
12792 // If we don't have a presShell, fall back to the default platform value of
12793 // whether or not APZ is enabled.
12794 *aOut = gfxPlatform::AsyncPanZoomEnabled();
12795 return NS_OK;
12796}
12797
12798bool nsDocShell::HasUnloadedParent() {
12799 for (WindowContext* wc = GetBrowsingContext()->GetParentWindowContext(); wc;
12800 wc = wc->GetParentWindowContext()) {
12801 if (!wc->IsCurrent() || wc->IsDiscarded() ||
12802 wc->GetBrowsingContext()->IsDiscarded()) {
12803 // If a parent is OOP and the parent WindowContext is no
12804 // longer current, we can assume the parent was unloaded.
12805 return true;
12806 }
12807
12808 if (wc->GetBrowsingContext()->IsInProcess() &&
12809 (!wc->GetBrowsingContext()->GetDocShell() ||
12810 wc->GetBrowsingContext()->GetDocShell()->GetIsInUnload())) {
12811 return true;
12812 }
12813 }
12814 return false;
12815}
12816
12817/* static */
12818bool nsDocShell::ShouldUpdateGlobalHistory(uint32_t aLoadType) {
12819 return !(aLoadType == LOAD_BYPASS_HISTORY || aLoadType == LOAD_ERROR_PAGE ||
12820 aLoadType & LOAD_CMD_HISTORY);
12821}
12822
12823void nsDocShell::UpdateGlobalHistoryTitle(nsIURI* aURI) {
12824 if (!mBrowsingContext->GetUseGlobalHistory() || UsePrivateBrowsing()) {
12825 return;
12826 }
12827
12828 // Global history is interested into sub-frame visits only for link-coloring
12829 // purposes, thus title updates are skipped for those.
12830 //
12831 // Moreover, some iframe documents (such as the ones created via
12832 // document.open()) inherit the document uri of the caller, which would cause
12833 // us to override a previously set page title with one from the subframe.
12834 if (IsSubframe()) {
12835 return;
12836 }
12837
12838 if (nsCOMPtr<IHistory> history = components::History::Service()) {
12839 history->SetURITitle(aURI, mTitle);
12840 }
12841}
12842
12843bool nsDocShell::IsInvisible() { return mInvisible; }
12844
12845void nsDocShell::SetInvisible(bool aInvisible) { mInvisible = aInvisible; }
12846
12847/* static */
12848void nsDocShell::MaybeNotifyKeywordSearchLoading(const nsString& aProviderId,
12849 const nsString& aKeyword) {
12850 if (aProviderId.IsEmpty()) {
12851 return;
12852 }
12853 nsresult rv;
12854 nsCOMPtr<nsISupportsString> isupportsString =
12855 do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID"@mozilla.org/supports-string;1", &rv);
12856 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, "./../../../docshell/base/nsDocShell.cpp"
, 12856); return; } } while (false)
;
12857
12858 rv = isupportsString->SetData(aProviderId);
12859 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, "./../../../docshell/base/nsDocShell.cpp"
, 12859); return; } } while (false)
;
12860
12861 nsCOMPtr<nsIObserverService> obsSvc = services::GetObserverService();
12862 if (obsSvc) {
12863 // Note that "keyword-search" refers to a search via the url
12864 // bar, not a bookmarks keyword search.
12865 obsSvc->NotifyObservers(isupportsString, "keyword-search", aKeyword.get());
12866 }
12867}
12868
12869NS_IMETHODIMPnsresult
12870nsDocShell::ShouldPrepareForIntercept(nsIURI* aURI, nsIChannel* aChannel,
12871 bool* aShouldIntercept) {
12872 return mInterceptController->ShouldPrepareForIntercept(aURI, aChannel,
12873 aShouldIntercept);
12874}
12875
12876NS_IMETHODIMPnsresult
12877nsDocShell::ChannelIntercepted(nsIInterceptedChannel* aChannel) {
12878 return mInterceptController->ChannelIntercepted(aChannel);
12879}
12880
12881bool nsDocShell::InFrameSwap() {
12882 RefPtr<nsDocShell> shell = this;
12883 do {
12884 if (shell->mInFrameSwap) {
12885 return true;
12886 }
12887 shell = shell->GetInProcessParentDocshell();
12888 } while (shell);
12889 return false;
12890}
12891
12892UniquePtr<ClientSource> nsDocShell::TakeInitialClientSource() {
12893 return std::move(mInitialClientSource);
12894}
12895
12896NS_IMETHODIMPnsresult
12897nsDocShell::GetEditingSession(nsIEditingSession** aEditSession) {
12898 if (!NS_SUCCEEDED(EnsureEditorData())((bool)(__builtin_expect(!!(!NS_FAILED_impl(EnsureEditorData(
))), 1)))
) {
12899 return NS_ERROR_FAILURE;
12900 }
12901
12902 *aEditSession = do_AddRef(mEditorData->GetEditingSession()).take();
12903 return *aEditSession ? NS_OK : NS_ERROR_FAILURE;
12904}
12905
12906NS_IMETHODIMPnsresult
12907nsDocShell::GetScriptableBrowserChild(nsIBrowserChild** aBrowserChild) {
12908 *aBrowserChild = GetBrowserChild().take();
12909 return *aBrowserChild ? NS_OK : NS_ERROR_FAILURE;
12910}
12911
12912already_AddRefed<nsIBrowserChild> nsDocShell::GetBrowserChild() {
12913 nsCOMPtr<nsIBrowserChild> tc = do_QueryReferent(mBrowserChild);
12914 return tc.forget();
12915}
12916
12917nsCommandManager* nsDocShell::GetCommandManager() {
12918 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
, "./../../../docshell/base/nsDocShell.cpp", 12918); return nullptr
; } } while (false)
;
12919 return mCommandManager;
12920}
12921
12922NS_IMETHODIMP_(void)void
12923nsDocShell::GetOriginAttributes(mozilla::OriginAttributes& aAttrs) {
12924 mBrowsingContext->GetOriginAttributes(aAttrs);
12925}
12926
12927HTMLEditor* nsIDocShell::GetHTMLEditor() {
12928 nsDocShell* docShell = static_cast<nsDocShell*>(this);
12929 return docShell->GetHTMLEditorInternal();
12930}
12931
12932nsresult nsIDocShell::SetHTMLEditor(HTMLEditor* aHTMLEditor) {
12933 nsDocShell* docShell = static_cast<nsDocShell*>(this);
12934 return docShell->SetHTMLEditorInternal(aHTMLEditor);
12935}
12936
12937#define MATRIX_LENGTH 20
12938
12939NS_IMETHODIMPnsresult
12940nsDocShell::SetColorMatrix(const nsTArray<float>& aMatrix) {
12941 if (aMatrix.Length() == MATRIX_LENGTH) {
12942 mColorMatrix = MakeUnique<gfx::Matrix5x4>();
12943 static_assert(
12944 MATRIX_LENGTH * sizeof(float) == sizeof(mColorMatrix->components),
12945 "Size mismatch for our memcpy");
12946 memcpy(mColorMatrix->components, aMatrix.Elements(),
12947 sizeof(mColorMatrix->components));
12948 } else if (aMatrix.Length() == 0) {
12949 mColorMatrix.reset();
12950 } else {
12951 return NS_ERROR_INVALID_ARG;
12952 }
12953
12954 PresShell* presShell = GetPresShell();
12955 if (!presShell) {
12956 return NS_ERROR_FAILURE;
12957 }
12958
12959 nsIFrame* frame = presShell->GetRootFrame();
12960 if (!frame) {
12961 return NS_ERROR_FAILURE;
12962 }
12963
12964 frame->SchedulePaint();
12965
12966 return NS_OK;
12967}
12968
12969NS_IMETHODIMPnsresult
12970nsDocShell::GetColorMatrix(nsTArray<float>& aMatrix) {
12971 if (mColorMatrix) {
12972 aMatrix.SetLength(MATRIX_LENGTH);
12973 static_assert(
12974 MATRIX_LENGTH * sizeof(float) == sizeof(mColorMatrix->components),
12975 "Size mismatch for our memcpy");
12976 memcpy(aMatrix.Elements(), mColorMatrix->components,
12977 MATRIX_LENGTH * sizeof(float));
12978 }
12979
12980 return NS_OK;
12981}
12982
12983#undef MATRIX_LENGTH
12984
12985NS_IMETHODIMPnsresult
12986nsDocShell::GetIsForceReloading(bool* aForceReload) {
12987 *aForceReload = IsForceReloading();
12988 return NS_OK;
12989}
12990
12991bool nsDocShell::IsForceReloading() { return IsForceReloadType(mLoadType); }
12992
12993NS_IMETHODIMPnsresult
12994nsDocShell::GetBrowsingContextXPCOM(BrowsingContext** aBrowsingContext) {
12995 *aBrowsingContext = do_AddRef(mBrowsingContext).take();
12996 return NS_OK;
12997}
12998
12999BrowsingContext* nsDocShell::GetBrowsingContext() { return mBrowsingContext; }
13000
13001bool nsDocShell::GetIsAttemptingToNavigate() {
13002 // XXXbz the document.open spec says to abort even if there's just a
13003 // queued navigation task, sort of. It's not clear whether browsers
13004 // actually do that, and we didn't use to do it, so for now let's
13005 // not do that.
13006 // https://github.com/whatwg/html/issues/3447 tracks the spec side of this.
13007 if (mDocumentRequest) {
13008 // There's definitely a navigation in progress.
13009 return true;
13010 }
13011
13012 // javascript: channels have slightly weird behavior: they're LOAD_BACKGROUND
13013 // until the script runs, which means they're not sending loadgroup
13014 // notifications and hence not getting set as mDocumentRequest. Look through
13015 // our loadgroup for document-level javascript: loads.
13016 if (!mLoadGroup) {
13017 return false;
13018 }
13019
13020 nsCOMPtr<nsISimpleEnumerator> requests;
13021 mLoadGroup->GetRequests(getter_AddRefs(requests));
13022 bool hasMore = false;
13023 while (NS_SUCCEEDED(requests->HasMoreElements(&hasMore))((bool)(__builtin_expect(!!(!NS_FAILED_impl(requests->HasMoreElements
(&hasMore))), 1)))
&& hasMore) {
13024 nsCOMPtr<nsISupports> elem;
13025 requests->GetNext(getter_AddRefs(elem));
13026 nsCOMPtr<nsIScriptChannel> scriptChannel(do_QueryInterface(elem));
13027 if (!scriptChannel) {
13028 continue;
13029 }
13030
13031 if (scriptChannel->GetIsDocumentLoad()) {
13032 // This is a javascript: load that might lead to a new document,
13033 // hence a navigation.
13034 return true;
13035 }
13036 }
13037
13038 if (mOngoingNavigation == Some(OngoingNavigation::NavigationID)) {
13039 return true;
13040 }
13041
13042 return mCheckingSessionHistory;
13043}
13044
13045mozilla::dom::SessionHistoryInfo* nsDocShell::GetActiveSessionHistoryInfo()
13046 const {
13047 return mActiveEntry.get();
13048}
13049
13050void nsDocShell::SetLoadingSessionHistoryInfo(
13051 const mozilla::dom::LoadingSessionHistoryInfo& aLoadingInfo,
13052 bool aNeedToReportActiveAfterLoadingBecomesActive) {
13053 // FIXME Would like to assert this, but can't yet.
13054 // MOZ_ASSERT(!mLoadingEntry);
13055 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)
13056 ("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)
13057 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)
;
13058 mLoadingEntry = MakeUnique<LoadingSessionHistoryInfo>(aLoadingInfo);
13059 mNeedToReportActiveAfterLoadingBecomesActive =
13060 aNeedToReportActiveAfterLoadingBecomesActive;
13061}
13062
13063void nsDocShell::MoveLoadingToActiveEntry(bool aExpired, uint32_t aCacheKey,
13064 nsIURI* aPreviousURI) {
13065 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)
13066 ("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)
;
13067
13068 UniquePtr<SessionHistoryInfo> previousActiveEntry(mActiveEntry.release());
13069 mozilla::UniquePtr<mozilla::dom::LoadingSessionHistoryInfo> loadingEntry;
13070 mActiveEntryIsLoadingFromSessionHistory =
13071 mLoadingEntry && mLoadingEntry->mLoadIsFromSessionHistory;
13072 if (mLoadingEntry) {
13073 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)
13074 ("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)
13075 "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)
13076 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)
;
13077 mActiveEntry = MakeUnique<SessionHistoryInfo>(mLoadingEntry->mInfo);
13078 mLoadingEntry.swap(loadingEntry);
13079 if (!mActiveEntryIsLoadingFromSessionHistory) {
13080 if (mNeedToReportActiveAfterLoadingBecomesActive) {
13081 // Needed to pass various history length WPTs.
13082 mBrowsingContext->SetActiveSessionHistoryEntry(
13083 mozilla::Nothing(), mActiveEntry.get(), previousActiveEntry.get(),
13084 mLoadType,
13085 /* aUpdatedCacheKey = */ 0, false);
13086 }
13087 if (!(previousActiveEntry && previousActiveEntry->IsTransient())) {
13088 mBrowsingContext->IncrementHistoryEntryCountForBrowsingContext();
13089 }
13090 }
13091 }
13092 mNeedToReportActiveAfterLoadingBecomesActive = false;
13093
13094 if (mActiveEntry) {
13095 if (aCacheKey != 0) {
13096 mActiveEntry->SetCacheKey(aCacheKey);
13097 }
13098
13099 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", "./../../../docshell/base/nsDocShell.cpp"
, 13099); AnnotateMozCrashReason("MOZ_ASSERT" "(" "loadingEntry"
")"); do { MOZ_CrashSequence(__null, 13099); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
13100 uint32_t loadType =
13101 mLoadType == LOAD_ERROR_PAGE ? mFailedLoadType : mLoadType;
13102
13103 if (loadingEntry->mLoadId != UINT64_MAX(18446744073709551615UL)) {
13104 // We're passing in mCurrentURI, which could be null. SessionHistoryCommit
13105 // does require a non-null uri if this is for a refresh load of the same
13106 // URI, but in that case mCurrentURI won't be null here.
13107 mBrowsingContext->SessionHistoryCommit(
13108 *loadingEntry, loadType, aPreviousURI, previousActiveEntry.get(),
13109 false, aExpired, aCacheKey);
13110 }
13111
13112 // Only update navigation if the new entry will be persisted (i.e., is not
13113 // an about: page).
13114 if (!loadingEntry->mInfo.IsTransient() && GetWindow() &&
13115 GetWindow()->GetCurrentInnerWindow()) {
13116 if (RefPtr navigation =
13117 GetWindow()->GetCurrentInnerWindow()->Navigation()) {
13118 navigation->InitializeHistoryEntries(loadingEntry->mContiguousEntries,
13119 mActiveEntry.get());
13120
13121 MOZ_LOG_FMT(gNavigationAPILog, LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = gNavigationAPILog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print_fmt(moz_real_module
, LogLevel::Debug, "Before creating NavigationActivation, " "triggeringEntry={}, triggeringType={}"
, fmt::ptr(loadingEntry->mPreviousEntry .map([](auto& entry
) { return &entry; }) .valueOr(nullptr)), loadingEntry->
mTriggeringNavigationType .map([](NavigationType type) { return
fmt::format("{}", type); }) .valueOr("none")); } } while (0)
13122 "Before creating NavigationActivation, "do { const ::mozilla::LogModule* moz_real_module = gNavigationAPILog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print_fmt(moz_real_module
, LogLevel::Debug, "Before creating NavigationActivation, " "triggeringEntry={}, triggeringType={}"
, fmt::ptr(loadingEntry->mPreviousEntry .map([](auto& entry
) { return &entry; }) .valueOr(nullptr)), loadingEntry->
mTriggeringNavigationType .map([](NavigationType type) { return
fmt::format("{}", type); }) .valueOr("none")); } } while (0)
13123 "triggeringEntry={}, triggeringType={}",do { const ::mozilla::LogModule* moz_real_module = gNavigationAPILog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print_fmt(moz_real_module
, LogLevel::Debug, "Before creating NavigationActivation, " "triggeringEntry={}, triggeringType={}"
, fmt::ptr(loadingEntry->mPreviousEntry .map([](auto& entry
) { return &entry; }) .valueOr(nullptr)), loadingEntry->
mTriggeringNavigationType .map([](NavigationType type) { return
fmt::format("{}", type); }) .valueOr("none")); } } while (0)
13124 fmt::ptr(loadingEntry->mPreviousEntrydo { const ::mozilla::LogModule* moz_real_module = gNavigationAPILog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print_fmt(moz_real_module
, LogLevel::Debug, "Before creating NavigationActivation, " "triggeringEntry={}, triggeringType={}"
, fmt::ptr(loadingEntry->mPreviousEntry .map([](auto& entry
) { return &entry; }) .valueOr(nullptr)), loadingEntry->
mTriggeringNavigationType .map([](NavigationType type) { return
fmt::format("{}", type); }) .valueOr("none")); } } while (0)
13125 .map([](auto& entry) { return &entry; })do { const ::mozilla::LogModule* moz_real_module = gNavigationAPILog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print_fmt(moz_real_module
, LogLevel::Debug, "Before creating NavigationActivation, " "triggeringEntry={}, triggeringType={}"
, fmt::ptr(loadingEntry->mPreviousEntry .map([](auto& entry
) { return &entry; }) .valueOr(nullptr)), loadingEntry->
mTriggeringNavigationType .map([](NavigationType type) { return
fmt::format("{}", type); }) .valueOr("none")); } } while (0)
13126 .valueOr(nullptr)),do { const ::mozilla::LogModule* moz_real_module = gNavigationAPILog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print_fmt(moz_real_module
, LogLevel::Debug, "Before creating NavigationActivation, " "triggeringEntry={}, triggeringType={}"
, fmt::ptr(loadingEntry->mPreviousEntry .map([](auto& entry
) { return &entry; }) .valueOr(nullptr)), loadingEntry->
mTriggeringNavigationType .map([](NavigationType type) { return
fmt::format("{}", type); }) .valueOr("none")); } } while (0)
13127 loadingEntry->mTriggeringNavigationTypedo { const ::mozilla::LogModule* moz_real_module = gNavigationAPILog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print_fmt(moz_real_module
, LogLevel::Debug, "Before creating NavigationActivation, " "triggeringEntry={}, triggeringType={}"
, fmt::ptr(loadingEntry->mPreviousEntry .map([](auto& entry
) { return &entry; }) .valueOr(nullptr)), loadingEntry->
mTriggeringNavigationType .map([](NavigationType type) { return
fmt::format("{}", type); }) .valueOr("none")); } } while (0)
13128 .map([](NavigationType type) {do { const ::mozilla::LogModule* moz_real_module = gNavigationAPILog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print_fmt(moz_real_module
, LogLevel::Debug, "Before creating NavigationActivation, " "triggeringEntry={}, triggeringType={}"
, fmt::ptr(loadingEntry->mPreviousEntry .map([](auto& entry
) { return &entry; }) .valueOr(nullptr)), loadingEntry->
mTriggeringNavigationType .map([](NavigationType type) { return
fmt::format("{}", type); }) .valueOr("none")); } } while (0)
13129 return fmt::format("{}", type);do { const ::mozilla::LogModule* moz_real_module = gNavigationAPILog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print_fmt(moz_real_module
, LogLevel::Debug, "Before creating NavigationActivation, " "triggeringEntry={}, triggeringType={}"
, fmt::ptr(loadingEntry->mPreviousEntry .map([](auto& entry
) { return &entry; }) .valueOr(nullptr)), loadingEntry->
mTriggeringNavigationType .map([](NavigationType type) { return
fmt::format("{}", type); }) .valueOr("none")); } } while (0)
13130 })do { const ::mozilla::LogModule* moz_real_module = gNavigationAPILog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print_fmt(moz_real_module
, LogLevel::Debug, "Before creating NavigationActivation, " "triggeringEntry={}, triggeringType={}"
, fmt::ptr(loadingEntry->mPreviousEntry .map([](auto& entry
) { return &entry; }) .valueOr(nullptr)), loadingEntry->
mTriggeringNavigationType .map([](NavigationType type) { return
fmt::format("{}", type); }) .valueOr("none")); } } while (0)
13131 .valueOr("none"))do { const ::mozilla::LogModule* moz_real_module = gNavigationAPILog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print_fmt(moz_real_module
, LogLevel::Debug, "Before creating NavigationActivation, " "triggeringEntry={}, triggeringType={}"
, fmt::ptr(loadingEntry->mPreviousEntry .map([](auto& entry
) { return &entry; }) .valueOr(nullptr)), loadingEntry->
mTriggeringNavigationType .map([](NavigationType type) { return
fmt::format("{}", type); }) .valueOr("none")); } } while (0)
;
13132 navigation->CreateNavigationActivationFrom(
13133 loadingEntry->mPreviousEntry,
13134 loadingEntry->mTriggeringNavigationType);
13135 }
13136 }
13137 }
13138}
13139
13140static bool IsFaviconLoad(nsIRequest* aRequest) {
13141 nsCOMPtr<nsIChannel> channel = do_QueryInterface(aRequest);
13142 if (!channel) {
13143 return false;
13144 }
13145
13146 nsCOMPtr<nsILoadInfo> li = channel->LoadInfo();
13147 return li && li->InternalContentPolicyType() ==
13148 nsIContentPolicy::TYPE_INTERNAL_IMAGE_FAVICON;
13149}
13150
13151void nsDocShell::RecordSingleChannelId(bool aStartRequest,
13152 nsIRequest* aRequest) {
13153 // Ignore favicon loads, they don't need to block caching.
13154 if (IsFaviconLoad(aRequest)) {
13155 return;
13156 }
13157
13158 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"
, "./../../../docshell/base/nsDocShell.cpp", 13158); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "mRequestForBlockingFromBFCacheCount > 0"
")"); do { MOZ_CrashSequence(__null, 13158); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false); } } while
(false)
;
13159
13160 mRequestForBlockingFromBFCacheCount += aStartRequest ? 1 : -1;
13161
13162 if (mBrowsingContext->GetCurrentWindowContext()) {
13163 // We have three states: no request, one request with an id and
13164 // eiher one request without an id or multiple requests. Nothing() is no
13165 // request, Some(non-zero) is one request with an id and Some(0) is one
13166 // request without an id or multiple requests.
13167 Maybe<uint64_t> singleChannelId;
13168 if (mRequestForBlockingFromBFCacheCount > 1) {
13169 singleChannelId = Some(0);
13170 } else if (mRequestForBlockingFromBFCacheCount == 1) {
13171 nsCOMPtr<nsIIdentChannel> identChannel;
13172 if (aStartRequest) {
13173 identChannel = do_QueryInterface(aRequest);
13174 } else {
13175 // aChannel is the channel that's being removed, but we need to check if
13176 // the remaining channel in the loadgroup has an id.
13177 nsCOMPtr<nsISimpleEnumerator> requests;
13178 mLoadGroup->GetRequests(getter_AddRefs(requests));
13179 for (const auto& request : SimpleEnumerator<nsIRequest>(requests)) {
13180 if (!IsFaviconLoad(request) &&
13181 !!(identChannel = do_QueryInterface(request))) {
13182 break;
13183 }
13184 }
13185 }
13186
13187 if (identChannel) {
13188 singleChannelId = Some(identChannel->ChannelId());
13189 } else {
13190 singleChannelId = Some(0);
13191 }
13192 } else {
13193 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"
, "./../../../docshell/base/nsDocShell.cpp", 13193); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "mRequestForBlockingFromBFCacheCount == 0" ")"
); do { MOZ_CrashSequence(__null, 13193); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
13194 singleChannelId = Nothing();
13195 }
13196
13197 if (MOZ_UNLIKELY(MOZ_LOG_TEST(gSHIPBFCacheLog, LogLevel::Verbose))(__builtin_expect(!!((__builtin_expect(!!(mozilla::detail::log_test
(gSHIPBFCacheLog, LogLevel::Verbose)), 0))), 0))
) {
13198 nsAutoCString uri("[no uri]");
13199 if (mCurrentURI) {
13200 uri = mCurrentURI->GetSpecOrDefault();
13201 }
13202 if (singleChannelId.isNothing()) {
13203 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)
13204 ("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)
13205 "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)
13206 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)
;
13207 } else if (singleChannelId.value() == 0) {
13208 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)
13209 ("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)
13210 "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)
13211 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)
;
13212 } else {
13213 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)
13214 ("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)
13215 " 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)
13216 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)
;
13217 }
13218 }
13219
13220 if (mSingleChannelId != singleChannelId) {
13221 mSingleChannelId = singleChannelId;
13222 WindowGlobalChild* wgc =
13223 mBrowsingContext->GetCurrentWindowContext()->GetWindowGlobalChild();
13224 if (wgc) {
13225 wgc->SendSetSingleChannelId(singleChannelId);
13226 }
13227 }
13228 }
13229}
13230
13231NS_IMETHODIMPnsresult
13232nsDocShell::OnStartRequest(nsIRequest* aRequest) {
13233 if (MOZ_UNLIKELY(MOZ_LOG_TEST(gSHIPBFCacheLog, LogLevel::Verbose))(__builtin_expect(!!((__builtin_expect(!!(mozilla::detail::log_test
(gSHIPBFCacheLog, LogLevel::Verbose)), 0))), 0))
) {
13234 nsAutoCString uri("[no uri]");
13235 if (mCurrentURI) {
13236 uri = mCurrentURI->GetSpecOrDefault();
13237 }
13238 nsAutoCString name;
13239 aRequest->GetName(name);
13240 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)
13241 ("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)
;
13242 }
13243 RecordSingleChannelId(true, aRequest);
13244 return nsDocLoader::OnStartRequest(aRequest);
13245}
13246
13247NS_IMETHODIMPnsresult
13248nsDocShell::OnStopRequest(nsIRequest* aRequest, nsresult aStatusCode) {
13249 if (MOZ_UNLIKELY(MOZ_LOG_TEST(gSHIPBFCacheLog, LogLevel::Verbose))(__builtin_expect(!!((__builtin_expect(!!(mozilla::detail::log_test
(gSHIPBFCacheLog, LogLevel::Verbose)), 0))), 0))
) {
13250 nsAutoCString uri("[no uri]");
13251 if (mCurrentURI) {
13252 uri = mCurrentURI->GetSpecOrDefault();
13253 }
13254 nsAutoCString name;
13255 aRequest->GetName(name);
13256 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)
13257 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)
13258 ("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)
;
13259 }
13260 RecordSingleChannelId(false, aRequest);
13261 return nsDocLoader::OnStopRequest(aRequest, aStatusCode);
13262}
13263
13264void nsDocShell::MaybeDisconnectChildListenersOnPageHide() {
13265 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()"
, "./../../../docshell/base/nsDocShell.cpp", 13265); AnnotateMozCrashReason
("MOZ_RELEASE_ASSERT" "(" "XRE_IsContentProcess()" ")"); do {
MOZ_CrashSequence(__null, 13265); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
13266
13267 if (mChannelToDisconnectOnPageHide != 0 && mLoadGroup) {
13268 nsCOMPtr<nsISimpleEnumerator> requests;
13269 mLoadGroup->GetRequests(getter_AddRefs(requests));
13270 for (const auto& request : SimpleEnumerator<nsIRequest>(requests)) {
13271 RefPtr<DocumentChannel> channel = do_QueryObject(request);
13272 if (channel && channel->ChannelId() == mChannelToDisconnectOnPageHide) {
13273 static_cast<DocumentChannelChild*>(channel.get())
13274 ->DisconnectChildListeners(NS_BINDING_ABORTED, NS_BINDING_ABORTED);
13275 }
13276 }
13277 mChannelToDisconnectOnPageHide = 0;
13278 }
13279}
13280
13281bool nsDocShell::IsSameDocumentAsActiveEntry(
13282 const mozilla::dom::SessionHistoryInfo& aSHInfo) {
13283 return mActiveEntry ? mActiveEntry->SharesDocumentWith(aSHInfo) : false;
13284}
13285
13286// https://html.spec.whatwg.org/#nav-window
13287nsPIDOMWindowInner* nsDocShell::GetActiveWindow() {
13288 nsPIDOMWindowOuter* outer = GetWindow();
13289 return outer ? outer->GetCurrentInnerWindow() : nullptr;
13290}
13291
13292// https://html.spec.whatwg.org/#inform-the-navigation-api-about-aborting-navigation
13293void nsDocShell::InformNavigationAPIAboutAbortingNavigation() {
13294 // Step 1
13295 // We really have no idea what this means.
13296
13297 // No ongoing navigations if we don't have a window.
13298 RefPtr<nsPIDOMWindowInner> window = GetActiveWindow();
13299 if (!window) {
13300 return;
13301 }
13302
13303 // Step 2
13304 RefPtr<Navigation> navigation = window->Navigation();
13305 if (!navigation) {
13306 return;
13307 }
13308
13309 AutoJSAPI jsapi;
13310 if (!jsapi.Init(navigation->GetRelevantGlobal())) {
13311 return;
13312 }
13313
13314 // Steps 3 & 4
13315 // See https://github.com/whatwg/html/issues/11579
13316 navigation->InnerInformAboutAbortingNavigation(jsapi.cx());
13317}
13318
13319// https://html.spec.whatwg.org/#inform-the-navigation-api-about-child-navigable-destruction
13320void nsDocShell::InformNavigationAPIAboutChildNavigableDestruction() {
13321 // Step 1
13322 InformNavigationAPIAboutAbortingNavigation();
13323
13324 // No ongoing navigations if we don't have a window.
13325 RefPtr<nsPIDOMWindowInner> window = GetActiveWindow();
13326 if (!window) {
13327 return;
13328 }
13329
13330 // Step 2
13331 RefPtr<Navigation> navigation = window->Navigation();
13332 if (!navigation) {
13333 return;
13334 }
13335
13336 AutoJSAPI jsapi;
13337 if (!jsapi.Init(navigation->GetRelevantGlobal())) {
13338 return;
13339 }
13340
13341 navigation->InformAboutChildNavigableDestruction(jsapi.cx());
13342}
13343
13344// https://html.spec.whatwg.org/#set-the-ongoing-navigation
13345void nsDocShell::SetOngoingNavigation(
13346 const Maybe<OngoingNavigation>& aOngoingNavigation) {
13347 // We currently only use #set-the-ongoing-navigation to call,
13348 // #inform-the-navigation-api-about-aborting-navigation, but really it should
13349 // be used for more. The spec keeps a piece of state on the navigable:
13350 // https://html.spec.whatwg.org/#ongoing-navigation. Spec uses it for several
13351 // things, for example right here in #set-the-ongoing-navigation to make sure
13352 // that we don't call #inform-the-navigation-api-about-aborting-navigation if
13353 // we're setting it to the same value. We currently only care about aborting
13354 // the currently firing navigate event. Also, in reality, this is very much
13355 // related to nsDocShell::GetIsAttemptingToNavigate() which is what we
13356 // currently use to determine if we need to stop an ongoing navigation in
13357 // Document::Open, whereas the spec checks if the ongoing navigation is a
13358 // NavigationID.
13359
13360 // Step 1, with the exception that we assume setting the ongoing navigation to
13361 // an id always means a fresh id.
13362 if (aOngoingNavigation == mOngoingNavigation &&
13363 aOngoingNavigation != Some(OngoingNavigation::NavigationID)) {
13364 return;
13365 }
13366
13367 // Step 2
13368 InformNavigationAPIAboutAbortingNavigation();
13369
13370 // Step 3
13371 mOngoingNavigation = aOngoingNavigation;
13372}
13373
13374void nsDocShell::StopPendingJavascriptURLNavigations() {
13375 nsCOMPtr<nsISimpleEnumerator> requests;
13376 mLoadGroup->GetRequests(getter_AddRefs(requests));
13377 bool hasMore;
13378 while (NS_SUCCEEDED(requests->HasMoreElements(&hasMore))((bool)(__builtin_expect(!!(!NS_FAILED_impl(requests->HasMoreElements
(&hasMore))), 1)))
&& hasMore) {
13379 nsCOMPtr<nsISupports> elem;
13380 requests->GetNext(getter_AddRefs(elem));
13381 nsCOMPtr<nsIScriptChannel> script = do_QueryInterface(elem);
13382 if (script) {
13383 nsCOMPtr<nsIRequest> request = do_QueryInterface(elem);
13384 MOZ_ASSERT(request)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(request)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(request))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("request", "./../../../docshell/base/nsDocShell.cpp"
, 13384); AnnotateMozCrashReason("MOZ_ASSERT" "(" "request" ")"
); do { MOZ_CrashSequence(__null, 13384); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
13385 mLoadGroup->CancelRequest(
13386 request, "nsDocShell::StopPendingJavascriptNavigations"_ns,
13387 NS_BINDING_ABORTED);
13388 }
13389 }
13390}