Bug Summary

File:root/firefox-clang/obj-x86_64-pc-linux-gnu/docshell/base/./../../../docshell/base/nsDocShell.cpp
Warning:line 3429, 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/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-10-17-231001-351276-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_mathml.h"
44#include "mozilla/StaticPrefs_network.h"
45#include "mozilla/StaticPrefs_privacy.h"
46#include "mozilla/StaticPrefs_security.h"
47#include "mozilla/StaticPrefs_ui.h"
48#include "mozilla/StaticPrefs_fission.h"
49#include "mozilla/StartupTimeline.h"
50#include "mozilla/StorageAccess.h"
51#include "mozilla/StoragePrincipalHelper.h"
52#include "mozilla/Telemetry.h"
53
54#include "mozilla/WidgetUtils.h"
55
56#include "mozilla/dom/AutoEntryScript.h"
57#include "mozilla/dom/ChildProcessChannelListener.h"
58#include "mozilla/dom/ClientChannelHelper.h"
59#include "mozilla/dom/ClientHandle.h"
60#include "mozilla/dom/ClientInfo.h"
61#include "mozilla/dom/ClientManager.h"
62#include "mozilla/dom/ClientSource.h"
63#include "mozilla/dom/ContentChild.h"
64#include "mozilla/dom/ContentFrameMessageManager.h"
65#include "mozilla/dom/DocGroup.h"
66#include "mozilla/dom/Element.h"
67#include "mozilla/dom/FragmentDirective.h"
68#include "mozilla/dom/HTMLAnchorElement.h"
69#include "mozilla/dom/HTMLIFrameElement.h"
70#include "mozilla/dom/Navigation.h"
71#include "mozilla/dom/NavigationBinding.h"
72#include "mozilla/dom/NavigationHistoryEntry.h"
73#include "mozilla/dom/NavigationUtils.h"
74#include "mozilla/dom/PerformanceNavigation.h"
75#include "mozilla/dom/PermissionMessageUtils.h"
76#include "mozilla/dom/PolicyContainer.h"
77#include "mozilla/dom/PopupBlocker.h"
78#include "mozilla/dom/ScreenOrientation.h"
79#include "mozilla/dom/ScriptSettings.h"
80#include "mozilla/dom/ServiceWorkerInterceptController.h"
81#include "mozilla/dom/ServiceWorkerUtils.h"
82#include "mozilla/dom/SessionHistoryEntry.h"
83#include "mozilla/dom/SessionStorageManager.h"
84#include "mozilla/dom/SessionStoreChangeListener.h"
85#include "mozilla/dom/SessionStoreChild.h"
86#include "mozilla/dom/SessionStoreUtils.h"
87#include "mozilla/dom/TrustedTypeUtils.h"
88#include "mozilla/dom/TrustedTypesConstants.h"
89#include "mozilla/dom/BrowserChild.h"
90#include "mozilla/dom/ToJSValue.h"
91#include "mozilla/dom/UserActivation.h"
92#include "mozilla/dom/ChildSHistory.h"
93#include "mozilla/dom/nsCSPContext.h"
94#include "mozilla/dom/nsHTTPSOnlyUtils.h"
95#include "mozilla/dom/LoadURIOptionsBinding.h"
96#include "mozilla/dom/JSWindowActorChild.h"
97#include "mozilla/dom/DocumentBinding.h"
98#include "mozilla/glean/DocshellMetrics.h"
99#include "mozilla/ipc/ProtocolUtils.h"
100#include "mozilla/net/DocumentChannel.h"
101#include "mozilla/net/DocumentChannelChild.h"
102#include "mozilla/net/ParentChannelWrapper.h"
103#include "mozilla/net/UrlClassifierFeatureFactory.h"
104#include "ReferrerInfo.h"
105
106#include "nsIAuthPrompt.h"
107#include "nsIAuthPrompt2.h"
108#include "nsICachingChannel.h"
109#include "nsICaptivePortalService.h"
110#include "nsIChannel.h"
111#include "nsIChannelEventSink.h"
112#include "nsIClassifiedChannel.h"
113#include "nsIClassOfService.h"
114#include "nsIConsoleReportCollector.h"
115#include "nsIContent.h"
116#include "nsIContentInlines.h"
117#include "nsIContentSecurityPolicy.h"
118#include "nsIController.h"
119#include "nsIDocShellTreeItem.h"
120#include "nsIDocShellTreeOwner.h"
121#include "nsIDocumentViewer.h"
122#include "mozilla/dom/Document.h"
123#include "nsHTMLDocument.h"
124#include "nsIDocumentLoaderFactory.h"
125#include "nsIDOMWindow.h"
126#include "nsIEditingSession.h"
127#include "nsIEffectiveTLDService.h"
128#include "nsExternalHelperAppService.h"
129#include "nsIExternalProtocolService.h"
130#include "nsIFormPOSTActionChannel.h"
131#include "nsIFrame.h"
132#include "nsIGlobalObject.h"
133#include "nsIHttpChannel.h"
134#include "nsIHttpChannelInternal.h"
135#include "nsIIDNService.h"
136#include "nsIInputStreamChannel.h"
137#include "nsIInterfaceRequestorUtils.h"
138#include "nsILayoutHistoryState.h"
139#include "nsILoadInfo.h"
140#include "nsILoadURIDelegate.h"
141#include "nsIMultiPartChannel.h"
142#include "nsINestedURI.h"
143#include "nsINode.h"
144#include "nsINSSErrorsService.h"
145#include "nsIObserverService.h"
146#include "nsIOService.h"
147#include "nsIPrincipal.h"
148#include "nsIPrivacyTransitionObserver.h"
149#include "nsIPrompt.h"
150#include "nsIPromptCollection.h"
151#include "nsIPromptFactory.h"
152#include "nsIPublicKeyPinningService.h"
153#include "nsIReflowObserver.h"
154#include "nsIScriptChannel.h"
155#include "nsIScriptObjectPrincipal.h"
156#include "nsIScriptSecurityManager.h"
157#include "nsScriptSecurityManager.h"
158#include "nsIScrollObserver.h"
159#include "nsISupportsPrimitives.h"
160#include "nsISecureBrowserUI.h"
161#include "nsISeekableStream.h"
162#include "nsISelectionDisplay.h"
163#include "nsISiteSecurityService.h"
164#include "nsISocketProvider.h"
165#include "nsIStringBundle.h"
166#include "nsIStructuredCloneContainer.h"
167#include "nsIBrowserChild.h"
168#include "nsITextToSubURI.h"
169#include "nsITimedChannel.h"
170#include "nsITimer.h"
171#include "nsITransportSecurityInfo.h"
172#include "nsIUploadChannel.h"
173#include "nsIURIFixup.h"
174#include "nsIURIMutator.h"
175#include "nsIURILoader.h"
176#include "nsIViewSourceChannel.h"
177#include "nsIWebBrowserChrome.h"
178#include "nsIWebBrowserFind.h"
179#include "nsIWebProgress.h"
180#include "nsIWidget.h"
181#include "nsIWindowWatcher.h"
182#include "nsIWritablePropertyBag2.h"
183#include "nsIX509Cert.h"
184#include "nsIXULRuntime.h"
185
186#include "nsCommandManager.h"
187#include "nsPIDOMWindow.h"
188#include "nsPIWindowRoot.h"
189
190#include "IHistory.h"
191#include "IUrlClassifierUITelemetry.h"
192
193#include "nsAboutProtocolUtils.h"
194#include "nsArray.h"
195#include "nsArrayUtils.h"
196#include "nsBrowserStatusFilter.h"
197#include "nsCExternalHandlerService.h"
198#include "nsContentDLF.h"
199#include "nsContentPolicyUtils.h" // NS_CheckContentLoadPolicy(...)
200#include "nsContentSecurityManager.h"
201#include "nsContentSecurityUtils.h"
202#include "nsContentUtils.h"
203#include "nsCURILoader.h"
204#include "nsDocElementCreatedNotificationRunner.h"
205#include "nsDocShellCID.h"
206#include "nsDocShellEditorData.h"
207#include "nsDocShellEnumerator.h"
208#include "nsDocShellLoadState.h"
209#include "nsDocShellLoadTypes.h"
210#include "nsDOMCID.h"
211#include "nsDOMNavigationTiming.h"
212#include "nsDSURIContentListener.h"
213#include "nsEditingSession.h"
214#include "nsError.h"
215#include "nsEscape.h"
216#include "nsFocusManager.h"
217#include "nsGlobalWindowInner.h"
218#include "nsGlobalWindowOuter.h"
219#include "nsJSEnvironment.h"
220#include "nsNetCID.h"
221#include "nsNetUtil.h"
222#include "nsObjectLoadingContent.h"
223#include "nsPIDOMWindowInlines.h"
224#include "nsPingListener.h"
225#include "nsPoint.h"
226#include "nsQueryObject.h"
227#include "nsQueryActor.h"
228#include "nsRect.h"
229#include "nsRefreshTimer.h"
230#include "nsSandboxFlags.h"
231#include "nsSHistory.h"
232#include "nsStructuredCloneContainer.h"
233#include "nsSubDocumentFrame.h"
234#include "nsURILoader.h"
235#include "nsURLHelper.h"
236#include "nsViewSourceHandler.h"
237#include "nsWebBrowserFind.h"
238#include "nsWhitespaceTokenizer.h"
239#include "nsWidgetsCID.h"
240#include "nsXULAppAPI.h"
241
242#include "CertVerifier.h"
243#include "ThirdPartyUtil.h"
244#include "GeckoProfiler.h"
245#include "mozilla/NullPrincipal.h"
246#include "Navigator.h"
247#include "prenv.h"
248#include "mozilla/ipc/URIUtils.h"
249#include "sslerr.h"
250#include "mozpkix/pkix.h"
251#include "NSSErrorsService.h"
252
253#include "nsDocShellTelemetryUtils.h"
254
255#include "nsIOpenWindowInfo.h"
256
257#ifdef MOZ_PLACES1
258# include "mozilla/places/nsFaviconService.h"
259# include "mozIPlacesPendingOperation.h"
260#endif
261
262#include "nsIDocumentViewerPrint.h"
263#include "nsIWebBrowserPrint.h"
264
265using namespace mozilla;
266using namespace mozilla::dom;
267using namespace mozilla::net;
268
269using mozilla::ipc::Endpoint;
270
271// Threshold value in ms for META refresh based redirects
272#define REFRESH_REDIRECT_TIMER15000 15000
273
274static mozilla::LazyLogModule gCharsetMenuLog("CharsetMenu");
275static mozilla::LazyLogModule gDocShellLog("nsDocShell");
276
277#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)
\
278 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)
279
280#ifdef DEBUG1
281unsigned long nsDocShell::gNumberOfDocShells = 0;
282static uint64_t gDocshellIDCounter = 0;
283
284static mozilla::LazyLogModule gDocShellAndDOMWindowLeakLogging(
285 "DocShellAndDOMWindowLeak");
286#endif
287static mozilla::LazyLogModule gDocShellLeakLog("nsDocShellLeak");
288extern mozilla::LazyLogModule gPageCacheLog;
289extern mozilla::LazyLogModule gNavigationAPILog;
290mozilla::LazyLogModule gSHLog("SessionHistory");
291extern mozilla::LazyLogModule gSHIPBFCacheLog;
292
293const char kAppstringsBundleURL[] =
294 "chrome://global/locale/appstrings.properties";
295
296static bool IsTopLevelDoc(BrowsingContext* aBrowsingContext,
297 nsILoadInfo* aLoadInfo) {
298 MOZ_ASSERT(aBrowsingContext)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aBrowsingContext)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aBrowsingContext))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("aBrowsingContext"
, "./../../../docshell/base/nsDocShell.cpp", 298); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aBrowsingContext" ")"); do { MOZ_CrashSequence
(__null, 298); __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
299 MOZ_ASSERT(aLoadInfo)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aLoadInfo)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aLoadInfo))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aLoadInfo", "./../../../docshell/base/nsDocShell.cpp"
, 299); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadInfo" ")"
); do { MOZ_CrashSequence(__null, 299); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
300
301 if (aLoadInfo->GetExternalContentPolicyType() !=
302 ExtContentPolicy::TYPE_DOCUMENT) {
303 return false;
304 }
305
306 return aBrowsingContext->IsTopContent();
307}
308
309// True if loading for top level document loading in active tab.
310static bool IsUrgentStart(BrowsingContext* aBrowsingContext,
311 nsILoadInfo* aLoadInfo, uint32_t aLoadType) {
312 MOZ_ASSERT(aBrowsingContext)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aBrowsingContext)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aBrowsingContext))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("aBrowsingContext"
, "./../../../docshell/base/nsDocShell.cpp", 312); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aBrowsingContext" ")"); do { MOZ_CrashSequence
(__null, 312); __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
313 MOZ_ASSERT(aLoadInfo)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aLoadInfo)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aLoadInfo))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aLoadInfo", "./../../../docshell/base/nsDocShell.cpp"
, 313); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadInfo" ")"
); do { MOZ_CrashSequence(__null, 313); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
314
315 if (!IsTopLevelDoc(aBrowsingContext, aLoadInfo)) {
316 return false;
317 }
318
319 if (aLoadType &
320 (nsIDocShell::LOAD_CMD_NORMAL | nsIDocShell::LOAD_CMD_HISTORY)) {
321 return true;
322 }
323
324 return aBrowsingContext->IsActive();
325}
326
327nsDocShell::nsDocShell(BrowsingContext* aBrowsingContext,
328 uint64_t aContentWindowID)
329 : nsDocLoader(true),
330 mContentWindowID(aContentWindowID),
331 mBrowsingContext(aBrowsingContext),
332 mParentCharset(nullptr),
333 mTreeOwner(nullptr),
334 mScrollbarPref(ScrollbarPreference::Auto),
335 mCharsetReloadState(eCharsetReloadInit),
336 mParentCharsetSource(0),
337 mFrameMargins(-1, -1),
338 mItemType(aBrowsingContext->IsContent() ? typeContent : typeChrome),
339 mPreviousEntryIndex(-1),
340 mLoadedEntryIndex(-1),
341 mBusyFlags(BUSY_FLAGS_NONE),
342 mAppType(nsIDocShell::APP_TYPE_UNKNOWN),
343 mLoadType(0),
344 mFailedLoadType(0),
345 mChannelToDisconnectOnPageHide(0),
346 mCreatingDocument(false),
347#ifdef DEBUG1
348 mInEnsureScriptEnv(false),
349#endif
350 mInitialized(false),
351 mAllowSubframes(true),
352 mAllowMetaRedirects(true),
353 mAllowImages(true),
354 mAllowMedia(true),
355 mAllowDNSPrefetch(true),
356 mAllowWindowControl(true),
357 mCSSErrorReportingEnabled(false),
358 mAllowAuth(mItemType == typeContent),
359 mAllowKeywordFixup(false),
360 mDisableMetaRefreshWhenInactive(false),
361 mWindowDraggingAllowed(false),
362 mInFrameSwap(false),
363 mFiredUnloadEvent(false),
364 mEODForCurrentDocument(false),
365 mURIResultedInDocument(false),
366 mIsBeingDestroyed(false),
367 mIsExecutingOnLoadHandler(false),
368 mInvisible(false),
369 mHasLoadedNonBlankURI(false),
370 mHasStartedLoadingOtherThanInitialBlankURI(false),
371 mBlankTiming(false),
372 mTitleValidForCurrentURI(false),
373 mWillChangeProcess(false),
374 mIsNavigating(false),
375 mForcedAutodetection(false),
376 mCheckingSessionHistory(false),
377 mNeedToReportActiveAfterLoadingBecomesActive(false) {
378 // If no outer window ID was provided, generate a new one.
379 if (aContentWindowID == 0) {
380 mContentWindowID = nsContentUtils::GenerateWindowId();
381 }
382
383 MOZ_LOG(gDocShellLeakLog, LogLevel::Debug, ("DOCSHELL %p created\n", this))do { const ::mozilla::LogModule* moz_real_module = gDocShellLeakLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "DOCSHELL %p created\n", this); } } while (
0)
;
384
385#ifdef DEBUG1
386 mDocShellID = gDocshellIDCounter++;
387 // We're counting the number of |nsDocShells| to help find leaks
388 ++gNumberOfDocShells;
389 MOZ_LOG(gDocShellAndDOMWindowLeakLogging, LogLevel::Info,do { const ::mozilla::LogModule* moz_real_module = gDocShellAndDOMWindowLeakLogging
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Info, "++DOCSHELL %p == %ld [pid = %d] [id = %" "l"
"u" "]\n", (void*)this, gNumberOfDocShells, getpid(), mDocShellID
); } } while (0)
390 ("++DOCSHELL %p == %ld [pid = %d] [id = %" PRIu64 "]\n", (void*)this,do { const ::mozilla::LogModule* moz_real_module = gDocShellAndDOMWindowLeakLogging
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Info, "++DOCSHELL %p == %ld [pid = %d] [id = %" "l"
"u" "]\n", (void*)this, gNumberOfDocShells, getpid(), mDocShellID
); } } while (0)
391 gNumberOfDocShells, getpid(), mDocShellID))do { const ::mozilla::LogModule* moz_real_module = gDocShellAndDOMWindowLeakLogging
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Info, "++DOCSHELL %p == %ld [pid = %d] [id = %" "l"
"u" "]\n", (void*)this, gNumberOfDocShells, getpid(), mDocShellID
); } } while (0)
;
392#endif
393}
394
395void nsDocShell::DestroyDocumentViewer() {
396 if (!mDocumentViewer) {
397 return;
398 }
399 mDocumentViewer->Close();
400 mDocumentViewer->Destroy();
401 mDocumentViewer = nullptr;
402}
403
404nsDocShell::~nsDocShell() {
405 // Avoid notifying observers while we're in the dtor.
406 mIsBeingDestroyed = true;
407
408 Destroy();
409
410 DestroyDocumentViewer();
411
412 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)
;
413
414#ifdef DEBUG1
415 if (MOZ_LOG_TEST(gDocShellAndDOMWindowLeakLogging, LogLevel::Info)(__builtin_expect(!!(mozilla::detail::log_test(gDocShellAndDOMWindowLeakLogging
, LogLevel::Info)), 0))
) {
416 nsAutoCString url;
417 if (mLastOpenedURI) {
418 url = mLastOpenedURI->GetSpecOrDefault();
419
420 // Data URLs can be very long, so truncate to avoid flooding the log.
421 const uint32_t maxURLLength = 1000;
422 if (url.Length() > maxURLLength) {
423 url.Truncate(maxURLLength);
424 }
425 }
426
427 // We're counting the number of |nsDocShells| to help find leaks
428 --gNumberOfDocShells;
429 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)
430 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)
431 ("--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)
432 (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)
;
433 }
434#endif
435}
436
437nsresult nsDocShell::InitWindow(nsIWidget* aParentWidget, int32_t aX,
438 int32_t aY, int32_t aWidth, int32_t aHeight,
439 nsIOpenWindowInfo* aOpenWindowInfo,
440 mozilla::dom::WindowGlobalChild* aWindowActor) {
441 SetParentWidget(aParentWidget);
442 SetPositionAndSize(aX, aY, aWidth, aHeight, 0);
443 return Initialize(aOpenWindowInfo, aWindowActor);
444}
445
446nsresult nsDocShell::Initialize(nsIOpenWindowInfo* aOpenWindowInfo,
447 mozilla::dom::WindowGlobalChild* aWindowActor) {
448 if (mInitialized) {
449 // We've already been initialized.
450 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"
, 451); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aOpenWindowInfo"
") (" "Tried to reinitialize with override principal" ")"); do
{ MOZ_CrashSequence(__null, 451); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
451 "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"
, 451); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aOpenWindowInfo"
") (" "Tried to reinitialize with override principal" ")"); do
{ MOZ_CrashSequence(__null, 451); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
452 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"
, 452); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aWindowActor"
") (" "Tried to reinitialize with a window actor" ")"); do {
MOZ_CrashSequence(__null, 452); __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
;
453 return NS_OK;
454 }
455
456 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", 457); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aOpenWindowInfo" ") (" "Must have openwindowinfo if not already initialized."
")"); do { MOZ_CrashSequence(__null, 457); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
457 "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", 457); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aOpenWindowInfo" ") (" "Must have openwindowinfo if not already initialized."
")"); do { MOZ_CrashSequence(__null, 457); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
458
459 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"
, 460); MOZ_PretendNoReturn(); } } while (0)
460 "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"
, 460); MOZ_PretendNoReturn(); } } while (0)
;
461
462 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"
, 462); return NS_ERROR_NOT_INITIALIZED; } } while (false)
;
463 mInitialized = true;
464
465 mDisableMetaRefreshWhenInactive =
466 Preferences::GetBool("browser.meta_refresh_when_inactive.disabled",
467 mDisableMetaRefreshWhenInactive);
468
469 nsresult rv = CreateInitialDocumentViewer(aOpenWindowInfo, aWindowActor);
470
471 if (nsCOMPtr<nsIObserverService> serv = services::GetObserverService()) {
472 const char* msg = mItemType == typeContent ? NS_WEBNAVIGATION_CREATE"webnavigation-create"
473 : NS_CHROME_WEBNAVIGATION_CREATE"chrome-webnavigation-create";
474 serv->NotifyWhenScriptSafe(GetAsSupports(this), msg, nullptr);
475 }
476
477 return rv;
478}
479
480/* static */
481already_AddRefed<nsDocShell> nsDocShell::Create(
482 BrowsingContext* aBrowsingContext, uint64_t aContentWindowID) {
483 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"
, 483); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aBrowsingContext"
") (" "DocShell without a BrowsingContext!" ")"); do { MOZ_CrashSequence
(__null, 483); __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
484
485 nsresult rv;
486 RefPtr<nsDocShell> ds = new nsDocShell(aBrowsingContext, aContentWindowID);
487
488 // Initialize the underlying nsDocLoader.
489 rv = ds->nsDocLoader::InitWithBrowsingContext(aBrowsingContext);
490 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"
, 490)
) {
491 return nullptr;
492 }
493
494 // Create our ContentListener
495 ds->mContentListener = new nsDSURIContentListener(ds);
496
497 // We enable if we're in the parent process in order to support non-e10s
498 // configurations.
499 // Note: This check is duplicated in SharedWorkerInterfaceRequestor's
500 // constructor.
501 if (XRE_IsParentProcess()) {
502 ds->mInterceptController = MakeRefPtr<ServiceWorkerInterceptController>();
503 }
504
505 // We want to hold a strong ref to the loadgroup, so it better hold a weak
506 // ref to us... use an InterfaceRequestorProxy to do this.
507 RefPtr proxy = MakeRefPtr<InterfaceRequestorProxy>(ds);
508 ds->mLoadGroup->SetNotificationCallbacks(proxy);
509
510 // XXX(nika): We have our BrowsingContext, so we might be able to skip this.
511 // It could be nice to directly set up our DocLoader tree?
512 rv = nsDocLoader::AddDocLoaderAsChildOfRoot(ds);
513 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"
, 513)
) {
514 return nullptr;
515 }
516
517 uint32_t notifyMask =
518 nsIWebProgress::NOTIFY_STATE_ALL | nsIWebProgress::NOTIFY_LOCATION |
519 nsIWebProgress::NOTIFY_SECURITY | nsIWebProgress::NOTIFY_STATUS;
520
521 // NOTE: Only listen for NOTIFY_PROGRESS on toplevel BrowsingContexts, as
522 // listeners in the browser UI only cares about total progress on the toplevel
523 // context. Aggregation of the total progress is currently handled within
524 // `nsDocLoader`, and does not take out-of-process iframes into account.
525 if (aBrowsingContext->IsTop()) {
526 notifyMask |= nsIWebProgress::NOTIFY_PROGRESS;
527 }
528
529 // Add |ds| as a progress listener to itself. A little weird, but simpler
530 // than reproducing all the listener-notification logic in overrides of the
531 // various methods via which nsDocLoader can be notified. Note that this
532 // holds an nsWeakPtr to |ds|, so it's ok.
533 rv = ds->AddProgressListener(ds, notifyMask);
534 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"
, 534)
) {
535 return nullptr;
536 }
537
538 // If our BrowsingContext has private browsing enabled, update the number of
539 // private browsing docshells.
540 if (aBrowsingContext->UsePrivateBrowsing()) {
541 ds->NotifyPrivateBrowsingChanged();
542 }
543
544 // If our parent window is present in this process, set up our parent now.
545 RefPtr<WindowContext> parentWC = aBrowsingContext->GetParentWindowContext();
546 if (parentWC && parentWC->IsInProcess()) {
547 // If we don't have a parent element anymore, we can't finish this load!
548 // How'd we get here?
549 RefPtr<Element> parentElement = aBrowsingContext->GetEmbedderElement();
550 if (!parentElement) {
551 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"
, 551); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "nsDocShell::Create() - !parentElement"
")"); do { MOZ_CrashSequence(__null, 551); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
552 return nullptr;
553 }
554
555 // We have an in-process parent window, but don't have a parent nsDocShell?
556 // How'd we get here!
557 nsCOMPtr<nsIDocShell> parentShell =
558 parentElement->OwnerDoc()->GetDocShell();
559 if (!parentShell) {
560 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"
, 560); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "nsDocShell::Create() - !parentShell"
")"); do { MOZ_CrashSequence(__null, 560); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
561 return nullptr;
562 }
563 parentShell->AddChild(ds);
564 }
565
566 // Make |ds| the primary DocShell for the given context.
567 aBrowsingContext->SetDocShell(ds);
568
569 // Set |ds| default load flags on load group.
570 ds->SetLoadGroupDefaultLoadFlags(aBrowsingContext->GetDefaultLoadFlags());
571
572 return ds.forget();
573}
574
575void nsDocShell::DestroyChildren() {
576 for (auto* child : mChildList.ForwardRange()) {
577 nsCOMPtr<nsIDocShellTreeItem> shell = do_QueryObject(child);
578 NS_ASSERTION(shell, "docshell has null child")do { if (!(shell)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "docshell has null child"
, "shell", "./../../../docshell/base/nsDocShell.cpp", 578); MOZ_PretendNoReturn
(); } } while (0)
;
579
580 if (shell) {
581 shell->SetTreeOwner(nullptr);
582 }
583 }
584
585 nsDocLoader::DestroyChildren();
586}
587
588NS_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; }
589 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; }
590 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; }
591 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; }
592 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; }
593
594NS_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; }
595NS_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; }
596
597NS_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", 597
); 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
598 NS_INTERFACE_MAP_ENTRY(nsIDocShell)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIDocShell>)) foundInterface = static_cast
<nsIDocShell*>(this); else
599 NS_INTERFACE_MAP_ENTRY(nsIDocShellTreeItem)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIDocShellTreeItem>)) foundInterface
= static_cast<nsIDocShellTreeItem*>(this); else
600 NS_INTERFACE_MAP_ENTRY(nsIWebNavigation)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIWebNavigation>)) foundInterface
= static_cast<nsIWebNavigation*>(this); else
601 NS_INTERFACE_MAP_ENTRY(nsIBaseWindow)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIBaseWindow>)) foundInterface =
static_cast<nsIBaseWindow*>(this); else
602 NS_INTERFACE_MAP_ENTRY(nsIRefreshURI)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIRefreshURI>)) foundInterface =
static_cast<nsIRefreshURI*>(this); else
603 NS_INTERFACE_MAP_ENTRY(nsIWebProgressListener)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIWebProgressListener>)) foundInterface
= static_cast<nsIWebProgressListener*>(this); else
604 NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsISupportsWeakReference>)) foundInterface
= static_cast<nsISupportsWeakReference*>(this); else
605 NS_INTERFACE_MAP_ENTRY(nsIWebPageDescriptor)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIWebPageDescriptor>)) foundInterface
= static_cast<nsIWebPageDescriptor*>(this); else
606 NS_INTERFACE_MAP_ENTRY(nsIAuthPromptProvider)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIAuthPromptProvider>)) foundInterface
= static_cast<nsIAuthPromptProvider*>(this); else
607 NS_INTERFACE_MAP_ENTRY(nsILoadContext)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsILoadContext>)) foundInterface =
static_cast<nsILoadContext*>(this); else
608 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
609 mInterceptController)if ((mInterceptController) && aIID.Equals(mozilla::detail
::kImplementedIID<std::remove_reference_t<decltype(*this
)>, nsINetworkInterceptController>)) foundInterface = static_cast
<nsINetworkInterceptController*>(this); else
610NS_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; }
611
612NS_IMETHODIMPnsresult
613nsDocShell::GetInterface(const nsIID& aIID, void** aSink) {
614 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", 614); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aSink" ") (" "null out param" ")"); do { MOZ_CrashSequence
(__null, 614); __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
615
616 *aSink = nullptr;
617
618 if (aIID.Equals(NS_GET_IID(nsICommandManager)(nsICommandManager::kIID))) {
619 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", 619); return NS_ERROR_FAILURE
; } } while (false)
;
620 *aSink = static_cast<nsICommandManager*>(mCommandManager.get());
621 } else if (aIID.Equals(NS_GET_IID(nsIURIContentListener)(nsIURIContentListener::kIID))) {
622 *aSink = mContentListener;
623 } else if ((aIID.Equals(NS_GET_IID(nsIScriptGlobalObject)(nsIScriptGlobalObject::kIID)) ||
624 aIID.Equals(NS_GET_IID(nsIGlobalObject)(nsIGlobalObject::kIID)) ||
625 aIID.Equals(NS_GET_IID(nsPIDOMWindowOuter)(nsPIDOMWindowOuter::kIID)) ||
626 aIID.Equals(NS_GET_IID(mozIDOMWindowProxy)(mozIDOMWindowProxy::kIID)) ||
627 aIID.Equals(NS_GET_IID(nsIDOMWindow)(nsIDOMWindow::kIID))) &&
628 NS_SUCCEEDED(EnsureScriptEnvironment())((bool)(__builtin_expect(!!(!NS_FAILED_impl(EnsureScriptEnvironment
())), 1)))
) {
629 return mScriptGlobal->QueryInterface(aIID, aSink);
630 } else if (aIID.Equals(NS_GET_IID(Document)(Document::kIID)) && VerifyDocumentViewer()) {
631 RefPtr<Document> doc = mDocumentViewer->GetDocument();
632 doc.forget(aSink);
633 return *aSink ? NS_OK : NS_NOINTERFACE;
634 } else if (aIID.Equals(NS_GET_IID(nsIPrompt)(nsIPrompt::kIID)) &&
635 NS_SUCCEEDED(EnsureScriptEnvironment())((bool)(__builtin_expect(!!(!NS_FAILED_impl(EnsureScriptEnvironment
())), 1)))
) {
636 nsresult rv;
637 nsCOMPtr<nsIWindowWatcher> wwatch =
638 do_GetService(NS_WINDOWWATCHER_CONTRACTID"@mozilla.org/embedcomp/window-watcher;1", &rv);
639 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"
, 639); return rv; } } while (false)
;
640
641 // Get the an auth prompter for our window so that the parenting
642 // of the dialogs works as it should when using tabs.
643 nsIPrompt* prompt;
644 rv = wwatch->GetNewPrompter(mScriptGlobal, &prompt);
645 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"
, 645); return rv; } } while (false)
;
646
647 *aSink = prompt;
648 return NS_OK;
649 } else if (aIID.Equals(NS_GET_IID(nsIAuthPrompt)(nsIAuthPrompt::kIID)) ||
650 aIID.Equals(NS_GET_IID(nsIAuthPrompt2)(nsIAuthPrompt2::kIID))) {
651 return NS_SUCCEEDED(GetAuthPrompt(PROMPT_NORMAL, aIID, aSink))((bool)(__builtin_expect(!!(!NS_FAILED_impl(GetAuthPrompt(PROMPT_NORMAL
, aIID, aSink))), 1)))
652 ? NS_OK
653 : NS_NOINTERFACE;
654 } else if (aIID.Equals(NS_GET_IID(nsISHistory)(nsISHistory::kIID))) {
655 // This is deprecated, you should instead directly get
656 // ChildSHistory from the browsing context.
657 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", 658); AnnotateMozCrashReason
("MOZ_DIAGNOSTIC_ASSERT" "(" "false" ") (" "Do not try to get a nsISHistory interface from nsIDocShell"
")"); do { MOZ_CrashSequence(__null, 658); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
658 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", 658); AnnotateMozCrashReason
("MOZ_DIAGNOSTIC_ASSERT" "(" "false" ") (" "Do not try to get a nsISHistory interface from nsIDocShell"
")"); do { MOZ_CrashSequence(__null, 658); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
659 return NS_NOINTERFACE;
660 } else if (aIID.Equals(NS_GET_IID(nsIWebBrowserFind)(nsIWebBrowserFind::kIID))) {
661 nsresult rv = EnsureFind();
662 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
663 return rv;
664 }
665
666 *aSink = mFind;
667 NS_ADDREF((nsISupports*)*aSink)((nsISupports*)*aSink)->AddRef();
668 return NS_OK;
669 } else if (aIID.Equals(NS_GET_IID(nsISelectionDisplay)(nsISelectionDisplay::kIID))) {
670 if (PresShell* presShell = GetPresShell()) {
671 return presShell->QueryInterface(aIID, aSink);
672 }
673 } else if (aIID.Equals(NS_GET_IID(nsIDocShellTreeOwner)(nsIDocShellTreeOwner::kIID))) {
674 nsCOMPtr<nsIDocShellTreeOwner> treeOwner;
675 nsresult rv = GetTreeOwner(getter_AddRefs(treeOwner));
676 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && treeOwner) {
677 return treeOwner->QueryInterface(aIID, aSink);
678 }
679 } else if (aIID.Equals(NS_GET_IID(nsIBrowserChild)(nsIBrowserChild::kIID))) {
680 *aSink = GetBrowserChild().take();
681 return *aSink ? NS_OK : NS_ERROR_FAILURE;
682 } else {
683 return nsDocLoader::GetInterface(aIID, aSink);
684 }
685
686 NS_IF_ADDREF(((nsISupports*)*aSink))ns_if_addref(((nsISupports*)*aSink));
687 return *aSink ? NS_OK : NS_NOINTERFACE;
688}
689
690NS_IMETHODIMPnsresult
691nsDocShell::SetCancelContentJSEpoch(int32_t aEpoch) {
692 // Note: this gets called fairly early (before a pageload actually starts).
693 // We could probably defer this even longer.
694 nsCOMPtr<nsIBrowserChild> browserChild = GetBrowserChild();
695 static_cast<BrowserChild*>(browserChild.get())
696 ->SetCancelContentJSEpoch(aEpoch);
697 return NS_OK;
698}
699
700nsresult nsDocShell::CheckDisallowedJavascriptLoad(
701 nsDocShellLoadState* aLoadState) {
702 if (!aLoadState->URI()->SchemeIs("javascript")) {
703 return NS_OK;
704 }
705
706 if (nsCOMPtr<nsIPrincipal> targetPrincipal =
707 GetInheritedPrincipal(/* aConsiderCurrentDocument */ true)) {
708 if (!aLoadState->TriggeringPrincipal()->Subsumes(targetPrincipal)) {
709 return NS_ERROR_DOM_BAD_CROSS_ORIGIN_URI;
710 }
711 return NS_OK;
712 }
713 return NS_ERROR_DOM_BAD_CROSS_ORIGIN_URI;
714}
715
716NS_IMETHODIMPnsresult
717nsDocShell::LoadURI(nsDocShellLoadState* aLoadState, bool aSetNavigating) {
718 return LoadURI(aLoadState, aSetNavigating, false);
719}
720
721nsresult nsDocShell::LoadURI(nsDocShellLoadState* aLoadState,
722 bool aSetNavigating,
723 bool aContinueHandlingSubframeHistory) {
724 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", 724); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aLoadState" ") (" "Must have a valid load state!"
")"); do { MOZ_CrashSequence(__null, 724); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
725 // NOTE: This comparison between what appears to be internal/external load
726 // flags is intentional, as it's ensuring that the caller isn't using any of
727 // the flags reserved for implementations by the `nsIWebNavigation` interface.
728 // In the future, this check may be dropped.
729 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"
, 731); AnnotateMozCrashReason("MOZ_ASSERT" "(" "(aLoadState->LoadFlags() & INTERNAL_LOAD_FLAGS_LOADURI_SETUP_FLAGS) == 0"
") (" "Should not have these flags set" ")"); do { MOZ_CrashSequence
(__null, 731); __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
730 (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"
, 731); AnnotateMozCrashReason("MOZ_ASSERT" "(" "(aLoadState->LoadFlags() & INTERNAL_LOAD_FLAGS_LOADURI_SETUP_FLAGS) == 0"
") (" "Should not have these flags set" ")"); do { MOZ_CrashSequence
(__null, 731); __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
731 "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"
, 731); AnnotateMozCrashReason("MOZ_ASSERT" "(" "(aLoadState->LoadFlags() & INTERNAL_LOAD_FLAGS_LOADURI_SETUP_FLAGS) == 0"
") (" "Should not have these flags set" ")"); do { MOZ_CrashSequence
(__null, 731); __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
732 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"
, 733); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->TargetBrowsingContext().IsNull()"
") (" "Targeting doesn't occur until InternalLoad" ")"); do {
MOZ_CrashSequence(__null, 733); __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
733 "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"
, 733); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->TargetBrowsingContext().IsNull()"
") (" "Targeting doesn't occur until InternalLoad" ")"); do {
MOZ_CrashSequence(__null, 733); __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
;
734
735 if (!aLoadState->TriggeringPrincipal()) {
736 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", 736); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "false" ") (" "LoadURI must have a triggering principal"
")"); do { MOZ_CrashSequence(__null, 736); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
737 return NS_ERROR_FAILURE;
738 }
739
740 MOZ_TRY(CheckDisallowedJavascriptLoad(aLoadState))__extension__({ auto mozTryVarTempResult = ::mozilla::ToResult
(CheckDisallowedJavascriptLoad(aLoadState)); if ((__builtin_expect
(!!(mozTryVarTempResult.isErr()), 0))) { return mozTryVarTempResult
.propagateErr(); } mozTryVarTempResult.unwrap(); })
;
741
742 bool oldIsNavigating = mIsNavigating;
743 auto cleanupIsNavigating =
744 MakeScopeExit([&]() { mIsNavigating = oldIsNavigating; });
745 if (aSetNavigating) {
746 mIsNavigating = true;
747 }
748
749 PopupBlocker::PopupControlState popupState = PopupBlocker::openOverridden;
750 if (aLoadState->HasLoadFlags(LOAD_FLAGS_ALLOW_POPUPS)) {
751 popupState = PopupBlocker::openAllowed;
752 // If we allow popups as part of the navigation, ensure we fake a user
753 // interaction, so that popups can, in fact, be allowed to open.
754 if (WindowContext* wc = mBrowsingContext->GetCurrentWindowContext()) {
755 wc->NotifyUserGestureActivation();
756 }
757 }
758
759 AutoPopupStatePusherAutoPopupStatePusherInternal statePusher(popupState);
760
761 if (aLoadState->GetCancelContentJSEpoch().isSome()) {
762 SetCancelContentJSEpoch(*aLoadState->GetCancelContentJSEpoch());
763 }
764
765 // Note: we allow loads to get through here even if mFiredUnloadEvent is
766 // true; that case will get handled in LoadInternal or LoadHistoryEntry,
767 // so we pass false as the second parameter to IsNavigationAllowed.
768 // However, we don't allow the page to change location *in the middle of*
769 // firing beforeunload, so we do need to check if *beforeunload* is currently
770 // firing, so we call IsNavigationAllowed rather than just IsPrintingOrPP.
771 if (!IsNavigationAllowed(true, false)) {
772 return NS_OK; // JS may not handle returning of an error code
773 }
774
775 nsLoadFlags defaultLoadFlags = mBrowsingContext->GetDefaultLoadFlags();
776 if (aLoadState->HasLoadFlags(LOAD_FLAGS_FORCE_TRR)) {
777 defaultLoadFlags |= nsIRequest::LOAD_TRR_ONLY_MODE;
778 } else if (aLoadState->HasLoadFlags(LOAD_FLAGS_DISABLE_TRR)) {
779 defaultLoadFlags |= nsIRequest::LOAD_TRR_DISABLED_MODE;
780 }
781
782 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", 782); AnnotateMozCrashReason
("MOZ_CRASH(" "NS_SUCCEEDED(mBrowsingContext->SetDefaultLoadFlags(defaultLoadFlags))"
")"); do { MOZ_CrashSequence(__null, 782); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
;
783
784 if (!StartupTimeline::HasRecord(StartupTimeline::FIRST_LOAD_URI) &&
785 mItemType == typeContent && !NS_IsAboutBlank(aLoadState->URI())) {
786 StartupTimeline::RecordOnce(StartupTimeline::FIRST_LOAD_URI);
787 }
788
789 // LoadType used to be set to a default value here, if no LoadInfo/LoadState
790 // object was passed in. That functionality has been removed as of bug
791 // 1492648. LoadType should now be set up by the caller at the time they
792 // create their nsDocShellLoadState object to pass into LoadURI.
793
794 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)
795 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)
796 ("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)
797 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)
;
798
799 if ((!aLoadState->LoadIsFromSessionHistory() &&
800 !LOAD_TYPE_HAS_FLAGS(aLoadState->LoadType(),((aLoadState->LoadType()) & ((LOAD_FLAGS_REPLACE_HISTORY
) << 16))
801 LOAD_FLAGS_REPLACE_HISTORY)((aLoadState->LoadType()) & ((LOAD_FLAGS_REPLACE_HISTORY
) << 16))
) ||
802 aContinueHandlingSubframeHistory) {
803 // This is possibly a subframe, so handle it accordingly.
804 //
805 // If history exists, it will be loaded into the aLoadState object, and the
806 // LoadType will be changed.
807 if (MaybeHandleSubframeHistory(aLoadState,
808 aContinueHandlingSubframeHistory)) {
809 // MaybeHandleSubframeHistory returns true if we need to continue loading
810 // asynchronously.
811 return NS_OK;
812 }
813 }
814
815 if (aLoadState->LoadIsFromSessionHistory()) {
816 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)
817 ("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)
;
818
819 // FIXME Null check aLoadState->GetLoadingSessionHistoryInfo()?
820 return LoadHistoryEntry(*aLoadState->GetLoadingSessionHistoryInfo(),
821 aLoadState->LoadType(),
822 aLoadState->HasValidUserGestureActivation(),
823 aLoadState->NotifiedBeforeUnloadListeners(),
824 aLoadState->IsResumingInterceptedNavigation());
825 }
826
827 // On history navigation via Back/Forward buttons, don't execute
828 // automatic JavaScript redirection such as |location.href = ...| or
829 // |window.open()|
830 //
831 // LOAD_NORMAL: window.open(...) etc.
832 // LOAD_STOP_CONTENT: location.href = ..., location.assign(...)
833 if ((aLoadState->LoadType() == LOAD_NORMAL ||
834 aLoadState->LoadType() == LOAD_STOP_CONTENT) &&
835 ShouldBlockLoadingForBackButton()) {
836 return NS_OK;
837 }
838
839 BrowsingContext::Type bcType = mBrowsingContext->GetType();
840
841 // Set up the inheriting principal in LoadState.
842 nsresult rv = aLoadState->SetupInheritingPrincipal(
843 bcType, mBrowsingContext->OriginAttributesRef());
844 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"
, 844); return rv; } } while (false)
;
845
846 rv = aLoadState->SetupTriggeringPrincipal(
847 mBrowsingContext->OriginAttributesRef());
848 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"
, 848); return rv; } } while (false)
;
849
850 aLoadState->CalculateLoadURIFlags();
851
852 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", 853); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aLoadState->TypeHint().IsVoid()" ") (" "Typehint should be null when calling InternalLoad from LoadURI"
")"); do { MOZ_CrashSequence(__null, 853); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
853 "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", 853); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aLoadState->TypeHint().IsVoid()" ") (" "Typehint should be null when calling InternalLoad from LoadURI"
")"); do { MOZ_CrashSequence(__null, 853); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
854 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", 855); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aLoadState->FileName().IsVoid()" ") (" "FileName should be null when calling InternalLoad from LoadURI"
")"); do { MOZ_CrashSequence(__null, 855); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
855 "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", 855); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aLoadState->FileName().IsVoid()" ") (" "FileName should be null when calling InternalLoad from LoadURI"
")"); do { MOZ_CrashSequence(__null, 855); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
856 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"
, 858); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aLoadState->LoadIsFromSessionHistory()"
") (" "Shouldn't be loading from an entry when calling InternalLoad "
"from LoadURI" ")"); do { MOZ_CrashSequence(__null, 858); __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
857 "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"
, 858); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aLoadState->LoadIsFromSessionHistory()"
") (" "Shouldn't be loading from an entry when calling InternalLoad "
"from LoadURI" ")"); do { MOZ_CrashSequence(__null, 858); __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
858 "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"
, 858); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aLoadState->LoadIsFromSessionHistory()"
") (" "Shouldn't be loading from an entry when calling InternalLoad "
"from LoadURI" ")"); do { MOZ_CrashSequence(__null, 858); __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
;
859
860 // If we have a system triggering principal, we can assume that this load was
861 // triggered by some UI in the browser chrome, such as the URL bar or
862 // bookmark bar. This should count as a user interaction for the current sh
863 // entry, so that the user may navigate back to the current entry, from the
864 // entry that is going to be added as part of this load.
865 nsCOMPtr<nsIPrincipal> triggeringPrincipal =
866 aLoadState->TriggeringPrincipal();
867 if (triggeringPrincipal && triggeringPrincipal->IsSystemPrincipal()) {
868 WindowContext* topWc = mBrowsingContext->GetTopWindowContext();
869 // Already set by BrowsingContext::LoadURI for a parent initiated load;
870 // notifying again could flag the entry this load is about to add.
871 if (topWc && !topWc->IsDiscarded() &&
872 !topWc->GetSHEntryHasUserInteraction()) {
873 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", 873); AnnotateMozCrashReason
("MOZ_CRASH(" "NS_SUCCEEDED(topWc->SetSHEntryHasUserInteraction(true))"
")"); do { MOZ_CrashSequence(__null, 873); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
;
874 }
875 }
876
877 rv = InternalLoad(aLoadState);
878 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"
, 878); return rv; } } while (false)
;
879
880 if (aLoadState->GetOriginalURIString().isSome()) {
881 // Save URI string in case it's needed later when
882 // sending to search engine service in EndPageLoad()
883 mOriginalUriString = *aLoadState->GetOriginalURIString();
884 }
885
886 return NS_OK;
887}
888
889bool nsDocShell::IsLoadingFromSessionHistory() {
890 return mActiveEntryIsLoadingFromSessionHistory;
891}
892
893// StopDetector is modeled similarly to OnloadBlocker; it is a rather
894// dummy nsIRequest implementation which can be added to an nsILoadGroup to
895// detect Cancel calls.
896class StopDetector final : public nsIRequest {
897 public:
898 StopDetector() = default;
899
900 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:
901 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;
902
903 bool Canceled() { return mCanceled; }
904
905 private:
906 ~StopDetector() = default;
907
908 bool mCanceled = false;
909};
910
911NS_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"
, 911); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { MOZ_CrashSequence(__null, 911
); __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"
, 911); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"StopDetector\" != nullptr"
") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__null
, 911); __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"
, 911); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { MOZ_CrashSequence(__null, 911
); __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"
, 911); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"StopDetector\" != nullptr"
") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__null
, 911); __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", 911
); 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; }
912
913NS_IMETHODIMPnsresult
914StopDetector::GetName(nsACString& aResult) {
915 aResult.AssignLiteral("about:stop-detector");
916 return NS_OK;
917}
918
919NS_IMETHODIMPnsresult
920StopDetector::IsPending(bool* aRetVal) {
921 *aRetVal = true;
922 return NS_OK;
923}
924
925NS_IMETHODIMPnsresult
926StopDetector::GetStatus(nsresult* aStatus) {
927 *aStatus = NS_OK;
928 return NS_OK;
929}
930
931NS_IMETHODIMPnsresult StopDetector::SetCanceledReason(const nsACString& aReason) {
932 return SetCanceledReasonImpl(aReason);
933}
934
935NS_IMETHODIMPnsresult StopDetector::GetCanceledReason(nsACString& aReason) {
936 return GetCanceledReasonImpl(aReason);
937}
938
939NS_IMETHODIMPnsresult StopDetector::CancelWithReason(nsresult aStatus,
940 const nsACString& aReason) {
941 return CancelWithReasonImpl(aStatus, aReason);
942}
943
944NS_IMETHODIMPnsresult
945StopDetector::Cancel(nsresult aStatus) {
946 mCanceled = true;
947 return NS_OK;
948}
949
950NS_IMETHODIMPnsresult
951StopDetector::Suspend(void) { return NS_OK; }
952NS_IMETHODIMPnsresult
953StopDetector::Resume(void) { return NS_OK; }
954
955NS_IMETHODIMPnsresult
956StopDetector::GetLoadGroup(nsILoadGroup** aLoadGroup) {
957 *aLoadGroup = nullptr;
958 return NS_OK;
959}
960
961NS_IMETHODIMPnsresult
962StopDetector::SetLoadGroup(nsILoadGroup* aLoadGroup) { return NS_OK; }
963
964NS_IMETHODIMPnsresult
965StopDetector::GetLoadFlags(nsLoadFlags* aLoadFlags) {
966 *aLoadFlags = nsIRequest::LOAD_NORMAL;
967 return NS_OK;
968}
969
970NS_IMETHODIMPnsresult
971StopDetector::GetTRRMode(nsIRequest::TRRMode* aTRRMode) {
972 return GetTRRModeImpl(aTRRMode);
973}
974
975NS_IMETHODIMPnsresult
976StopDetector::SetTRRMode(nsIRequest::TRRMode aTRRMode) {
977 return SetTRRModeImpl(aTRRMode);
978}
979
980NS_IMETHODIMPnsresult
981StopDetector::SetLoadFlags(nsLoadFlags aLoadFlags) { return NS_OK; }
982
983bool nsDocShell::MaybeHandleSubframeHistory(
984 nsDocShellLoadState* aLoadState, bool aContinueHandlingSubframeHistory) {
985 // First, verify if this is a subframe.
986 // Note, it is ok to rely on docshell here and not browsing context since when
987 // an iframe is created, it has first in-process docshell.
988 nsCOMPtr<nsIDocShellTreeItem> parentAsItem;
989 GetInProcessSameTypeParent(getter_AddRefs(parentAsItem));
990 nsCOMPtr<nsIDocShell> parentDS(do_QueryInterface(parentAsItem));
991
992 if (!parentDS || parentDS == static_cast<nsIDocShell*>(this)) {
993 if (mBrowsingContext && mBrowsingContext->IsTop() &&
994 !aLoadState->HistoryBehavior()) {
995 // This is the root docshell. If we got here while
996 // executing an onLoad Handler,this load will not go
997 // into session history.
998 // XXX Why is this code in a method which deals with iframes!
999 if (aLoadState->IsFormSubmission()) {
1000#ifdef DEBUG1
1001 if (!mEODForCurrentDocument) {
1002 const MaybeDiscarded<BrowsingContext>& targetBC =
1003 aLoadState->TargetBrowsingContext();
1004 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"
, 1005); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->LoadType() == LOAD_NORMAL_REPLACE"
")"); do { MOZ_CrashSequence(__null, 1005); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
1005 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"
, 1005); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->LoadType() == LOAD_NORMAL_REPLACE"
")"); do { MOZ_CrashSequence(__null, 1005); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
1006 }
1007#endif
1008 } else {
1009 bool inOnLoadHandler = false;
1010 GetIsExecutingOnLoadHandler(&inOnLoadHandler);
1011 if (inOnLoadHandler) {
1012 aLoadState->SetLoadType(LOAD_NORMAL_REPLACE);
1013 }
1014 }
1015 }
1016 return false;
1017 }
1018
1019 /* OK. It is a subframe. Checkout the parent's loadtype. If the parent was
1020 * loaded through a history mechanism, then get the SH entry for the child
1021 * from the parent. This is done to restore frameset navigation while going
1022 * back/forward. If the parent was loaded through any other loadType, set the
1023 * child's loadType too accordingly, so that session history does not get
1024 * confused.
1025 */
1026
1027 // Get the parent's load type
1028 uint32_t parentLoadType;
1029 parentDS->GetLoadType(&parentLoadType);
1030
1031 // If parent is loading from history and we're loading the original src for a
1032 // parser-inserted iframe, instead restore it from SH.
1033 if (!aContinueHandlingSubframeHistory &&
1034 nsDocShell::Cast(parentDS.get())->IsLoadingFromSessionHistory() &&
1035 !GetCreatedDynamically() && aLoadState->OriginalFrameSrc()) {
1036 if (XRE_IsContentProcess()) {
1037 dom::ContentChild* contentChild = dom::ContentChild::GetSingleton();
1038 nsCOMPtr<nsILoadGroup> loadGroup;
1039 GetLoadGroup(getter_AddRefs(loadGroup));
1040 if (contentChild && loadGroup && !GetIsAttemptingToNavigate()) {
1041 RefPtr<Document> parentDoc = parentDS->GetDocument();
1042 parentDoc->BlockOnload();
1043 RefPtr<BrowsingContext> browsingContext = mBrowsingContext;
1044 Maybe<uint64_t> currentLoadIdentifier =
1045 mBrowsingContext->GetCurrentLoadIdentifier();
1046 RefPtr<nsDocShellLoadState> loadState = aLoadState;
1047 bool isNavigating = mIsNavigating;
1048 RefPtr stopDetector = MakeRefPtr<StopDetector>();
1049 loadGroup->AddRequest(stopDetector, nullptr);
1050 // Need to set mCheckingSessionHistory so that
1051 // GetIsAttemptingToNavigate() returns true.
1052 mCheckingSessionHistory = true;
1053
1054 auto resolve =
1055 [currentLoadIdentifier, browsingContext, parentDoc, loadState,
1056 isNavigating, loadGroup,
1057 stopDetector](mozilla::Maybe<LoadingSessionHistoryInfo>&& aResult)
1058 MOZ_CAN_RUN_SCRIPT {
1059 RefPtr<nsDocShell> docShell =
1060 static_cast<nsDocShell*>(browsingContext->GetDocShell());
1061 auto unblockParent = MakeScopeExit(
1062 [loadGroup, stopDetector, parentDoc, docShell]() {
1063 if (docShell) {
1064 docShell->mCheckingSessionHistory = false;
1065 }
1066 loadGroup->RemoveRequest(stopDetector, nullptr, NS_OK);
1067 parentDoc->UnblockOnload(false);
1068 });
1069
1070 if (!docShell || !docShell->mCheckingSessionHistory) {
1071 return;
1072 }
1073
1074 if (stopDetector->Canceled()) {
1075 return;
1076 }
1077 if (currentLoadIdentifier ==
1078 browsingContext->GetCurrentLoadIdentifier() &&
1079 aResult.isSome()) {
1080 loadState->SetLoadingSessionHistoryInfo(aResult.value());
1081 // This is an initial subframe load from the session
1082 // history, index doesn't need to be updated.
1083 loadState->SetLoadIsFromSessionHistory(0, false);
1084 }
1085
1086 // We got the results back from the parent process, call
1087 // LoadURI again with the possibly updated data.
1088 docShell->LoadURI(loadState, isNavigating, true);
1089 };
1090 auto reject = [loadGroup, stopDetector, browsingContext,
1091 parentDoc](mozilla::ipc::ResponseRejectReason) {
1092 RefPtr<nsDocShell> docShell =
1093 static_cast<nsDocShell*>(browsingContext->GetDocShell());
1094 if (docShell) {
1095 docShell->mCheckingSessionHistory = false;
1096 }
1097 // In practise reject shouldn't be called ever.
1098 loadGroup->RemoveRequest(stopDetector, nullptr, NS_OK);
1099 parentDoc->UnblockOnload(false);
1100 };
1101 contentChild->SendAdoptChildSHEntry(
1102 mBrowsingContext, std::move(resolve), std::move(reject));
1103 return true;
1104 }
1105 } else {
1106 Maybe<LoadingSessionHistoryInfo> info;
1107 mBrowsingContext->Canonical()->AdoptChildSHEntry(info);
1108 if (info.isSome()) {
1109 aLoadState->SetLoadingSessionHistoryInfo(info.value());
1110 // This is an initial subframe load from the session
1111 // history, index doesn't need to be updated.
1112 aLoadState->SetLoadIsFromSessionHistory(0, false);
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(nsACString& aCustomUserAgent) {
2300 mBrowsingContext->GetCustomUserAgent(aCustomUserAgent);
2301 return NS_OK;
2302}
2303
2304NS_IMETHODIMPnsresult
2305nsDocShell::SetCustomUserAgent(const nsACString& 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
3265// If aChannel failed while it was following a redirect, returns the URI of the
3266// redirect target when that target uses a different scheme, otherwise nullptr.
3267// The channel itself keeps reporting the URI it was redirected away from, which
3268// isn't the URI that we were unable to load.
3269static already_AddRefed<nsIURI> GetUnhandledRedirectURI(nsIChannel* aChannel) {
3270 nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(aChannel);
3271 if (!httpChannel) {
3272 return nullptr;
3273 }
3274
3275 nsAutoCString location;
3276 if (NS_FAILED(httpChannel->GetResponseHeader("Location"_ns, location))((bool)(__builtin_expect(!!(NS_FAILED_impl(httpChannel->GetResponseHeader
("Location"_ns, location))), 0)))
) {
3277 return nullptr;
3278 }
3279
3280 nsCOMPtr<nsIURI> channelURI;
3281 if (NS_FAILED(httpChannel->GetURI(getter_AddRefs(channelURI)))((bool)(__builtin_expect(!!(NS_FAILED_impl(httpChannel->GetURI
(getter_AddRefs(channelURI)))), 0)))
) {
3282 return nullptr;
3283 }
3284
3285 nsCOMPtr<nsIURI> redirectURI;
3286 if (NS_FAILED(NS_NewURI(getter_AddRefs(redirectURI), location, nullptr,((bool)(__builtin_expect(!!(NS_FAILED_impl(NS_NewURI(getter_AddRefs
(redirectURI), location, nullptr, channelURI))), 0)))
3287 channelURI))((bool)(__builtin_expect(!!(NS_FAILED_impl(NS_NewURI(getter_AddRefs
(redirectURI), location, nullptr, channelURI))), 0)))
) {
3288 return nullptr;
3289 }
3290
3291 nsAutoCString channelScheme;
3292 nsAutoCString redirectScheme;
3293 channelURI->GetScheme(channelScheme);
3294 redirectURI->GetScheme(redirectScheme);
3295 if (channelScheme.Equals(redirectScheme)) {
3296 return nullptr;
3297 }
3298
3299 return redirectURI.forget();
3300}
3301
3302NS_IMETHODIMPnsresult
3303nsDocShell::DisplayLoadError(nsresult aError, nsIURI* aURI,
3304 const char16_t* aURL, nsIChannel* aFailedChannel,
3305 bool* aDisplayedErrorPage) {
3306 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
)
3307 ("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
)
3308 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
)
;
3309
3310 *aDisplayedErrorPage = false;
3311 // Get prompt and string bundle services
3312 nsCOMPtr<nsIPrompt> prompter;
3313 nsCOMPtr<nsIStringBundle> stringBundle;
3314 GetPromptAndStringBundle(getter_AddRefs(prompter),
3315 getter_AddRefs(stringBundle));
3316
3317 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", 3317); return
NS_ERROR_FAILURE; } } while (false)
;
3318 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", 3318); return NS_ERROR_FAILURE
; } } while (false)
;
3319
3320 const char* error = nullptr;
3321 // The key used to select the appropriate error message from the properties
3322 // file.
3323 const char* errorDescriptionID = nullptr;
3324 AutoTArray<nsString, 3> formatStrs;
3325 bool addHostPort = false;
3326 bool isBadStsCertError = false;
3327 nsresult rv = NS_OK;
3328 nsAutoString messageStr;
3329 nsAutoCString cssClass;
3330 nsAutoCString errorPage;
3331
3332 errorPage.AssignLiteral("neterror");
3333
3334 // Turn the error code into a human readable error message.
3335 if (NS_ERROR_UNKNOWN_PROTOCOL == aError) {
3336 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", 3336); return NS_ERROR_INVALID_POINTER
; } } while (false)
;
3337
3338 // A load that failed while following a redirect reports the URI it was
3339 // redirected away from, so name the protocol we could not handle rather
3340 // than the one of the server which sent us there.
3341 nsCOMPtr<nsIURI> unknownProtocolURI =
3342 GetUnhandledRedirectURI(aFailedChannel);
3343 if (!unknownProtocolURI) {
3344 unknownProtocolURI = aURI;
3345 }
3346
3347 // Extract the schemes into a comma delimited list.
3348 nsAutoCString scheme;
3349 unknownProtocolURI->GetScheme(scheme);
3350 CopyASCIItoUTF16(scheme, *formatStrs.AppendElement());
3351 nsCOMPtr<nsINestedURI> nestedURI = do_QueryInterface(unknownProtocolURI);
3352 while (nestedURI) {
3353 nsCOMPtr<nsIURI> tempURI;
3354 nsresult rv2;
3355 rv2 = nestedURI->GetInnerURI(getter_AddRefs(tempURI));
3356 if (NS_SUCCEEDED(rv2)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv2)), 1))) && tempURI) {
3357 tempURI->GetScheme(scheme);
3358 formatStrs[0].AppendLiteral(", ");
3359 AppendASCIItoUTF16(scheme, formatStrs[0]);
3360 }
3361 nestedURI = do_QueryInterface(tempURI);
3362 }
3363 error = "unknownProtocolFound";
3364 } else if (NS_ERROR_NET_EMPTY_RESPONSE == aError) {
3365 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", 3365); return NS_ERROR_INVALID_POINTER
; } } while (false)
;
3366 error = "httpErrorPage";
3367 } else if (NS_ERROR_NET_ERROR_RESPONSE == aError) {
3368 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", 3368); return NS_ERROR_INVALID_POINTER
; } } while (false)
;
3369 error = "serverError";
3370 } else if (NS_ERROR_FILE_NOT_FOUND == aError) {
3371 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", 3371); return NS_ERROR_INVALID_POINTER
; } } while (false)
;
3372 error = "fileNotFound";
3373 } else if (NS_ERROR_FILE_ACCESS_DENIED == aError) {
3374 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", 3374); return NS_ERROR_INVALID_POINTER
; } } while (false)
;
3375 error = "fileAccessDenied";
3376 } else if (NS_ERROR_UNKNOWN_HOST == aError) {
3377 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", 3377); return NS_ERROR_INVALID_POINTER
; } } while (false)
;
3378 // Get the host
3379 nsAutoCString host;
3380 nsCOMPtr<nsIURI> innermostURI = NS_GetInnermostURI(aURI);
3381 innermostURI->GetHost(host);
3382 CopyUTF8toUTF16(host, *formatStrs.AppendElement());
3383 errorDescriptionID = "dnsNotFound2";
3384 error = "dnsNotFound";
3385 } else if (NS_ERROR_CONNECTION_REFUSED == aError ||
3386 NS_ERROR_PROXY_BAD_GATEWAY == aError) {
3387 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", 3387); return NS_ERROR_INVALID_POINTER
; } } while (false)
;
3388 addHostPort = true;
3389 error = "connectionFailure";
3390 } else if (NS_ERROR_NET_INTERRUPT == aError) {
3391 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", 3391); return NS_ERROR_INVALID_POINTER
; } } while (false)
;
3392 addHostPort = true;
3393 error = "netInterrupt";
3394 } else if (NS_ERROR_NET_TIMEOUT == aError ||
3395 NS_ERROR_PROXY_GATEWAY_TIMEOUT == aError ||
3396 NS_ERROR_NET_TIMEOUT_EXTERNAL == aError) {
3397 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", 3397); return NS_ERROR_INVALID_POINTER
; } } while (false)
;
3398 // Get the host
3399 nsAutoCString host;
3400 aURI->GetHost(host);
3401 CopyUTF8toUTF16(host, *formatStrs.AppendElement());
3402 error = "netTimeout";
3403 } else if (NS_ERROR_CSP_FRAME_ANCESTOR_VIOLATION == aError ||
3404 NS_ERROR_CSP_FORM_ACTION_VIOLATION == aError) {
3405 // CSP error
3406 cssClass.AssignLiteral("neterror");
3407 error = "cspBlocked";
3408 } else if (NS_ERROR_XFO_VIOLATION == aError) {
3409 // XFO error
3410 cssClass.AssignLiteral("neterror");
3411 error = "xfoBlocked";
3412 } else if (NS_ERROR_GET_MODULE(aError) == NS_ERROR_MODULE_SECURITY21) {
3413 nsCOMPtr<nsINSSErrorsService> nsserr =
3414 do_GetService(NS_NSS_ERRORS_SERVICE_CONTRACTID"@mozilla.org/nss_errors_service;1");
3415
3416 uint32_t errorClass;
3417 if (!nsserr || NS_FAILED(nsserr->GetErrorClass(aError, &errorClass))((bool)(__builtin_expect(!!(NS_FAILED_impl(nsserr->GetErrorClass
(aError, &errorClass))), 0)))
) {
3418 errorClass = nsINSSErrorsService::ERROR_CLASS_SSL_PROTOCOL;
3419 }
3420
3421 nsCOMPtr<nsITransportSecurityInfo> tsi;
3422 if (aFailedChannel) {
3423 aFailedChannel->GetSecurityInfo(getter_AddRefs(tsi));
3424 }
3425 if (tsi) {
3426 uint32_t securityState;
3427 tsi->GetSecurityState(&securityState);
3428 if (securityState & nsIWebProgressListener::STATE_USES_SSL_3) {
3429 error = "sslv3Used";
Value stored to 'error' is never read
3430 addHostPort = true;
3431 } else if (securityState &
3432 nsIWebProgressListener::STATE_USES_WEAK_CRYPTO) {
3433 error = "weakCryptoUsed";
3434 addHostPort = true;
3435 }
3436 } else {
3437 // No channel, let's obtain the generic error message
3438 if (nsserr) {
3439 nsserr->GetErrorMessage(aError, messageStr);
3440 }
3441 }
3442 // We don't have a message string here anymore but DisplayLoadError
3443 // requires a non-empty messageStr.
3444 messageStr.Truncate();
3445 messageStr.AssignLiteral(u" ");
3446 if (errorClass == nsINSSErrorsService::ERROR_CLASS_BAD_CERT) {
3447 error = "nssBadCert";
3448
3449 // If this is an HTTP Strict Transport Security host or a pinned host
3450 // and the certificate is bad, don't allow overrides (RFC 6797 section
3451 // 12.1).
3452 bool isStsHost = false;
3453 bool isPinnedHost = false;
3454 OriginAttributes attrsForHSTS;
3455 if (aFailedChannel) {
3456 StoragePrincipalHelper::GetOriginAttributesForHSTS(aFailedChannel,
3457 attrsForHSTS);
3458 } else {
3459 attrsForHSTS = GetOriginAttributes();
3460 }
3461
3462 if (XRE_IsParentProcess()) {
3463 nsCOMPtr<nsISiteSecurityService> sss =
3464 do_GetService(NS_SSSERVICE_CONTRACTID"@mozilla.org/ssservice;1", &rv);
3465 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"
, 3465); return rv; } } while (false)
;
3466 rv = sss->IsSecureURI(aURI, attrsForHSTS, &isStsHost);
3467 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"
, 3467); return rv; } } while (false)
;
3468 } else {
3469 mozilla::dom::ContentChild* cc =
3470 mozilla::dom::ContentChild::GetSingleton();
3471 cc->SendIsSecureURI(aURI, attrsForHSTS, &isStsHost);
3472 }
3473 nsCOMPtr<nsIPublicKeyPinningService> pkps =
3474 do_GetService(NS_PKPSERVICE_CONTRACTID"@mozilla.org/security/publickeypinningservice;1", &rv);
3475 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"
, 3475); return rv; } } while (false)
;
3476 rv = pkps->HostHasPins(aURI, &isPinnedHost);
3477
3478 if (Preferences::GetBool("browser.xul.error_pages.expert_bad_cert",
3479 false)) {
3480 cssClass.AssignLiteral("expertBadCert");
3481 }
3482
3483 // HSTS/pinning takes precedence over the expert bad cert pref. We
3484 // never want to show the "Add Exception" button for these sites.
3485 // In the future we should differentiate between an HSTS host and a
3486 // pinned host and display a more informative message to the user.
3487 if (isStsHost || isPinnedHost) {
3488 isBadStsCertError = true;
3489 cssClass.AssignLiteral("badStsCert");
3490 }
3491
3492 errorPage.Assign("certerror");
3493 } else {
3494 error = "nssFailure2";
3495 }
3496 } else if (NS_ERROR_PHISHING_URI == aError ||
3497 NS_ERROR_MALWARE_URI == aError ||
3498 NS_ERROR_UNWANTED_URI == aError ||
3499 NS_ERROR_HARMFULADDON_URI == aError ||
3500 NS_ERROR_HARMFUL_URI == aError) {
3501 nsAutoCString host;
3502 aURI->GetHost(host);
3503 CopyUTF8toUTF16(host, *formatStrs.AppendElement());
3504
3505 // Malware and phishing detectors may want to use an alternate error
3506 // page, but if the pref's not set, we'll fall back on the standard page
3507 nsAutoCString alternateErrorPage;
3508 nsresult rv = Preferences::GetCString("urlclassifier.alternate_error_page",
3509 alternateErrorPage);
3510 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
3511 errorPage.Assign(alternateErrorPage);
3512 }
3513
3514 if (NS_ERROR_PHISHING_URI == aError) {
3515 error = "deceptiveBlocked";
3516 } else if (NS_ERROR_MALWARE_URI == aError) {
3517 error = "malwareBlocked";
3518 } else if (NS_ERROR_UNWANTED_URI == aError) {
3519 error = "unwantedBlocked";
3520 } else if (NS_ERROR_HARMFUL_URI == aError) {
3521 error = "harmfulBlocked";
3522 } else if (NS_ERROR_HARMFULADDON_URI == aError) {
3523 error = "addonBlocked";
3524 }
3525
3526 cssClass.AssignLiteral("blacklist");
3527 } else if (NS_ERROR_CONTENT_CRASHED == aError) {
3528 errorPage.AssignLiteral("tabcrashed");
3529 error = "tabcrashed";
3530
3531 RefPtr<EventTarget> handler = mChromeEventHandler;
3532 if (handler) {
3533 nsCOMPtr<Element> element = do_QueryInterface(handler);
3534 element->GetAttribute(u"crashedPageTitle"_ns, messageStr);
3535 }
3536
3537 // DisplayLoadError requires a non-empty messageStr to proceed and call
3538 // LoadErrorPage. If the page doesn't have a title, we will use a blank
3539 // space which will be trimmed and thus treated as empty by the front-end.
3540 if (messageStr.IsEmpty()) {
3541 messageStr.AssignLiteral(u" ");
3542 }
3543 } else if (NS_ERROR_FRAME_CRASHED == aError) {
3544 errorPage.AssignLiteral("framecrashed");
3545 error = "framecrashed";
3546 messageStr.AssignLiteral(u" ");
3547 } else if (NS_ERROR_BUILDID_MISMATCH == aError) {
3548 errorPage.AssignLiteral("restartrequired");
3549 error = "restartrequired";
3550
3551 // DisplayLoadError requires a non-empty messageStr to proceed and call
3552 // LoadErrorPage. If the page doesn't have a title, we will use a blank
3553 // space which will be trimmed and thus treated as empty by the front-end.
3554 if (messageStr.IsEmpty()) {
3555 messageStr.AssignLiteral(u" ");
3556 }
3557 } else if (aError == NS_ERROR_RESTRICTED_CONTENT) {
3558 errorPage.AssignLiteral("restricted");
3559 error = "restrictedcontent";
3560 if (messageStr.IsEmpty()) {
3561 messageStr.AssignLiteral(u" ");
3562 }
3563 } else {
3564 // Errors requiring simple formatting
3565 switch (aError) {
3566 case NS_ERROR_MALFORMED_URI:
3567 // URI is malformed
3568 error = "malformedURI";
3569 errorDescriptionID = "malformedURI2";
3570 break;
3571 case NS_ERROR_REDIRECT_LOOP:
3572 // Doc failed to load because the server generated too many redirects
3573 error = "redirectLoop";
3574 break;
3575 case NS_ERROR_UNKNOWN_SOCKET_TYPE:
3576 // Doc failed to load because the client is misconfigured
3577 error = "clientSocketMisconfiguration";
3578 break;
3579 case NS_ERROR_NET_RESET:
3580 case NS_ERROR_OS_LOCAL_NETWORK_ACCESS_DENIED:
3581 // Doc failed to load because the server kept reseting the connection
3582 // before we could read any data from it
3583 // NS_ERROR_OS_LOCAL_NETWORK_ACCESS_DENIED is temporarily grouped
3584 // with netReset; it will get its own dedicated error page in
3585 // bug 2060188.
3586 error = "netReset";
3587 break;
3588 case NS_ERROR_DOCUMENT_NOT_CACHED:
3589 // Doc failed to load because the cache does not contain a copy of
3590 // the document.
3591 error = "notCached";
3592 break;
3593 case NS_ERROR_OFFLINE:
3594 // Doc failed to load because we are offline.
3595 error = "netOffline";
3596 break;
3597 case NS_ERROR_DOCUMENT_IS_PRINTMODE:
3598 // Doc navigation attempted while Printing or Print Preview
3599 error = "isprinting";
3600 break;
3601 case NS_ERROR_PORT_ACCESS_NOT_ALLOWED:
3602 // Port blocked for security reasons
3603 addHostPort = true;
3604 error = "deniedPortAccess";
3605 break;
3606 case NS_ERROR_UNKNOWN_PROXY_HOST:
3607 // Proxy hostname could not be resolved.
3608 error = "proxyResolveFailure";
3609 break;
3610 case NS_ERROR_PROXY_CONNECTION_REFUSED:
3611 case NS_ERROR_PROXY_FORBIDDEN:
3612 case NS_ERROR_PROXY_NOT_IMPLEMENTED:
3613 case NS_ERROR_PROXY_AUTHENTICATION_FAILED:
3614 case NS_ERROR_PROXY_TOO_MANY_REQUESTS:
3615 // Proxy connection was refused.
3616 error = "proxyConnectFailure";
3617 break;
3618 case NS_ERROR_INVALID_CONTENT_ENCODING:
3619 // Bad Content Encoding.
3620 error = "contentEncodingError";
3621 break;
3622 case NS_ERROR_UNSAFE_CONTENT_TYPE:
3623 // Channel refused to load from an unrecognized content type.
3624 error = "unsafeContentType";
3625 break;
3626 case NS_ERROR_CORRUPTED_CONTENT:
3627 // Broken Content Detected. e.g. Content-MD5 check failure.
3628 error = "corruptedContentErrorv2";
3629 break;
3630 case NS_ERROR_INTERCEPTION_FAILED:
3631 // ServiceWorker intercepted request, but something went wrong.
3632 error = "corruptedContentErrorv2";
3633 break;
3634 case NS_ERROR_NET_INADEQUATE_SECURITY:
3635 // Server negotiated bad TLS for HTTP/2.
3636 error = "inadequateSecurityError";
3637 addHostPort = true;
3638 break;
3639 case NS_ERROR_BLOCKED_BY_POLICY:
3640 // Page blocked by policy
3641 error = "blockedByPolicy";
3642 break;
3643 case NS_ERROR_DOM_COOP_FAILED:
3644 error = "blockedByCOOP";
3645 errorDescriptionID = "blockedByCORP";
3646 break;
3647 case NS_ERROR_DOM_COEP_FAILED:
3648 error = "blockedByCOEP";
3649 errorDescriptionID = "blockedByCORP";
3650 break;
3651 case NS_ERROR_DOM_INVALID_HEADER_VALUE:
3652 error = "invalidHeaderValue";
3653 break;
3654 case NS_ERROR_NET_HTTP2_SENT_GOAWAY:
3655 case NS_ERROR_NET_HTTP3_PROTOCOL_ERROR:
3656 // HTTP/2 or HTTP/3 stack detected a protocol error
3657 error = "networkProtocolError";
3658 break;
3659 case NS_ERROR_BASIC_HTTP_AUTH_DISABLED:
3660 error = "basicHttpAuthDisabled";
3661 break;
3662 default:
3663 break;
3664 }
3665 }
3666
3667 nsresult delegateErrorCode = aError;
3668 // If the HTTPS-Only Mode upgraded this request and the upgrade might have
3669 // caused this error, we replace the error-page with about:httpsonlyerror
3670 if (nsHTTPSOnlyUtils::CouldBeHttpsOnlyError(aFailedChannel, aError)) {
3671 errorPage.AssignLiteral("httpsonlyerror");
3672 delegateErrorCode = NS_ERROR_HTTPS_ONLY;
3673 } else if (isBadStsCertError) {
3674 delegateErrorCode = NS_ERROR_BAD_HSTS_CERT;
3675 }
3676
3677 if (nsCOMPtr<nsILoadURIDelegate> loadURIDelegate = GetLoadURIDelegate()) {
3678 nsCOMPtr<nsIURI> errorPageURI;
3679 rv = loadURIDelegate->HandleLoadError(
3680 aURI, delegateErrorCode, NS_ERROR_GET_MODULE(delegateErrorCode),
3681 getter_AddRefs(errorPageURI));
3682 // If the docshell is going away there's no point in showing an error page.
3683 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) || mIsBeingDestroyed) {
3684 *aDisplayedErrorPage = false;
3685 return NS_OK;
3686 }
3687
3688 if (errorPageURI) {
3689 *aDisplayedErrorPage =
3690 NS_SUCCEEDED(LoadErrorPage(errorPageURI, aURI, aFailedChannel))((bool)(__builtin_expect(!!(!NS_FAILED_impl(LoadErrorPage(errorPageURI
, aURI, aFailedChannel))), 1)))
;
3691 return NS_OK;
3692 }
3693 }
3694
3695 // Test if the error should be displayed
3696 if (!error) {
3697 return NS_OK;
3698 }
3699
3700 if (!errorDescriptionID) {
3701 errorDescriptionID = error;
3702 }
3703
3704 glean::page::load_error
3705 .Get(IsSubframe() ? "frame"_ns : "top"_ns,
3706 mozilla::dom::LoadErrorToTelemetryLabel(aError))
3707 .Add();
3708
3709 // Test if the error needs to be formatted
3710 if (!messageStr.IsEmpty()) {
3711 // already obtained message
3712 } else {
3713 if (addHostPort) {
3714 // Build up the host:port string.
3715 nsAutoCString hostport;
3716 if (aURI) {
3717 aURI->GetHostPort(hostport);
3718 } else {
3719 hostport.Assign('?');
3720 }
3721 CopyUTF8toUTF16(hostport, *formatStrs.AppendElement());
3722 }
3723
3724 nsAutoCString spec;
3725 rv = NS_ERROR_NOT_AVAILABLE;
3726 auto& nextFormatStr = *formatStrs.AppendElement();
3727 if (aURI) {
3728 // displaying "file://" is aesthetically unpleasing and could even be
3729 // confusing to the user
3730 if (aURI->SchemeIs("file")) {
3731 aURI->GetPathQueryRef(spec);
3732 } else {
3733 aURI->GetSpec(spec);
3734 }
3735
3736 nsCOMPtr<nsITextToSubURI> textToSubURI(
3737 do_GetService(NS_ITEXTTOSUBURI_CONTRACTID"@mozilla.org/intl/texttosuburi;1", &rv));
3738 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
3739 rv = textToSubURI->UnEscapeURIForUI(spec, nextFormatStr);
3740 }
3741 } else {
3742 spec.Assign('?');
3743 }
3744 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3745 CopyUTF8toUTF16(spec, nextFormatStr);
3746 }
3747 rv = NS_OK;
3748
3749 nsAutoString str;
3750 rv =
3751 stringBundle->FormatStringFromName(errorDescriptionID, formatStrs, str);
3752 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"
, 3752); return rv; } } while (false)
;
3753 messageStr.Assign(str);
3754 }
3755
3756 // Display the error as a page or an alert prompt
3757 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"
, 3757); return NS_ERROR_FAILURE; } } while (false)
;
3758
3759 if (mBrowsingContext->GetUseErrorPages()) {
3760 // Display an error page
3761 nsresult loadedPage =
3762 LoadErrorPage(aURI, aURL, errorPage.get(), error, messageStr.get(),
3763 cssClass.get(), aFailedChannel);
3764 *aDisplayedErrorPage = NS_SUCCEEDED(loadedPage)((bool)(__builtin_expect(!!(!NS_FAILED_impl(loadedPage)), 1))
)
;
3765 } else {
3766 // The prompter reqires that our private window has a document (or it
3767 // asserts). Satisfy that assertion now since GetDoc will force
3768 // creation of one if it hasn't already been created.
3769 if (mScriptGlobal) {
3770 (void)mScriptGlobal->GetDoc();
3771 }
3772
3773 // Display a message box
3774 prompter->Alert(nullptr, messageStr.get());
3775 }
3776
3777 return NS_OK;
3778}
3779
3780#define PREF_SAFEBROWSING_ALLOWOVERRIDE"browser.safebrowsing.allowOverride" "browser.safebrowsing.allowOverride"
3781
3782nsresult nsDocShell::LoadErrorPage(nsIURI* aURI, const char16_t* aURL,
3783 const char* aErrorPage,
3784 const char* aErrorType,
3785 const char16_t* aDescription,
3786 const char* aCSSClass,
3787 nsIChannel* aFailedChannel) {
3788 if (mIsBeingDestroyed) {
3789 return NS_ERROR_NOT_AVAILABLE;
3790 }
3791
3792#if defined(DEBUG1)
3793 if (MOZ_LOG_TEST(gDocShellLog, LogLevel::Debug)(__builtin_expect(!!(mozilla::detail::log_test(gDocShellLog, LogLevel
::Debug)), 0))
) {
3794 nsAutoCString chanName;
3795 if (aFailedChannel) {
3796 aFailedChannel->GetName(chanName);
3797 } else {
3798 chanName.AssignLiteral("<no channel>");
3799 }
3800
3801 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)
3802 ("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)
3803 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)
3804 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)
;
3805 }
3806#endif
3807
3808 nsAutoCString url;
3809 if (aURI) {
3810 nsresult rv = aURI->GetSpec(url);
3811 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"
, 3811); return rv; } } while (false)
;
3812 } else if (aURL) {
3813 CopyUTF16toUTF8(MakeStringSpan(aURL), url);
3814 } else {
3815 return NS_ERROR_INVALID_POINTER;
3816 }
3817
3818 // Create a URL to pass all the error information through to the page.
3819
3820#undef SAFE_ESCAPE
3821#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", 3821)) { return NS_ERROR_OUT_OF_MEMORY
; }
\
3822 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", 3822)
) { \
3823 return NS_ERROR_OUT_OF_MEMORY; \
3824 }
3825
3826 nsCString escapedUrl, escapedError, escapedDescription, escapedCSSClass;
3827 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", 3827)) { return NS_ERROR_OUT_OF_MEMORY
; }
;
3828 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", 3828)) { return NS_ERROR_OUT_OF_MEMORY
; }
;
3829 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", 3830)) { return NS_ERROR_OUT_OF_MEMORY
; }
3830 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", 3830)) { return NS_ERROR_OUT_OF_MEMORY
; }
;
3831 if (aCSSClass) {
3832 nsCString cssClass(aCSSClass);
3833 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"
, 3833)) { return NS_ERROR_OUT_OF_MEMORY; }
;
3834 }
3835 nsCString errorPageUrl("about:");
3836 errorPageUrl.AppendASCII(aErrorPage);
3837 errorPageUrl.AppendLiteral("?e=");
3838
3839 errorPageUrl.AppendASCII(escapedError.get());
3840 errorPageUrl.AppendLiteral("&u=");
3841 errorPageUrl.AppendASCII(escapedUrl.get());
3842 if ((strcmp(aErrorPage, "blocked") == 0) &&
3843 Preferences::GetBool(PREF_SAFEBROWSING_ALLOWOVERRIDE"browser.safebrowsing.allowOverride", true)) {
3844 errorPageUrl.AppendLiteral("&o=1");
3845 }
3846 if (!escapedCSSClass.IsEmpty()) {
3847 errorPageUrl.AppendLiteral("&s=");
3848 errorPageUrl.AppendASCII(escapedCSSClass.get());
3849 }
3850 errorPageUrl.AppendLiteral("&c=UTF-8");
3851
3852 nsCOMPtr<nsICaptivePortalService> cps = do_GetService(NS_CAPTIVEPORTAL_CID{ 0xbdbe0555, 0xfc3d, 0x4f7b, {0x92, 0x05, 0xc3, 0x09, 0xce, 0xb2
, 0xd6, 0x41}}
);
3853 int32_t cpsState;
3854 if (cps && NS_SUCCEEDED(cps->GetState(&cpsState))((bool)(__builtin_expect(!!(!NS_FAILED_impl(cps->GetState(
&cpsState))), 1)))
) {
3855 if (cpsState == nsICaptivePortalService::LOCKED_PORTAL) {
3856 errorPageUrl.AppendLiteral("&captive=true");
3857 }
3858 if (strcmp(aErrorPage, "neterror") == 0) {
3859 static const char* const kCaptivePortalStateNames[] = {
3860 "unknown", "not_captive", "unlocked_portal", "locked_portal"};
3861 if (cpsState >= 0 &&
3862 size_t(cpsState) < std::size(kCaptivePortalStateNames)) {
3863 errorPageUrl.AppendLiteral("&captivePortalState=");
3864 errorPageUrl.AppendASCII(kCaptivePortalStateNames[cpsState]);
3865 }
3866 }
3867 }
3868
3869 errorPageUrl.AppendLiteral("&d=");
3870 errorPageUrl.AppendASCII(escapedDescription.get());
3871
3872 nsCOMPtr<nsIWritablePropertyBag2> props(do_QueryInterface(aFailedChannel));
3873 if (props) {
3874 nsAutoCString addonName;
3875 props->GetPropertyAsACString(u"blockedExtension"_ns, addonName);
3876
3877 nsCString escapedAddonName;
3878 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"
, 3878)) { return NS_ERROR_OUT_OF_MEMORY; }
;
3879
3880 errorPageUrl.AppendLiteral("&a=");
3881 errorPageUrl.AppendASCII(escapedAddonName.get());
3882 }
3883
3884 nsCOMPtr<nsIURI> errorPageURI;
3885 nsresult rv = NS_NewURI(getter_AddRefs(errorPageURI), errorPageUrl);
3886 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"
, 3886); return rv; } } while (false)
;
3887
3888 return LoadErrorPage(errorPageURI, aURI, aFailedChannel);
3889}
3890
3891nsresult nsDocShell::LoadErrorPage(nsIURI* aErrorURI, nsIURI* aFailedURI,
3892 nsIChannel* aFailedChannel) {
3893 mFailedChannel = aFailedChannel;
3894 mFailedURI = aFailedURI;
3895 mFailedLoadType = mLoadType;
3896
3897 RefPtr loadState = MakeRefPtr<nsDocShellLoadState>(aErrorURI);
3898 loadState->SetTriggeringPrincipal(nsContentUtils::GetSystemPrincipal());
3899 if (mBrowsingContext) {
3900 loadState->SetTriggeringSandboxFlags(mBrowsingContext->GetSandboxFlags());
3901 loadState->SetTriggeringWindowId(
3902 mBrowsingContext->GetCurrentInnerWindowId());
3903 }
3904 loadState->SetLoadType(LOAD_ERROR_PAGE);
3905 loadState->SetFirstParty(true);
3906 loadState->SetSourceBrowsingContext(mBrowsingContext);
3907 if (mLoadingEntry) {
3908 // We keep the loading entry for the load that failed here. If the user
3909 // reloads we want to try to reload the original load, not the error page.
3910 loadState->SetLoadingSessionHistoryInfo(
3911 MakeUnique<LoadingSessionHistoryInfo>(*mLoadingEntry));
3912 }
3913
3914 // Prevent initial about:blank handling, as it's likely irrelevant and
3915 // keeps us from needing to change GeckoView / NavigationDelegateTest.
3916 // It also makes the load more consistent with non-about-blank cases.
3917 loadState->ProhibitInitialAboutBlankHandling();
3918
3919 return InternalLoad(loadState);
3920}
3921
3922MOZ_CAN_RUN_SCRIPT_BOUNDARY NS_IMETHODIMPnsresult
3923nsDocShell::Reload(uint32_t aReloadFlags) {
3924 return ReloadNavigable(Nothing(), aReloadFlags, nullptr,
3925 UserNavigationInvolvement::BrowserUI);
3926}
3927
3928// https://html.spec.whatwg.org/#reload
3929// To reload a navigable navigable given an optional serialized state-or-null
3930// navigationAPIState (default null) and an optional user navigation
3931// involvement userInvolvement (default "none"):
3932nsresult nsDocShell::ReloadNavigable(
3933 mozilla::Maybe<NotNull<JSContext*>> aCx, uint32_t aReloadFlags,
3934 nsIStructuredCloneContainer* aNavigationAPIState,
3935 UserNavigationInvolvement aUserInvolvement,
3936 NavigationAPIMethodTracker* aNavigationAPIMethodTracker) {
3937 AUTO_PROFILER_MARKER_UNTYPED(AutoProfilerUntypedMarker raiiObject3940( "nsDocShell:ReloadNavigable"
, ::mozilla::baseprofiler::category::DOM, MarkerOptions(MarkerStack
::Capture(), MarkerInnerWindowIdFromDocShell(this)))
3938 "nsDocShell:ReloadNavigable", DOM,AutoProfilerUntypedMarker raiiObject3940( "nsDocShell:ReloadNavigable"
, ::mozilla::baseprofiler::category::DOM, MarkerOptions(MarkerStack
::Capture(), MarkerInnerWindowIdFromDocShell(this)))
3939 MarkerOptions(MarkerStack::Capture(),AutoProfilerUntypedMarker raiiObject3940( "nsDocShell:ReloadNavigable"
, ::mozilla::baseprofiler::category::DOM, MarkerOptions(MarkerStack
::Capture(), MarkerInnerWindowIdFromDocShell(this)))
3940 MarkerInnerWindowIdFromDocShell(this)))AutoProfilerUntypedMarker raiiObject3940( "nsDocShell:ReloadNavigable"
, ::mozilla::baseprofiler::category::DOM, MarkerOptions(MarkerStack
::Capture(), MarkerInnerWindowIdFromDocShell(this)))
;
3941
3942 if (!IsNavigationAllowed()) {
3943 return NS_OK; // JS may not handle returning of an error code
3944 }
3945
3946 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", 3947); MOZ_PretendNoReturn
(); } } while (0)
3947 "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", 3947); MOZ_PretendNoReturn
(); } } while (0)
;
3948 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", 3949); MOZ_PretendNoReturn
(); } } while (0)
3949 "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", 3949); MOZ_PretendNoReturn
(); } } while (0)
;
3950
3951 uint32_t loadType = MAKE_LOAD_TYPE(LOAD_RELOAD_NORMAL, aReloadFlags)((LOAD_RELOAD_NORMAL) | ((aReloadFlags) << 16));
3952 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"
, 3952); return NS_ERROR_INVALID_ARG; } } while (false)
;
3953 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"
, 3955); return NS_ERROR_INVALID_ARG; } } while (false)
3954 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"
, 3955); return NS_ERROR_INVALID_ARG; } } while (false)
3955 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"
, 3955); return NS_ERROR_INVALID_ARG; } } while (false)
;
3956
3957 RefPtr<nsDocShell> docShell(this);
3958
3959 // 1. If userInvolvement is not "browser UI", then:
3960 if (aUserInvolvement != UserNavigationInvolvement::BrowserUI) {
3961 // 1.1 Let navigation be navigable's active window's navigation API.
3962 nsPIDOMWindowOuter* windowOuter = GetWindow();
3963 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"
, 3963); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "windowOuter"
")"); do { MOZ_CrashSequence(__null, 3963); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3964 nsPIDOMWindowInner* windowInner = windowOuter->GetCurrentInnerWindow();
3965 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"
, 3965); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "windowInner"
")"); do { MOZ_CrashSequence(__null, 3965); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3966 RefPtr navigation = windowInner->Navigation();
3967
3968 // 1.2 Let destinationNavigationAPIState be navigable's active session
3969 // history entry's navigation API state.
3970 // 1.3 If navigationAPIState is not null, then set
3971 // destinationNavigationAPIState to navigationAPIState.
3972 RefPtr<nsIStructuredCloneContainer> destinationNavigationAPIState =
3973 aNavigationAPIState;
3974 if (!destinationNavigationAPIState) {
3975 destinationNavigationAPIState =
3976 mActiveEntry ? mActiveEntry->GetNavigationAPIState() : nullptr;
3977 }
3978
3979 // 1.4 Let continue be the result of firing a push/replace/reload navigate
3980 // event at navigation with navigationType set to "reload",
3981 // isSameDocument set to false, userInvolvement set to userInvolvement,
3982 // destinationURL set to navigable's active session history entry's URL,
3983 // and navigationAPIState set to destinationNavigationAPIState.
3984 // 1.5 If continue is false, then return.
3985 RefPtr destinationURL = mActiveEntry ? mActiveEntry->GetURI() : nullptr;
3986 if (navigation &&
3987 !navigation->FirePushReplaceReloadNavigateEvent(
3988 *aCx, NavigationType::Reload, destinationURL,
3989 /* aIsSameDocument */ false, Some(aUserInvolvement),
3990 /* aSourceElement*/ nullptr, /* aFormDataEntryList */ nullptr,
3991 destinationNavigationAPIState,
3992 /* aClassiCHistoryAPIState */ nullptr,
3993 aNavigationAPIMethodTracker)) {
3994 return NS_OK;
3995 }
3996 }
3997
3998 // The following steps are implemented by the remainder of ReloadNavigable.
3999
4000 // Send notifications to the HistoryListener if any, about the impending
4001 // reload
4002 RefPtr<ChildSHistory> rootSH = GetRootSessionHistory();
4003 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)
;
4004 if (!XRE_IsParentProcess()) {
4005 ++mPendingReloadCount;
4006 nsCOMPtr<nsIDocumentViewer> viewer(mDocumentViewer);
4007 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", 4007); return NS_ERROR_UNEXPECTED
; } } while (false)
;
4008
4009 bool okToUnload = true;
4010 MOZ_TRY(viewer->PermitUnload(&okToUnload))__extension__({ auto mozTryVarTempResult = ::mozilla::ToResult
(viewer->PermitUnload(&okToUnload)); if ((__builtin_expect
(!!(mozTryVarTempResult.isErr()), 0))) { return mozTryVarTempResult
.propagateErr(); } mozTryVarTempResult.unwrap(); })
;
4011 if (mIsBeingDestroyed) {
4012 // unload handler destroyed this docshell.
4013 return NS_ERROR_NOT_AVAILABLE;
4014 }
4015 if (!okToUnload) {
4016 return NS_OK;
4017 }
4018
4019 RefPtr<Document> doc(GetDocument());
4020 RefPtr<BrowsingContext> browsingContext(mBrowsingContext);
4021 nsCOMPtr<nsIURI> currentURI(mCurrentURI);
4022 nsCOMPtr<nsIReferrerInfo> referrerInfo(mReferrerInfo);
4023 RefPtr stopDetector = MakeRefPtr<StopDetector>();
4024 nsCOMPtr<nsILoadGroup> loadGroup;
4025 GetLoadGroup(getter_AddRefs(loadGroup));
4026 if (loadGroup) {
4027 // loadGroup may be null in theory. In that case stopDetector just
4028 // doesn't do anything.
4029 loadGroup->AddRequest(stopDetector, nullptr);
4030 }
4031
4032 ContentChild::GetSingleton()->SendNotifyOnHistoryReload(
4033 mBrowsingContext, aReloadFlags,
4034 [docShell, doc, loadType, browsingContext, currentURI, referrerInfo,
4035 loadGroup, stopDetector](
4036 std::tuple<bool, Maybe<NotNull<RefPtr<nsDocShellLoadState>>>,
4037 Maybe<bool>>&& aResult) MOZ_CAN_RUN_SCRIPT {
4038 auto scopeExit = MakeScopeExit([loadGroup, stopDetector]() {
4039 if (loadGroup) {
4040 loadGroup->RemoveRequest(stopDetector, nullptr, NS_OK);
4041 }
4042 });
4043
4044 // Decrease mPendingReloadCount before any other early returns!
4045 if (--(docShell->mPendingReloadCount) > 0) {
4046 return;
4047 }
4048
4049 if (stopDetector->Canceled()) {
4050 return;
4051 }
4052 bool canReload;
4053 Maybe<NotNull<RefPtr<nsDocShellLoadState>>> loadState;
4054 Maybe<bool> reloadingActiveEntry;
4055
4056 std::tie(canReload, loadState, reloadingActiveEntry) = aResult;
4057
4058 if (!canReload) {
4059 return;
4060 }
4061
4062 if (loadState.isSome()) {
4063 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)
4064 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)
4065 ("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)
;
4066 loadState.ref()->SetNotifiedBeforeUnloadListeners(true);
4067 docShell->LoadHistoryEntry(MOZ_KnownLive(loadState.ref().get())(loadState.ref().get()),
4068 loadType, reloadingActiveEntry.ref());
4069 } else {
4070 MOZ_LOG(gSHLog, LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = gSHLog; if
((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "nsDocShell %p ReloadDocument", docShell.get
()); } } while (0)
4071 ("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)
;
4072 ReloadDocument(docShell, doc, loadType, browsingContext, currentURI,
4073 referrerInfo,
4074 /* aNotifiedBeforeUnloadListeners */ true);
4075 }
4076 },
4077 [](mozilla::ipc::ResponseRejectReason) {});
4078 } else {
4079 // Parent process
4080 bool canReload = false;
4081 Maybe<NotNull<RefPtr<nsDocShellLoadState>>> loadState;
4082 Maybe<bool> reloadingActiveEntry;
4083 if (!mBrowsingContext->IsDiscarded()) {
4084 mBrowsingContext->Canonical()->NotifyOnHistoryReload(
4085 aReloadFlags, canReload, loadState, reloadingActiveEntry);
4086 }
4087 if (canReload) {
4088 if (loadState.isSome()) {
4089 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)
4090 ("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)
;
4091 LoadHistoryEntry(MOZ_KnownLive(loadState.ref().get())(loadState.ref().get()), loadType,
4092 reloadingActiveEntry.ref());
4093 } else {
4094 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)
4095 ("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)
;
4096 RefPtr<Document> doc = GetDocument();
4097 RefPtr<BrowsingContext> bc = mBrowsingContext;
4098 nsCOMPtr<nsIURI> currentURI = mCurrentURI;
4099 nsCOMPtr<nsIReferrerInfo> referrerInfo = mReferrerInfo;
4100 ReloadDocument(this, doc, loadType, bc, currentURI, referrerInfo);
4101 }
4102 }
4103 }
4104 return NS_OK;
4105}
4106
4107void nsDocShell::DisplayRestrictedContentError() {
4108 bool didDisplayLoadError = false;
4109 RefPtr<mozilla::dom::Document> doc = GetDocument();
4110 if (!doc) {
4111 return;
4112 }
4113 doc->TerminateParserAndDisableScripts();
4114 DisplayLoadError(NS_ERROR_RESTRICTED_CONTENT, doc->GetDocumentURI(), nullptr,
4115 nullptr, &didDisplayLoadError);
4116}
4117
4118/* static */
4119nsresult nsDocShell::ReloadDocument(nsDocShell* aDocShell, Document* aDocument,
4120 uint32_t aLoadType,
4121 BrowsingContext* aBrowsingContext,
4122 nsIURI* aCurrentURI,
4123 nsIReferrerInfo* aReferrerInfo,
4124 bool aNotifiedBeforeUnloadListeners) {
4125 if (!aDocument) {
4126 return NS_OK;
4127 }
4128
4129 // Do not inherit owner from document
4130 uint32_t flags = INTERNAL_LOAD_FLAGS_NONE;
4131 nsAutoString srcdoc;
4132 nsIURI* baseURI = nullptr;
4133 nsCOMPtr<nsIURI> originalURI;
4134 nsCOMPtr<nsIURI> resultPrincipalURI;
4135 bool loadReplace = false;
4136
4137 nsIPrincipal* triggeringPrincipal = aDocument->NodePrincipal();
4138 nsCOMPtr<nsIPolicyContainer> policyContainer =
4139 aDocument->GetPolicyContainer();
4140 uint32_t triggeringSandboxFlags = aDocument->GetSandboxFlags();
4141 uint64_t triggeringWindowId = aDocument->InnerWindowID();
4142 net::ClassificationFlags triggeringClassificationFlags =
4143 aDocument->GetScriptTrackingFlags();
4144
4145 nsAutoString contentTypeHint;
4146 aDocument->GetContentType(contentTypeHint);
4147
4148 if (aDocument->IsSrcdocDocument()) {
4149 aDocument->GetSrcdocData(srcdoc);
4150 flags |= INTERNAL_LOAD_FLAGS_IS_SRCDOC;
4151 baseURI = aDocument->GetBaseURI();
4152 } else {
4153 srcdoc = VoidString();
4154 }
4155 nsCOMPtr<nsIChannel> chan = aDocument->GetChannel();
4156 if (chan) {
4157 uint32_t loadFlags;
4158 chan->GetLoadFlags(&loadFlags);
4159 loadReplace = loadFlags & nsIChannel::LOAD_REPLACE;
4160 nsCOMPtr<nsIHttpChannel> httpChan(do_QueryInterface(chan));
4161 if (httpChan) {
4162 httpChan->GetOriginalURI(getter_AddRefs(originalURI));
4163 }
4164
4165 nsCOMPtr<nsILoadInfo> loadInfo = chan->LoadInfo();
4166 loadInfo->GetResultPrincipalURI(getter_AddRefs(resultPrincipalURI));
4167 }
4168
4169 if (!triggeringPrincipal) {
4170 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", 4170); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "false" ") (" "Reload needs a valid triggeringPrincipal"
")"); do { MOZ_CrashSequence(__null, 4170); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4171 return NS_ERROR_FAILURE;
4172 }
4173
4174 // Stack variables to ensure changes to the member variables don't affect to
4175 // the call.
4176 nsCOMPtr<nsIURI> currentURI = aCurrentURI;
4177
4178 // Reload always rewrites result principal URI.
4179 Maybe<nsCOMPtr<nsIURI>> emplacedResultPrincipalURI;
4180 emplacedResultPrincipalURI.emplace(std::move(resultPrincipalURI));
4181
4182 RefPtr<WindowContext> context = aBrowsingContext->GetCurrentWindowContext();
4183 RefPtr loadState = MakeRefPtr<nsDocShellLoadState>(currentURI);
4184 loadState->SetReferrerInfo(aReferrerInfo);
4185 loadState->SetOriginalURI(originalURI);
4186 loadState->SetMaybeResultPrincipalURI(emplacedResultPrincipalURI);
4187 loadState->SetLoadReplace(loadReplace);
4188 loadState->SetTriggeringPrincipal(triggeringPrincipal);
4189 loadState->SetTriggeringSandboxFlags(triggeringSandboxFlags);
4190 loadState->SetTriggeringWindowId(triggeringWindowId);
4191 loadState->SetTriggeringClassificationFlags(triggeringClassificationFlags);
4192 loadState->SetPrincipalToInherit(triggeringPrincipal);
4193 loadState->SetPolicyContainer(policyContainer);
4194 loadState->SetInternalLoadFlags(flags);
4195 loadState->SetTypeHint(NS_ConvertUTF16toUTF8(contentTypeHint));
4196 loadState->SetLoadType(aLoadType);
4197 loadState->SetFirstParty(true);
4198 loadState->SetSrcdocData(srcdoc);
4199 loadState->SetSourceBrowsingContext(aBrowsingContext);
4200 loadState->SetBaseURI(baseURI);
4201 loadState->SetHasValidUserGestureActivation(
4202 context && context->HasValidTransientUserGestureActivation());
4203
4204 loadState->SetTextDirectiveUserActivation(
4205 aDocument->ConsumeTextDirectiveUserActivation() ||
4206 loadState->HasValidUserGestureActivation());
4207
4208 loadState->SetNotifiedBeforeUnloadListeners(aNotifiedBeforeUnloadListeners);
4209 return aDocShell->InternalLoad(loadState);
4210}
4211
4212// TODO: Convert this to MOZ_CAN_RUN_SCRIPT (bug 1415230)
4213MOZ_CAN_RUN_SCRIPT_BOUNDARY NS_IMETHODIMPnsresult
4214nsDocShell::Stop(uint32_t aStopFlags) {
4215 return StopInternal(aStopFlags, UnsetOngoingNavigation::Yes);
4216}
4217
4218nsresult nsDocShell::StopInternal(
4219 uint32_t aStopFlags, UnsetOngoingNavigation aUnsetOngoingNavigation) {
4220 RefPtr kungFuDeathGrip = this;
4221 if (RefPtr<Document> doc = GetExtantDocument();
4222 aUnsetOngoingNavigation == UnsetOngoingNavigation::Yes && doc &&
4223 !doc->ShouldIgnoreOpens() &&
4224 mOngoingNavigation == Some(OngoingNavigation::NavigationID)) {
4225 SetOngoingNavigation(Nothing());
4226 }
4227
4228 if (mLoadType == LOAD_ERROR_PAGE) {
4229 mActiveEntryIsLoadingFromSessionHistory = false;
4230
4231 mFailedChannel = nullptr;
4232 mFailedURI = nullptr;
4233 }
4234
4235 if (nsIWebNavigation::STOP_CONTENT & aStopFlags) {
4236 // Stop the document loading and animations
4237 if (mDocumentViewer) {
4238 nsCOMPtr<nsIDocumentViewer> viewer = mDocumentViewer;
4239 viewer->Stop();
4240 }
4241 } else if (nsIWebNavigation::STOP_NETWORK & aStopFlags) {
4242 // Stop the document loading only
4243 if (mDocumentViewer) {
4244 RefPtr<Document> doc = mDocumentViewer->GetDocument();
4245 if (doc) {
4246 doc->StopDocumentLoad();
4247 }
4248 }
4249 }
4250
4251 if (nsIWebNavigation::STOP_NETWORK & aStopFlags) {
4252 // Suspend any timers that were set for this loader. We'll clear
4253 // them out for good in CreateDocumentViewer.
4254 if (mRefreshURIList) {
4255 SuspendRefreshURIs();
4256 mSavedRefreshURIList.swap(mRefreshURIList);
4257 mRefreshURIList = nullptr;
4258 }
4259
4260 // XXXbz We could also pass |this| to nsIURILoader::Stop. That will
4261 // just call Stop() on us as an nsIDocumentLoader... We need fewer
4262 // redundant apis!
4263 if (aUnsetOngoingNavigation == UnsetOngoingNavigation::No && mLoadGroup) {
4264 // Tag load group cancellation as navigation-caused so that XHR can
4265 // suppress abort events (bug 1505389). SetCanceledReason is
4266 // first-write-wins, so nsDocLoader::Stop's reason won't overwrite.
4267
4268 // XXX Consider using a flag on LoadGroup instead of CanceledReason
4269 mLoadGroup->SetCanceledReason("navigation"_ns);
4270 }
4271 // Cancel <form> planned navigations.
4272 // Not currently in the spec, but it follows other browsers' behaviour:
4273 // https://github.com/whatwg/html/issues/12609
4274 CancelPlannedFormNavigation();
4275 Stop();
4276
4277 // Clear out mChannelToDisconnectOnPageHide. This page won't go in the
4278 // BFCache now, and the Stop above will have removed the DocumentChannel
4279 // from the loadgroup.
4280 mChannelToDisconnectOnPageHide = 0;
4281 }
4282
4283 for (auto* child : mChildList.ForwardRange()) {
4284 nsCOMPtr<nsIWebNavigation> shellAsNav(do_QueryObject(child));
4285 if (shellAsNav) {
4286 shellAsNav->Stop(aStopFlags);
4287 }
4288 }
4289
4290 return NS_OK;
4291}
4292
4293NS_IMETHODIMPnsresult
4294nsDocShell::GetDocument(Document** aDocument) {
4295 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", 4295); return NS_ERROR_INVALID_POINTER
; } } while (false)
;
4296 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"
, 4296); return NS_ERROR_FAILURE; } } while (false)
;
4297
4298 RefPtr<Document> doc = mDocumentViewer->GetDocument();
4299 if (!doc) {
4300 return NS_ERROR_NOT_AVAILABLE;
4301 }
4302
4303 doc.forget(aDocument);
4304 return NS_OK;
4305}
4306
4307NS_IMETHODIMPnsresult
4308nsDocShell::GetCurrentURI(nsIURI** aURI) {
4309 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", 4309); return NS_ERROR_INVALID_POINTER
; } } while (false)
;
4310
4311 nsCOMPtr<nsIURI> uri = mCurrentURI;
4312 uri.forget(aURI);
4313 return NS_OK;
4314}
4315
4316NS_IMETHODIMPnsresult
4317nsDocShell::GetSessionHistoryXPCOM(nsISupports** aSessionHistory) {
4318 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", 4318); return
NS_ERROR_INVALID_POINTER; } } while (false)
;
4319 RefPtr<ChildSHistory> shistory = GetSessionHistory();
4320 shistory.forget(aSessionHistory);
4321 return NS_OK;
4322}
4323
4324//*****************************************************************************
4325// nsDocShell::nsIWebPageDescriptor
4326//*****************************************************************************
4327
4328NS_IMETHODIMPnsresult
4329nsDocShell::LoadPageAsViewSource(nsIDocShell* aOtherDocShell,
4330 const nsAString& aURI) {
4331 if (!aOtherDocShell) {
4332 return NS_ERROR_INVALID_POINTER;
4333 }
4334 auto* otherDocShell = nsDocShell::Cast(aOtherDocShell);
4335
4336 Document* otherDoc = otherDocShell->GetDocument();
4337 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", 4337); return NS_ERROR_UNEXPECTED
; } } while (false)
;
4338
4339 nsCOMPtr<nsIURI> newURI;
4340 nsresult rv = NS_NewURI(getter_AddRefs(newURI), aURI);
4341 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
4342 return rv;
4343 }
4344
4345 RefPtr loadState = MakeRefPtr<nsDocShellLoadState>(newURI);
4346 if (!otherDocShell->FillLoadStateFromCurrentEntry(*loadState)) {
4347 return NS_ERROR_INVALID_POINTER;
4348 }
4349 uint32_t cacheKey = otherDocShell->GetCacheKeyFromCurrentEntry().valueOr(0);
4350
4351 // We're doing a load of the page, via an API that
4352 // is only exposed to system code. The triggering principal for this load
4353 // should be the system principal.
4354 loadState->SetTriggeringPrincipal(nsContentUtils::GetSystemPrincipal());
4355 RefPtr<nsIPrincipal> nullPrincipal =
4356 NullPrincipal::CreateWithInheritedAttributes(otherDoc->NodePrincipal());
4357 loadState->SetPrincipalToInherit(nullPrincipal);
4358 loadState->SetPartitionedPrincipalToInherit(nullPrincipal);
4359 loadState->SetOriginalURI(nullptr);
4360 loadState->SetResultPrincipalURI(nullptr);
4361
4362 // Initial about:blank handling is probably irrelevant, but newURI shouldn't
4363 // anyway be about:blank. Otherwise we should prohibit initial about blank
4364 // handling.
4365 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"
, 4366); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!NS_IsAboutBlankAllowQueryAndFragment(newURI)"
") (" "We only expect view-source:// URIs" ")"); do { MOZ_CrashSequence
(__null, 4366); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
4366 "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"
, 4366); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!NS_IsAboutBlankAllowQueryAndFragment(newURI)"
") (" "We only expect view-source:// URIs" ")"); do { MOZ_CrashSequence
(__null, 4366); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
4367
4368 return InternalLoad(loadState, Some(cacheKey));
4369}
4370
4371already_AddRefed<nsIInputStream> nsDocShell::GetPostDataFromCurrentEntry()
4372 const {
4373 nsCOMPtr<nsIInputStream> postData;
4374 if (mActiveEntry) {
4375 postData = mActiveEntry->GetPostData();
4376 } else if (mLoadingEntry) {
4377 postData = mLoadingEntry->mInfo.GetPostData();
4378 }
4379
4380 return postData.forget();
4381}
4382
4383Maybe<uint32_t> nsDocShell::GetCacheKeyFromCurrentEntry() const {
4384 if (mActiveEntry) {
4385 return Some(mActiveEntry->GetCacheKey());
4386 }
4387
4388 if (mLoadingEntry) {
4389 return Some(mLoadingEntry->mInfo.GetCacheKey());
4390 }
4391
4392 return Nothing();
4393}
4394
4395bool nsDocShell::FillLoadStateFromCurrentEntry(
4396 nsDocShellLoadState& aLoadState) {
4397 if (mLoadingEntry) {
4398 mLoadingEntry->mInfo.FillLoadInfo(aLoadState);
4399 return true;
4400 }
4401 if (mActiveEntry) {
4402 mActiveEntry->FillLoadInfo(aLoadState);
4403 return true;
4404 }
4405 return false;
4406}
4407
4408//*****************************************************************************
4409// nsDocShell::nsIBaseWindow
4410//*****************************************************************************
4411
4412NS_IMETHODIMPnsresult
4413nsDocShell::Destroy() {
4414 // XXX: We allow this function to be called just once. If you are going to
4415 // reset new variables in this function, please make sure the variables will
4416 // never be re-initialized. Adding assertions to check |mIsBeingDestroyed|
4417 // in the setter functions for the variables would be enough.
4418 if (mIsBeingDestroyed) {
4419 return NS_ERROR_DOCSHELL_DYING;
4420 }
4421
4422 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"
, 4423); MOZ_PretendNoReturn(); } } while (0)
4423 "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"
, 4423); MOZ_PretendNoReturn(); } } while (0)
;
4424
4425 nsCOMPtr<nsIObserverService> serv = services::GetObserverService();
4426 if (serv) {
4427 const char* msg = mItemType == typeContent
4428 ? NS_WEBNAVIGATION_DESTROY"webnavigation-destroy"
4429 : NS_CHROME_WEBNAVIGATION_DESTROY"chrome-webnavigation-destroy";
4430 serv->NotifyObservers(GetAsSupports(this), msg, nullptr);
4431 }
4432
4433 mIsBeingDestroyed = true;
4434
4435 // Brak the cycle with the initial client, if present.
4436 mInitialClientSource.reset();
4437
4438 // Make sure to blow away our mLoadingURI just in case. No loads
4439 // from inside this pagehide.
4440 mLoadingURI = nullptr;
4441
4442 // Fire unload event before we blow anything away.
4443 (void)FirePageHideNotification();
4444
4445 // Note: mContentListener can be null if Init() failed and we're being
4446 // called from the destructor.
4447 if (mContentListener) {
4448 mContentListener->DropDocShellReference();
4449 mContentListener->SetParentContentListener(nullptr);
4450 // Note that we do NOT set mContentListener to null here; that
4451 // way if someone tries to do a load in us after this point
4452 // the nsDSURIContentListener will block it. All of which
4453 // means that we should do this before calling Stop(), of
4454 // course.
4455 }
4456
4457 if (BrowsingContext* browsingContext = GetBrowsingContext();
4458 browsingContext && !browsingContext->IsTop()) {
4459 InformNavigationAPIAboutChildNavigableDestruction();
4460 }
4461
4462 // Stop any URLs that are currently being loaded...
4463 Stop(nsIWebNavigation::STOP_ALL);
4464
4465 mEditorData = nullptr;
4466
4467 // Save the state of the current document, before destroying the window.
4468 // This is needed to capture the state of a frameset when the new document
4469 // causes the frameset to be destroyed...
4470 PersistLayoutHistoryState();
4471
4472 // Remove this docshell from its parent's child list
4473 nsCOMPtr<nsIDocShellTreeItem> docShellParentAsItem =
4474 do_QueryInterface(GetAsSupports(mParent));
4475 if (docShellParentAsItem) {
4476 docShellParentAsItem->RemoveChild(this);
4477 }
4478
4479 DestroyDocumentViewer();
4480
4481 nsDocLoader::Destroy();
4482
4483 mParentWidget = nullptr;
4484 SetCurrentURIInternal(nullptr);
4485
4486 if (mScriptGlobal) {
4487 mScriptGlobal->DetachFromDocShell(!mWillChangeProcess);
4488 mScriptGlobal = nullptr;
4489 }
4490
4491 if (mWillChangeProcess && !mBrowsingContext->IsDiscarded()) {
4492 mBrowsingContext->PrepareForProcessChange();
4493 }
4494
4495 SetTreeOwner(nullptr);
4496
4497 mBrowserChild = nullptr;
4498
4499 mChromeEventHandler = nullptr;
4500
4501 mBCWebProgressStatusFilter = nullptr;
4502
4503 // Cancel any timers that were set for this docshell; this is needed
4504 // to break the cycle between us and the timers.
4505 CancelRefreshURITimers();
4506
4507 return NS_OK;
4508}
4509
4510double nsDocShell::GetWidgetCSSToDeviceScale() {
4511 if (mParentWidget) {
4512 return mParentWidget->GetDefaultScale().scale;
4513 }
4514 if (nsCOMPtr<nsIBaseWindow> ownerWindow = do_QueryInterface(mTreeOwner)) {
4515 return ownerWindow->GetWidgetCSSToDeviceScale();
4516 }
4517 return 1.0;
4518}
4519
4520NS_IMETHODIMPnsresult
4521nsDocShell::GetDevicePixelsPerDesktopPixel(double* aScale) {
4522 if (mParentWidget) {
4523 *aScale = mParentWidget->GetDesktopToDeviceScale().scale;
4524 return NS_OK;
4525 }
4526
4527 nsCOMPtr<nsIBaseWindow> ownerWindow(do_QueryInterface(mTreeOwner));
4528 if (ownerWindow) {
4529 return ownerWindow->GetDevicePixelsPerDesktopPixel(aScale);
4530 }
4531
4532 *aScale = 1.0;
4533 return NS_OK;
4534}
4535
4536NS_IMETHODIMPnsresult
4537nsDocShell::SetPosition(int32_t aX, int32_t aY) {
4538 mBounds.MoveTo(aX, aY);
4539
4540 if (mDocumentViewer) {
4541 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"
, 4541); return NS_ERROR_FAILURE; } } while (false)
;
4542 }
4543
4544 return NS_OK;
4545}
4546
4547NS_IMETHODIMPnsresult
4548nsDocShell::SetPositionDesktopPix(int32_t aX, int32_t aY) {
4549 nsCOMPtr<nsIBaseWindow> ownerWindow(do_QueryInterface(mTreeOwner));
4550 if (ownerWindow) {
4551 return ownerWindow->SetPositionDesktopPix(aX, aY);
4552 }
4553
4554 double scale = 1.0;
4555 GetDevicePixelsPerDesktopPixel(&scale);
4556 return SetPosition(NSToIntRound(aX * scale), NSToIntRound(aY * scale));
4557}
4558
4559NS_IMETHODIMPnsresult
4560nsDocShell::GetPosition(int32_t* aX, int32_t* aY) {
4561 return GetPositionAndSize(aX, aY, nullptr, nullptr);
4562}
4563
4564NS_IMETHODIMPnsresult
4565nsDocShell::SetSize(int32_t aWidth, int32_t aHeight, bool aRepaint) {
4566 int32_t x = 0, y = 0;
4567 GetPosition(&x, &y);
4568 return SetPositionAndSize(x, y, aWidth, aHeight,
4569 aRepaint ? nsIBaseWindow::eRepaint : 0);
4570}
4571
4572NS_IMETHODIMPnsresult
4573nsDocShell::GetSize(int32_t* aWidth, int32_t* aHeight) {
4574 return GetPositionAndSize(nullptr, nullptr, aWidth, aHeight);
4575}
4576
4577NS_IMETHODIMPnsresult
4578nsDocShell::SetPositionAndSize(int32_t aX, int32_t aY, int32_t aWidth,
4579 int32_t aHeight, uint32_t aFlags) {
4580 mBounds.SetRect(aX, aY, aWidth, aHeight);
4581
4582 // Hold strong ref, since SetBounds can make us null out mDocumentViewer
4583 nsCOMPtr<nsIDocumentViewer> viewer = mDocumentViewer;
4584 if (viewer) {
4585 uint32_t cvflags = (aFlags & nsIBaseWindow::eDelayResize)
4586 ? nsIDocumentViewer::eDelayResize
4587 : 0;
4588 // XXX Border figured in here or is that handled elsewhere?
4589 nsresult rv = viewer->SetBoundsWithFlags(mBounds, cvflags);
4590 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", 4590); return NS_ERROR_FAILURE
; } } while (false)
;
4591 }
4592
4593 if (nsCOMPtr<nsIObserverService> obs = services::GetObserverService()) {
4594 obs->NotifyObservers(GetAsSupports(this), "docshell-position-size-changed",
4595 nullptr);
4596 }
4597
4598 return NS_OK;
4599}
4600
4601NS_IMETHODIMPnsresult
4602nsDocShell::GetPositionAndSize(int32_t* aX, int32_t* aY, int32_t* aWidth,
4603 int32_t* aHeight) {
4604 if (mParentWidget) {
4605 // ensure size is up-to-date if window has changed resolution
4606 LayoutDeviceIntRect r = mParentWidget->GetClientBounds();
4607 SetPositionAndSize(mBounds.X(), mBounds.Y(), r.Width(), r.Height(), 0);
4608 }
4609
4610 // We should really consider just getting this information from
4611 // our window instead of duplicating the storage and code...
4612 if (aWidth || aHeight) {
4613 // Caller wants to know our size; make sure to give them up to
4614 // date information.
4615 RefPtr<Document> doc(do_GetInterface(GetAsSupports(mParent)));
4616 if (doc) {
4617 doc->FlushPendingNotifications(FlushType::Layout);
4618 }
4619 }
4620
4621 DoGetPositionAndSize(aX, aY, aWidth, aHeight);
4622 return NS_OK;
4623}
4624
4625void nsDocShell::DoGetPositionAndSize(int32_t* aX, int32_t* aY, int32_t* aWidth,
4626 int32_t* aHeight) {
4627 if (aX) {
4628 *aX = mBounds.X();
4629 }
4630 if (aY) {
4631 *aY = mBounds.Y();
4632 }
4633 if (aWidth) {
4634 *aWidth = mBounds.Width();
4635 }
4636 if (aHeight) {
4637 *aHeight = mBounds.Height();
4638 }
4639}
4640
4641NS_IMETHODIMPnsresult
4642nsDocShell::SetDimensions(DimensionRequest&& aRequest) {
4643 return NS_ERROR_NOT_IMPLEMENTED;
4644}
4645
4646NS_IMETHODIMPnsresult
4647nsDocShell::GetDimensions(DimensionKind aDimensionKind, int32_t* aX,
4648 int32_t* aY, int32_t* aCX, int32_t* aCY) {
4649 return NS_ERROR_NOT_IMPLEMENTED;
4650}
4651
4652NS_IMETHODIMPnsresult
4653nsDocShell::GetParentWidget(nsIWidget** aParentWidget) {
4654 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", 4654); return
NS_ERROR_INVALID_POINTER; } } while (false)
;
4655
4656 *aParentWidget = mParentWidget;
4657 NS_IF_ADDREF(*aParentWidget)ns_if_addref(*aParentWidget);
4658
4659 return NS_OK;
4660}
4661
4662NS_IMETHODIMPnsresult
4663nsDocShell::SetParentWidget(nsIWidget* aParentWidget) {
4664 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", 4664); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!mIsBeingDestroyed" ")"); do { MOZ_CrashSequence
(__null, 4664); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
4665 mParentWidget = aParentWidget;
4666
4667 return NS_OK;
4668}
4669
4670NS_IMETHODIMPnsresult
4671nsDocShell::GetNativeHandle(nsAString& aNativeHandle) {
4672 // the nativeHandle should be accessed from nsIAppWindow
4673 return NS_ERROR_NOT_IMPLEMENTED;
4674}
4675
4676NS_IMETHODIMPnsresult
4677nsDocShell::GetVisibility(bool* aVisibility) {
4678 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", 4678); return
NS_ERROR_INVALID_POINTER; } } while (false)
;
4679
4680 *aVisibility = false;
4681
4682 if (!mDocumentViewer) {
4683 return NS_OK;
4684 }
4685
4686 PresShell* presShell = GetPresShell();
4687 if (!presShell || presShell->IsUnderHiddenEmbedderElement()) {
4688 // NOTE(emilio): IsUnderHiddenEmbedderElement() accounts for ancestors as
4689 // well.
4690 return NS_OK;
4691 }
4692
4693 nsCOMPtr<nsIBaseWindow> treeOwnerAsWin(do_QueryInterface(mTreeOwner));
4694 if (!treeOwnerAsWin) {
4695 *aVisibility = true;
4696 return NS_OK;
4697 }
4698
4699 // Check with the tree owner as well to give embedders a chance to
4700 // expose visibility as well.
4701 nsresult rv = treeOwnerAsWin->GetVisibility(aVisibility);
4702 if (rv == NS_ERROR_NOT_IMPLEMENTED) {
4703 // The tree owner had no opinion on our visibility.
4704 *aVisibility = true;
4705 return NS_OK;
4706 }
4707 return rv;
4708}
4709
4710void nsDocShell::ActivenessMaybeChanged() {
4711 const bool isActive = mBrowsingContext->IsActive();
4712 if (RefPtr<PresShell> presShell = GetPresShell()) {
4713 presShell->ActivenessMaybeChanged();
4714 }
4715
4716 // Tell the window about it
4717 if (mScriptGlobal) {
4718 mScriptGlobal->SetIsBackground(!isActive);
4719 if (RefPtr<Document> doc = mScriptGlobal->GetExtantDoc()) {
4720 // Update orientation when the top-level browsing context becomes active.
4721 if (isActive && mBrowsingContext->IsTop() &&
4722 !mBrowsingContext->Windowless()) {
4723 // We only care about the top-level browsing context.
4724 auto orientation = mBrowsingContext->GetOrientationLock();
4725 ScreenOrientation::UpdateActiveOrientationLock(orientation);
4726 }
4727
4728 doc->PostVisibilityUpdateEvent();
4729 }
4730 }
4731
4732 // Tell the nsDOMNavigationTiming about it
4733 RefPtr<nsDOMNavigationTiming> timing = mTiming;
4734 if (!timing && mDocumentViewer) {
4735 if (Document* doc = mDocumentViewer->GetDocument()) {
4736 timing = doc->GetNavigationTiming();
4737 }
4738 }
4739 if (timing) {
4740 timing->NotifyDocShellStateChanged(
4741 isActive ? nsDOMNavigationTiming::DocShellState::eActive
4742 : nsDOMNavigationTiming::DocShellState::eInactive);
4743 }
4744
4745 // Restart or stop meta refresh timers if necessary
4746 if (mDisableMetaRefreshWhenInactive) {
4747 if (isActive) {
4748 ResumeRefreshURIs();
4749 } else {
4750 SuspendRefreshURIs();
4751 }
4752 }
4753
4754 if (InputTaskManager::CanSuspendInputEvent()) {
4755 mBrowsingContext->Group()->UpdateInputTaskManagerIfNeeded(isActive);
4756 }
4757}
4758
4759NS_IMETHODIMPnsresult
4760nsDocShell::SetDefaultLoadFlags(uint32_t aDefaultLoadFlags) {
4761 if (!mWillChangeProcess) {
4762 // Intentionally ignoring handling discarded browsing contexts.
4763 (void)mBrowsingContext->SetDefaultLoadFlags(aDefaultLoadFlags);
4764 } else {
4765 // Bug 1623565: DevTools tries to clean up defaultLoadFlags on
4766 // shutdown. Sorry DevTools, your DocShell is in another process.
4767 NS_WARNING("nsDocShell::SetDefaultLoadFlags called on Zombie DocShell")NS_DebugBreak(NS_DEBUG_WARNING, "nsDocShell::SetDefaultLoadFlags called on Zombie DocShell"
, nullptr, "./../../../docshell/base/nsDocShell.cpp", 4767)
;
4768 }
4769 return NS_OK;
4770}
4771
4772NS_IMETHODIMPnsresult
4773nsDocShell::GetDefaultLoadFlags(uint32_t* aDefaultLoadFlags) {
4774 *aDefaultLoadFlags = mBrowsingContext->GetDefaultLoadFlags();
4775 return NS_OK;
4776}
4777
4778NS_IMETHODIMPnsresult
4779nsDocShell::GetFailedChannel(nsIChannel** aFailedChannel) {
4780 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", 4780); return
NS_ERROR_INVALID_POINTER; } } while (false)
;
4781 Document* doc = GetDocument();
4782 if (!doc) {
4783 *aFailedChannel = nullptr;
4784 return NS_OK;
4785 }
4786 NS_IF_ADDREF(*aFailedChannel = doc->GetFailedChannel())ns_if_addref(*aFailedChannel = doc->GetFailedChannel());
4787 return NS_OK;
4788}
4789
4790NS_IMETHODIMPnsresult
4791nsDocShell::SetVisibility(bool aVisibility) {
4792 // Show()/Hide() may change mDocumentViewer.
4793 nsCOMPtr<nsIDocumentViewer> viewer = mDocumentViewer;
4794 if (!viewer) {
4795 return NS_OK;
4796 }
4797 if (aVisibility) {
4798 viewer->Show();
4799 } else {
4800 viewer->Hide();
4801 }
4802
4803 return NS_OK;
4804}
4805
4806NS_IMETHODIMPnsresult
4807nsDocShell::GetEnabled(bool* aEnabled) {
4808 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", 4808); return NS_ERROR_INVALID_POINTER
; } } while (false)
;
4809 *aEnabled = true;
4810 return NS_ERROR_NOT_IMPLEMENTED;
4811}
4812
4813NS_IMETHODIMPnsresult
4814nsDocShell::SetEnabled(bool aEnabled) { return NS_ERROR_NOT_IMPLEMENTED; }
4815
4816NS_IMETHODIMPnsresult
4817nsDocShell::GetMainWidget(nsIWidget** aMainWidget) {
4818 // We don't create our own widget, so simply return the parent one.
4819 return GetParentWidget(aMainWidget);
4820}
4821
4822NS_IMETHODIMPnsresult
4823nsDocShell::GetTitle(nsAString& aTitle) {
4824 aTitle = mTitle;
4825 return NS_OK;
4826}
4827
4828NS_IMETHODIMPnsresult
4829nsDocShell::SetTitle(const nsAString& aTitle) {
4830 // Avoid unnecessary updates of the title if the URI and the title haven't
4831 // changed.
4832 if (mTitleValidForCurrentURI && mTitle == aTitle) {
4833 return NS_OK;
4834 }
4835
4836 // Store local title
4837 mTitle = aTitle;
4838 mTitleValidForCurrentURI = true;
4839
4840 // When title is set on the top object it should then be passed to the
4841 // tree owner.
4842 if (mBrowsingContext->IsTop()) {
4843 nsCOMPtr<nsIBaseWindow> treeOwnerAsWin(do_QueryInterface(mTreeOwner));
4844 if (treeOwnerAsWin) {
4845 treeOwnerAsWin->SetTitle(aTitle);
4846 }
4847 }
4848
4849 if (mCurrentURI && mLoadType != LOAD_ERROR_PAGE) {
4850 UpdateGlobalHistoryTitle(mCurrentURI);
4851 }
4852
4853 // Update SessionHistory with the document's title.
4854 if (mLoadType != LOAD_BYPASS_HISTORY && mLoadType != LOAD_ERROR_PAGE) {
4855 SetTitleOnHistoryEntry(true);
4856 }
4857
4858 return NS_OK;
4859}
4860
4861void nsDocShell::SetTitleOnHistoryEntry(bool aUpdateEntryInSessionHistory) {
4862 if (mActiveEntry && mBrowsingContext) {
4863 mActiveEntry->SetTitle(mTitle);
4864 if (aUpdateEntryInSessionHistory) {
4865 if (XRE_IsParentProcess()) {
4866 SessionHistoryEntry* entry =
4867 mBrowsingContext->Canonical()->GetActiveSessionHistoryEntry();
4868 if (entry) {
4869 entry->SetTitle(mTitle);
4870 }
4871 } else {
4872 (void)ContentChild::GetSingleton()->SendSessionHistoryEntryTitle(
4873 mBrowsingContext, mTitle);
4874 }
4875 }
4876 }
4877}
4878
4879nsPoint nsDocShell::GetCurScrollPos() {
4880 nsPoint scrollPos;
4881 if (ScrollContainerFrame* sf = GetRootScrollContainerFrame()) {
4882 scrollPos = sf->GetVisualViewportOffset();
4883 }
4884 return scrollPos;
4885}
4886
4887nsresult nsDocShell::SetCurScrollPosEx(int32_t aCurHorizontalPos,
4888 int32_t aCurVerticalPos) {
4889 ScrollContainerFrame* sf = GetRootScrollContainerFrame();
4890 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"
, 4890); return NS_ERROR_FAILURE; } } while (false)
;
4891
4892 ScrollMode scrollMode = sf->ScrollModeForScrollBehavior();
4893
4894 nsPoint targetPos(aCurHorizontalPos, aCurVerticalPos);
4895 sf->ScrollTo(targetPos, scrollMode);
4896
4897 // Set the visual viewport offset as well.
4898
4899 RefPtr<PresShell> presShell = GetPresShell();
4900 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", 4900); return NS_ERROR_FAILURE
; } } while (false)
;
4901
4902 nsPresContext* presContext = presShell->GetPresContext();
4903 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", 4903); return
NS_ERROR_FAILURE; } } while (false)
;
4904
4905 // Only the root content document can have a distinct visual viewport offset.
4906 if (!presContext->IsRootContentDocumentCrossProcess()) {
4907 return NS_OK;
4908 }
4909
4910 // Not on a platform with a distinct visual viewport - don't bother setting
4911 // the visual viewport offset.
4912 if (!presShell->IsVisualViewportSizeSet()) {
4913 return NS_OK;
4914 }
4915
4916 presShell->ScrollToVisual(
4917 targetPos, layers::ScrollOffsetUpdateType::MainThread, scrollMode);
4918
4919 return NS_OK;
4920}
4921
4922void nsDocShell::RestoreScrollPositionFromTargetSessionHistoryInfo(
4923 SessionHistoryInfo* aTarget) {
4924 nscoord bx = 0;
4925 nscoord by = 0;
4926 if (aTarget) {
4927 aTarget->GetScrollPosition(&bx, &by);
4928 }
4929 SetCurScrollPosEx(bx, by);
4930}
4931
4932void nsDocShell::SetScrollbarPreference(mozilla::ScrollbarPreference aPref) {
4933 if (mScrollbarPref == aPref) {
4934 return;
4935 }
4936 mScrollbarPref = aPref;
4937 auto* ps = GetPresShell();
4938 if (!ps) {
4939 return;
4940 }
4941 nsIFrame* rootScrollContainerFrame = ps->GetRootScrollContainerFrame();
4942 if (!rootScrollContainerFrame) {
4943 return;
4944 }
4945 ps->FrameNeedsReflow(rootScrollContainerFrame,
4946 IntrinsicDirty::FrameAncestorsAndDescendants,
4947 NS_FRAME_IS_DIRTY);
4948}
4949
4950//*****************************************************************************
4951// nsDocShell::nsIRefreshURI
4952//*****************************************************************************
4953
4954NS_IMETHODIMPnsresult
4955nsDocShell::RefreshURI(nsIURI* aURI, nsIPrincipal* aPrincipal,
4956 uint32_t aDelay) {
4957 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", 4957); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!mIsBeingDestroyed" ")"); do { MOZ_CrashSequence
(__null, 4957); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
4958
4959 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", 4959); return NS_ERROR_INVALID_ARG
; } } while (false)
;
4960
4961 /* Check if Meta refresh/redirects are permitted. Some
4962 * embedded applications may not want to do this.
4963 * Must do this before sending out NOTIFY_REFRESH events
4964 * because listeners may have side effects (e.g. displaying a
4965 * button to manually trigger the refresh later).
4966 */
4967 bool allowRedirects = true;
4968 GetAllowMetaRedirects(&allowRedirects);
4969 if (!allowRedirects) {
4970 return NS_OK;
4971 }
4972
4973 // If any web progress listeners are listening for NOTIFY_REFRESH events,
4974 // give them a chance to block this refresh.
4975 bool sameURI;
4976 nsresult rv = aURI->Equals(mCurrentURI, &sameURI);
4977 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
4978 sameURI = false;
4979 }
4980 if (!RefreshAttempted(this, aURI, aDelay, sameURI)) {
4981 return NS_OK;
4982 }
4983
4984 nsCOMPtr<nsITimerCallback> refreshTimer =
4985 MakeRefPtr<nsRefreshTimer>(this, aURI, aPrincipal, aDelay);
4986
4987 BusyFlags busyFlags = GetBusyFlags();
4988
4989 if (!mRefreshURIList) {
4990 mRefreshURIList = nsArray::Create();
4991 }
4992
4993 if (busyFlags & BUSY_FLAGS_BUSY ||
4994 (!mBrowsingContext->IsActive() && mDisableMetaRefreshWhenInactive)) {
4995 // We don't want to create the timer right now. Instead queue up the
4996 // request and trigger the timer in EndPageLoad() or whenever we become
4997 // active.
4998 mRefreshURIList->AppendElement(refreshTimer);
4999 } else {
5000 // There is no page loading going on right now. Create the
5001 // timer and fire it right away.
5002 nsCOMPtr<nsPIDOMWindowOuter> win = GetWindow();
5003 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"
, 5003); return NS_ERROR_FAILURE; } } while (false)
;
5004
5005 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(); })
5006 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(); })
;
5007
5008 mRefreshURIList->AppendElement(timer); // owning timer ref
5009 }
5010 return NS_OK;
5011}
5012
5013nsresult nsDocShell::ForceRefreshURIFromTimer(nsIURI* aURI,
5014 nsIPrincipal* aPrincipal,
5015 uint32_t aDelay,
5016 nsITimer* aTimer) {
5017 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", 5017); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aTimer" ") (" "Must have a timer here" ")"
); do { MOZ_CrashSequence(__null, 5017); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5018
5019 // Remove aTimer from mRefreshURIList if needed
5020 if (mRefreshURIList) {
5021 uint32_t n = 0;
5022 mRefreshURIList->GetLength(&n);
5023
5024 for (uint32_t i = 0; i < n; ++i) {
5025 nsCOMPtr<nsITimer> timer = do_QueryElementAt(mRefreshURIList, i);
5026 if (timer == aTimer) {
5027 mRefreshURIList->RemoveElementAt(i);
5028 break;
5029 }
5030 }
5031 }
5032
5033 return ForceRefreshURI(aURI, aPrincipal, aDelay);
5034}
5035
5036NS_IMETHODIMPnsresult
5037nsDocShell::ForceRefreshURI(nsIURI* aURI, nsIPrincipal* aPrincipal,
5038 uint32_t aDelay) {
5039 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", 5039); return NS_ERROR_INVALID_ARG
; } } while (false)
;
5040
5041 RefPtr loadState = MakeRefPtr<nsDocShellLoadState>(aURI);
5042 loadState->SetOriginalURI(mCurrentURI);
5043 loadState->SetResultPrincipalURI(aURI);
5044 loadState->SetResultPrincipalURIIsSome(true);
5045 loadState->SetKeepResultPrincipalURIIfSet(true);
5046 loadState->SetIsMetaRefresh(true);
5047
5048 RefPtr<Document> doc = GetDocument();
5049 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"
, 5049); return NS_ERROR_UNEXPECTED; } } while (false)
;
5050
5051 // Set the triggering pricipal to aPrincipal if available, or current
5052 // document's principal otherwise.
5053 nsCOMPtr<nsIPrincipal> principal = aPrincipal;
5054 if (!principal) {
5055 principal = doc->NodePrincipal();
5056 }
5057 loadState->SetTriggeringPrincipal(principal);
5058 loadState->SetPolicyContainer(doc->GetPolicyContainer());
5059 loadState->SetHasValidUserGestureActivation(
5060 doc->HasValidTransientUserGestureActivation());
5061
5062 loadState->SetTextDirectiveUserActivation(
5063 doc->ConsumeTextDirectiveUserActivation() ||
5064 loadState->HasValidUserGestureActivation());
5065 loadState->SetTriggeringSandboxFlags(doc->GetSandboxFlags());
5066 loadState->SetTriggeringWindowId(doc->InnerWindowID());
5067 loadState->SetTriggeringClassificationFlags(doc->GetScriptTrackingFlags());
5068
5069 loadState->SetPrincipalIsExplicit(true);
5070
5071 /* Check if this META refresh causes a redirection
5072 * to another site.
5073 */
5074 bool equalUri = false;
5075 nsresult rv = aURI->Equals(mCurrentURI, &equalUri);
5076
5077 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && !equalUri && aDelay <= REFRESH_REDIRECT_TIMER15000) {
5078 /* It is a META refresh based redirection within the threshold time
5079 * we have in mind (15000 ms as defined by REFRESH_REDIRECT_TIMER).
5080 * Pass a REPLACE flag to LoadURI().
5081 */
5082 loadState->SetLoadType(LOAD_REFRESH_REPLACE);
5083 } else {
5084 loadState->SetLoadType(LOAD_REFRESH);
5085 }
5086
5087 const bool sendReferrer = StaticPrefs::network_http_referer_sendFromRefresh();
5088 /* The document's referrer policy is needed instead of mReferrerInfo's
5089 * referrer policy.
5090 */
5091 const RefPtr referrerInfo = MakeRefPtr<ReferrerInfo>(*doc, sendReferrer);
5092 /* We mimic HTTP, which passes the original referrer. See step 3 of
5093 * <https://html.spec.whatwg.org/multipage/browsing-the-web.html#create-navigation-params-by-fetching>.
5094 */
5095 loadState->SetReferrerInfo(referrerInfo);
5096
5097 loadState->SetLoadFlags(
5098 nsIWebNavigation::LOAD_FLAGS_DISALLOW_INHERIT_PRINCIPAL);
5099 loadState->SetFirstParty(true);
5100
5101 /*
5102 * LoadURI(...) will cancel all refresh timers... This causes the
5103 * Timer and its refreshData instance to be released...
5104 */
5105 LoadURI(loadState, false);
5106
5107 return NS_OK;
5108}
5109
5110static const char16_t* SkipASCIIWhitespace(const char16_t* aStart,
5111 const char16_t* aEnd) {
5112 const char16_t* iter = aStart;
5113 while (iter != aEnd && mozilla::IsAsciiWhitespace(*iter)) {
5114 ++iter;
5115 }
5116 return iter;
5117}
5118
5119static std::tuple<const char16_t*, const char16_t*> ExtractURLString(
5120 const char16_t* aPosition, const char16_t* aEnd) {
5121 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", 5121); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aPosition != aEnd" ")"); do { MOZ_CrashSequence
(__null, 5121); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
5122
5123 // 1. Let urlString be the substring of input from the code point at
5124 // position to the end of the string.
5125 const char16_t* urlStart = aPosition;
5126 const char16_t* urlEnd = aEnd;
5127
5128 // 2. If the code point in input pointed to by position is U+0055 (U) or
5129 // U+0075 (u), then advance position to the next code point.
5130 // Otherwise, jump to the step labeled skip quotes.
5131 if (*aPosition == 'U' || *aPosition == 'u') {
5132 ++aPosition;
5133
5134 // 3. If the code point in input pointed to by position is U+0052 (R) or
5135 // U+0072 (r), then advance position to the next code point.
5136 // Otherwise, jump to the step labeled parse.
5137 if (aPosition == aEnd || (*aPosition != 'R' && *aPosition != 'r')) {
5138 return std::make_tuple(urlStart, urlEnd);
5139 }
5140
5141 ++aPosition;
5142
5143 // 4. If the code point in input pointed to by position is U+004C (L) or
5144 // U+006C (l), then advance position to the next code point.
5145 // Otherwise, jump to the step labeled parse.
5146 if (aPosition == aEnd || (*aPosition != 'L' && *aPosition != 'l')) {
5147 return std::make_tuple(urlStart, urlEnd);
5148 }
5149
5150 ++aPosition;
5151
5152 // 5. Skip ASCII whitespace within input given position.
5153 aPosition = SkipASCIIWhitespace(aPosition, aEnd);
5154
5155 // 6. If the code point in input pointed to by position is U+003D (=),
5156 // then advance position to the next code point. Otherwise, jump to
5157 // the step labeled parse.
5158 if (aPosition == aEnd || *aPosition != '=') {
5159 return std::make_tuple(urlStart, urlEnd);
5160 }
5161
5162 ++aPosition;
5163
5164 // 7. Skip ASCII whitespace within input given position.
5165 aPosition = SkipASCIIWhitespace(aPosition, aEnd);
5166 }
5167
5168 // 8. Skip quotes: If the code point in input pointed to by position is
5169 // U+0027 (') or U+0022 ("), then let quote be that code point, and
5170 // advance position to the next code point. Otherwise, let quote be
5171 // the empty string.
5172 Maybe<char> quote;
5173 if (aPosition != aEnd && (*aPosition == '\'' || *aPosition == '"')) {
5174 quote.emplace(*aPosition);
5175 ++aPosition;
5176 }
5177
5178 // 9. Set urlString to the substring of input from the code point at
5179 // position to the end of the string.
5180 urlStart = aPosition;
5181 urlEnd = aEnd;
5182
5183 // 10. If quote is not the empty string, and there is a code point in
5184 // urlString equal to quote, then truncate urlString at that code
5185 // point, so that it and all subsequent code points are removed.
5186 const char16_t* quotePos;
5187 if (quote.isSome() &&
5188 (quotePos = nsCharTraits<char16_t>::find(
5189 urlStart, std::distance(urlStart, aEnd), quote.value()))) {
5190 urlEnd = quotePos;
5191 }
5192
5193 return std::make_tuple(urlStart, urlEnd);
5194}
5195
5196void nsDocShell::SetupRefreshURIFromHeader(Document* aDocument,
5197 const nsAString& aHeader) {
5198 if (mIsBeingDestroyed) {
5199 return;
5200 }
5201
5202 const char16_t* position = aHeader.BeginReading();
5203 const char16_t* end = aHeader.EndReading();
5204
5205 // See https://html.spec.whatwg.org/#shared-declarative-refresh-steps.
5206
5207 // 3. Skip ASCII whitespace
5208 position = SkipASCIIWhitespace(position, end);
5209
5210 // 4. Let time be 0.
5211 CheckedInt<uint32_t> milliSeconds;
5212
5213 // 5. Collect a sequence of code points that are ASCII digits
5214 const char16_t* digitsStart = position;
5215 while (position != end && mozilla::IsAsciiDigit(*position)) {
5216 ++position;
5217 }
5218
5219 if (position == digitsStart) {
5220 // 6. If timeString is the empty string, then:
5221 // 1. If the code point in input pointed to by position is not U+002E
5222 // (.), then return.
5223 if (position == end || *position != '.') {
5224 return;
5225 }
5226 } else {
5227 // 7. Otherwise, set time to the result of parsing timeString using the
5228 // rules for parsing non-negative integers.
5229 nsContentUtils::ParseHTMLIntegerResultFlags result;
5230 uint32_t seconds =
5231 nsContentUtils::ParseHTMLInteger(digitsStart, position, &result);
5232 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", 5232); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!(result & nsContentUtils::eParseHTMLInteger_Negative)"
")"); do { MOZ_CrashSequence(__null, 5232); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5233 if (result & nsContentUtils::eParseHTMLInteger_Error) {
5234 // The spec assumes no errors here (since we only pass ASCII digits in),
5235 // but we can still overflow, so this block should deal with that (and
5236 // only that).
5237 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", 5240); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!(result & ~(nsContentUtils::eParseHTMLInteger_DidNotConsumeAllInput | nsContentUtils::eParseHTMLInteger_Error | nsContentUtils::eParseHTMLInteger_ErrorOverflow))"
")"); do { MOZ_CrashSequence(__null, 5240); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
5238 !(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", 5240); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!(result & ~(nsContentUtils::eParseHTMLInteger_DidNotConsumeAllInput | nsContentUtils::eParseHTMLInteger_Error | nsContentUtils::eParseHTMLInteger_ErrorOverflow))"
")"); do { MOZ_CrashSequence(__null, 5240); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
5239 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", 5240); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!(result & ~(nsContentUtils::eParseHTMLInteger_DidNotConsumeAllInput | nsContentUtils::eParseHTMLInteger_Error | nsContentUtils::eParseHTMLInteger_ErrorOverflow))"
")"); do { MOZ_CrashSequence(__null, 5240); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
5240 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", 5240); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!(result & ~(nsContentUtils::eParseHTMLInteger_DidNotConsumeAllInput | nsContentUtils::eParseHTMLInteger_Error | nsContentUtils::eParseHTMLInteger_ErrorOverflow))"
")"); do { MOZ_CrashSequence(__null, 5240); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5241 return;
5242 }
5243 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", 5244); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!(result & nsContentUtils::eParseHTMLInteger_DidNotConsumeAllInput)"
")"); do { MOZ_CrashSequence(__null, 5244); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
5244 !(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", 5244); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!(result & nsContentUtils::eParseHTMLInteger_DidNotConsumeAllInput)"
")"); do { MOZ_CrashSequence(__null, 5244); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5245
5246 milliSeconds = seconds;
5247 milliSeconds *= 1000;
5248 if (!milliSeconds.isValid()) {
5249 return;
5250 }
5251 }
5252
5253 // 8. Collect a sequence of code points that are ASCII digits and U+002E FULL
5254 // STOP characters (.) from input given position. Ignore any collected
5255 // characters.
5256 while (position != end &&
5257 (mozilla::IsAsciiDigit(*position) || *position == '.')) {
5258 ++position;
5259 }
5260
5261 // 9. Let urlRecord be document's URL.
5262 nsCOMPtr<nsIURI> urlRecord(aDocument->GetDocumentURI());
5263
5264 // 10. If position is not past the end of input
5265 if (position != end) {
5266 // 1. If the code point in input pointed to by position is not U+003B (;),
5267 // U+002C (,), or ASCII whitespace, then return.
5268 if (*position != ';' && *position != ',' &&
5269 !mozilla::IsAsciiWhitespace(*position)) {
5270 return;
5271 }
5272
5273 // 2. Skip ASCII whitespace within input given position.
5274 position = SkipASCIIWhitespace(position, end);
5275
5276 // 3. If the code point in input pointed to by position is U+003B (;) or
5277 // U+002C (,), then advance position to the next code point.
5278 if (position != end && (*position == ';' || *position == ',')) {
5279 ++position;
5280
5281 // 4. Skip ASCII whitespace within input given position.
5282 position = SkipASCIIWhitespace(position, end);
5283 }
5284
5285 // 11. If position is not past the end of input, then:
5286 if (position != end) {
5287 const char16_t* urlStart;
5288 const char16_t* urlEnd;
5289
5290 // 1-10. See ExtractURLString.
5291 std::tie(urlStart, urlEnd) = ExtractURLString(position, end);
5292
5293 // 11. Parse: Parse urlString relative to document. If that fails, return.
5294 // Otherwise, set urlRecord to the resulting URL record.
5295 nsresult rv =
5296 NS_NewURI(getter_AddRefs(urlRecord),
5297 Substring(urlStart, std::distance(urlStart, urlEnd)),
5298 /* charset = */ nullptr, aDocument->GetDocBaseURI());
5299 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"
, 5299); return; } } while (false)
;
5300 }
5301 }
5302
5303 nsIPrincipal* principal = aDocument->NodePrincipal();
5304 nsCOMPtr<nsIScriptSecurityManager> securityManager =
5305 nsContentUtils::GetSecurityManager();
5306 nsresult rv = securityManager->CheckLoadURIWithPrincipal(
5307 principal, urlRecord,
5308 nsIScriptSecurityManager::LOAD_IS_AUTOMATIC_DOCUMENT_REPLACEMENT,
5309 aDocument->InnerWindowID());
5310 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"
, 5310); return; } } while (false)
;
5311
5312 bool isjs = true;
5313 rv = NS_URIChainHasFlags(
5314 urlRecord, nsIProtocolHandler::URI_OPENING_EXECUTES_SCRIPT, &isjs);
5315 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"
, 5315); return; } } while (false)
;
5316
5317 if (isjs) {
5318 return;
5319 }
5320
5321 RefreshURI(urlRecord, principal, milliSeconds.value());
5322}
5323
5324static void DoCancelRefreshURITimers(nsIMutableArray* aTimerList) {
5325 if (!aTimerList) {
5326 return;
5327 }
5328
5329 uint32_t n = 0;
5330 aTimerList->GetLength(&n);
5331
5332 while (n) {
5333 nsCOMPtr<nsITimer> timer(do_QueryElementAt(aTimerList, --n));
5334
5335 aTimerList->RemoveElementAt(n); // bye bye owning timer ref
5336
5337 if (timer) {
5338 timer->Cancel();
5339 }
5340 }
5341}
5342
5343NS_IMETHODIMPnsresult
5344nsDocShell::CancelRefreshURITimers() {
5345 DoCancelRefreshURITimers(mRefreshURIList);
5346 DoCancelRefreshURITimers(mSavedRefreshURIList);
5347 DoCancelRefreshURITimers(mBFCachedRefreshURIList);
5348 mRefreshURIList = nullptr;
5349 mSavedRefreshURIList = nullptr;
5350 mBFCachedRefreshURIList = nullptr;
5351
5352 return NS_OK;
5353}
5354
5355NS_IMETHODIMPnsresult
5356nsDocShell::GetRefreshPending(bool* aResult) {
5357 if (!mRefreshURIList) {
5358 *aResult = false;
5359 return NS_OK;
5360 }
5361
5362 uint32_t count;
5363 nsresult rv = mRefreshURIList->GetLength(&count);
5364 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
5365 *aResult = (count != 0);
5366 }
5367 return rv;
5368}
5369
5370void nsDocShell::RefreshURIToQueue() {
5371 if (mRefreshURIList) {
5372 uint32_t n = 0;
5373 mRefreshURIList->GetLength(&n);
5374
5375 for (uint32_t i = 0; i < n; ++i) {
5376 nsCOMPtr<nsITimer> timer = do_QueryElementAt(mRefreshURIList, i);
5377 if (!timer) {
5378 continue; // this must be a nsRefreshURI already
5379 }
5380
5381 // Replace this timer object with a nsRefreshTimer object.
5382 nsCOMPtr<nsITimerCallback> callback;
5383 timer->GetCallback(getter_AddRefs(callback));
5384
5385 timer->Cancel();
5386
5387 mRefreshURIList->ReplaceElementAt(callback, i);
5388 }
5389 }
5390}
5391
5392NS_IMETHODIMPnsresult
5393nsDocShell::SuspendRefreshURIs() {
5394 RefreshURIToQueue();
5395
5396 // Suspend refresh URIs for our child shells as well.
5397 for (auto* child : mChildList.ForwardRange()) {
5398 nsCOMPtr<nsIDocShell> shell = do_QueryObject(child);
5399 if (shell) {
5400 shell->SuspendRefreshURIs();
5401 }
5402 }
5403
5404 return NS_OK;
5405}
5406
5407NS_IMETHODIMPnsresult
5408nsDocShell::ResumeRefreshURIs() {
5409 RefreshURIFromQueue();
5410
5411 // Resume refresh URIs for our child shells as well.
5412 for (auto* child : mChildList.ForwardRange()) {
5413 nsCOMPtr<nsIDocShell> shell = do_QueryObject(child);
5414 if (shell) {
5415 shell->ResumeRefreshURIs();
5416 }
5417 }
5418
5419 return NS_OK;
5420}
5421
5422nsresult nsDocShell::RefreshURIFromQueue() {
5423 if (!mRefreshURIList) {
5424 return NS_OK;
5425 }
5426 uint32_t n = 0;
5427 mRefreshURIList->GetLength(&n);
5428
5429 while (n) {
5430 nsCOMPtr<nsITimerCallback> refreshInfo =
5431 do_QueryElementAt(mRefreshURIList, --n);
5432
5433 if (refreshInfo) {
5434 // This is the nsRefreshTimer object, waiting to be
5435 // setup in a timer object and fired.
5436 // Create the timer and trigger it.
5437 uint32_t delay = static_cast<nsRefreshTimer*>(
5438 static_cast<nsITimerCallback*>(refreshInfo))
5439 ->GetDelay();
5440 nsCOMPtr<nsPIDOMWindowOuter> win = GetWindow();
5441 if (win) {
5442 nsCOMPtr<nsITimer> timer;
5443 NS_NewTimerWithCallback(getter_AddRefs(timer), refreshInfo, delay,
5444 nsITimer::TYPE_ONE_SHOT);
5445
5446 if (timer) {
5447 // Replace the nsRefreshTimer element in the queue with
5448 // its corresponding timer object, so that in case another
5449 // load comes through before the timer can go off, the timer will
5450 // get cancelled in CancelRefreshURITimer()
5451 mRefreshURIList->ReplaceElementAt(timer, n);
5452 }
5453 }
5454 }
5455 }
5456
5457 return NS_OK;
5458}
5459
5460static bool IsFollowupPartOfMultipart(nsIRequest* aRequest) {
5461 nsCOMPtr<nsIMultiPartChannel> multiPartChannel = do_QueryInterface(aRequest);
5462 bool firstPart = false;
5463 return multiPartChannel &&
5464 NS_SUCCEEDED(multiPartChannel->GetIsFirstPart(&firstPart))((bool)(__builtin_expect(!!(!NS_FAILED_impl(multiPartChannel->
GetIsFirstPart(&firstPart))), 1)))
&&
5465 !firstPart;
5466}
5467
5468nsresult nsDocShell::Embed(nsIDocumentViewer* aDocumentViewer,
5469 WindowGlobalChild* aWindowActor,
5470 bool aIsTransientAboutBlank, nsIRequest* aRequest,
5471 nsIURI* aPreviousURI) {
5472 // Save the LayoutHistoryState of the previous document, before
5473 // setting up new document
5474 PersistLayoutHistoryState();
5475
5476 nsresult rv = SetupNewViewer(aDocumentViewer, aWindowActor);
5477 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"
, 5477); return rv; } } while (false)
;
5478
5479 // XXX What if SetupNewViewer fails?
5480 if (mLoadingEntry) {
5481 // Set history.state
5482 SetDocCurrentStateObj(mLoadingEntry ? &mLoadingEntry->mInfo : nullptr);
5483 }
5484
5485 if (!aIsTransientAboutBlank && !IsFollowupPartOfMultipart(aRequest)) {
5486 bool expired = false;
5487 uint32_t cacheKey = 0;
5488 nsCOMPtr<nsICacheInfoChannel> cacheChannel = do_QueryInterface(aRequest);
5489 if (cacheChannel) {
5490 // Check if the page has expired from cache
5491 uint32_t expTime = 0;
5492 cacheChannel->GetCacheTokenExpirationTime(&expTime);
5493 uint32_t now = PRTimeToSeconds(PR_Now());
5494 if (expTime <= now) {
5495 expired = true;
5496 }
5497
5498 // The checks for updating cache key are similar to the old session
5499 // history in OnNewURI. Try to update the cache key if
5500 // - we should update session history and aren't doing a session
5501 // history load.
5502 // - we're doing a forced reload.
5503 if (((!mLoadingEntry || !mLoadingEntry->mLoadIsFromSessionHistory) &&
5504 mBrowsingContext->ShouldUpdateSessionHistory(mLoadType)) ||
5505 IsForceReloadType(mLoadType)) {
5506 cacheChannel->GetCacheKey(&cacheKey);
5507 }
5508 }
5509
5510 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)
;
5511 MoveLoadingToActiveEntry(expired, cacheKey, aPreviousURI);
5512 }
5513
5514 bool updateHistory = true;
5515
5516 // Determine if this type of load should update history
5517 switch (mLoadType) {
5518 case LOAD_NORMAL_REPLACE:
5519 case LOAD_REFRESH_REPLACE:
5520 case LOAD_STOP_CONTENT_AND_REPLACE:
5521 case LOAD_RELOAD_BYPASS_CACHE:
5522 case LOAD_RELOAD_BYPASS_PROXY:
5523 case LOAD_RELOAD_BYPASS_PROXY_AND_CACHE:
5524 case LOAD_REPLACE_BYPASS_CACHE:
5525 updateHistory = false;
5526 break;
5527 default:
5528 break;
5529 }
5530
5531 if (!updateHistory) {
5532 SetLayoutHistoryState(nullptr);
5533 }
5534
5535 return NS_OK;
5536}
5537
5538//*****************************************************************************
5539// nsDocShell::nsIWebProgressListener
5540//*****************************************************************************
5541
5542NS_IMETHODIMPnsresult
5543nsDocShell::OnProgressChange(nsIWebProgress* aProgress, nsIRequest* aRequest,
5544 int32_t aCurSelfProgress, int32_t aMaxSelfProgress,
5545 int32_t aCurTotalProgress,
5546 int32_t aMaxTotalProgress) {
5547 // Listeners in the parent process only care about aCurTotalProgress and
5548 // aMaxTotalProgress, which is internally managed by nsDocLoader. Because of
5549 // this, we don't send progress notifications except when they are recorded by
5550 // the toplevel context, and only report them on the toplevel context in the
5551 // parent process.
5552 //
5553 // FIXME: We should track progress for out-of-process iframes and manage total
5554 // progress in the parent process for more accurate notifications.
5555 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", 5557); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "mBrowsingContext->IsTop()" ") (" "notification excluded in AddProgressListener(...) for non-toplevel BCs"
")"); do { MOZ_CrashSequence(__null, 5557); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
5556 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", 5557); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "mBrowsingContext->IsTop()" ") (" "notification excluded in AddProgressListener(...) for non-toplevel BCs"
")"); do { MOZ_CrashSequence(__null, 5557); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
5557 "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", 5557); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "mBrowsingContext->IsTop()" ") (" "notification excluded in AddProgressListener(...) for non-toplevel BCs"
")"); do { MOZ_CrashSequence(__null, 5557); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5558
5559 if (nsCOMPtr<nsIWebProgressListener> listener = BCWebProgressListener()) {
5560 listener->OnProgressChange(aProgress, aRequest, aCurSelfProgress,
5561 aMaxSelfProgress, aCurTotalProgress,
5562 aMaxTotalProgress);
5563 }
5564
5565 return NS_OK;
5566}
5567
5568NS_IMETHODIMPnsresult
5569nsDocShell::OnStateChange(nsIWebProgress* aProgress, nsIRequest* aRequest,
5570 uint32_t aStateFlags, nsresult aStatus) {
5571 // If we're receiving a notification on ourselves which has at least one of
5572 // the state change flags in kStateChangeFlagFilter, also notify WebProgress
5573 // on BrowsingContextWebProgress, potentially over IPC.
5574 //
5575 // NOTE: We don't notify for bubbled notifications (aProgress != this), as
5576 // BrowsingContextWebProgress independently handles event bubbling in the
5577 // parent process.
5578 //
5579 // NOTE: We don't filter notifications when registering our listener, as
5580 // `STATE_IS_REDIRECTED_DOCUMENT` cannot be filtered for at registration time.
5581 static constexpr uint32_t kStateChangeFlagFilter =
5582 STATE_IS_NETWORK | STATE_IS_DOCUMENT | STATE_IS_WINDOW |
5583 STATE_IS_REDIRECTED_DOCUMENT;
5584 if (aProgress == this && (aStateFlags & kStateChangeFlagFilter) != 0) {
5585 if (nsCOMPtr<nsIWebProgressListener> listener = BCWebProgressListener()) {
5586 listener->OnStateChange(aProgress, aRequest, aStateFlags, aStatus);
5587 }
5588 }
5589
5590 if ((~aStateFlags & (STATE_START | STATE_IS_NETWORK)) == 0) {
5591 // Save timing statistics.
5592 nsCOMPtr<nsIChannel> channel(do_QueryInterface(aRequest));
5593 nsCOMPtr<nsIURI> uri;
5594 channel->GetURI(getter_AddRefs(uri));
5595 nsAutoCString aURI;
5596 uri->GetAsciiSpec(aURI);
5597
5598 if (this == aProgress) {
5599 (void)MaybeInitTiming();
5600 mTiming->NotifyFetchStart(uri,
5601 ConvertLoadTypeToNavigationType(mLoadType));
5602 // If we are starting a DocumentChannel, we need to pass the timing
5603 // statistics so that should a process switch occur, the starting type can
5604 // be passed to the new DocShell running in the other content process.
5605 if (RefPtr<DocumentChannel> docChannel = do_QueryObject(aRequest)) {
5606 docChannel->SetNavigationTiming(mTiming);
5607 }
5608 }
5609
5610 // Page has begun to load
5611 mBusyFlags = (BusyFlags)(BUSY_FLAGS_BUSY | BUSY_FLAGS_BEFORE_PAGE_LOAD);
5612
5613 if ((aStateFlags & STATE_RESTORING) == 0) {
5614 if (SessionStorePlatformCollection()) {
5615 if (IsForceReloadType(mLoadType)) {
5616 if (WindowContext* windowContext =
5617 mBrowsingContext->GetCurrentWindowContext()) {
5618 SessionStoreChild::From(windowContext->GetWindowGlobalChild())
5619 ->ResetSessionStore(mBrowsingContext,
5620 mBrowsingContext->GetSessionStoreEpoch());
5621 }
5622 }
5623 }
5624 }
5625 } else if ((~aStateFlags & (STATE_TRANSFERRING | STATE_IS_DOCUMENT)) == 0) {
5626 // Page is loading
5627 mBusyFlags = (BusyFlags)(BUSY_FLAGS_BUSY | BUSY_FLAGS_PAGE_LOADING);
5628 } else if ((aStateFlags & STATE_STOP) && (aStateFlags & STATE_IS_NETWORK)) {
5629 // Page has finished loading
5630 mBusyFlags = BUSY_FLAGS_NONE;
5631 }
5632
5633 if ((~aStateFlags & (STATE_IS_DOCUMENT | STATE_STOP)) == 0) {
5634 nsCOMPtr<nsIWebProgress> webProgress =
5635 do_QueryInterface(GetAsSupports(this));
5636 // Is the document stop notification for this document?
5637 if (aProgress == webProgress.get()) {
5638 nsCOMPtr<nsIChannel> channel(do_QueryInterface(aRequest));
5639 EndPageLoad(aProgress, channel, aStatus);
5640 }
5641 }
5642 // note that redirect state changes will go through here as well, but it
5643 // is better to handle those in OnRedirectStateChange where more
5644 // information is available.
5645 return NS_OK;
5646}
5647
5648NS_IMETHODIMPnsresult
5649nsDocShell::OnLocationChange(nsIWebProgress* aProgress, nsIRequest* aRequest,
5650 nsIURI* aURI, uint32_t aFlags) {
5651 // If we're receiving a notification on ourselves, also notify WebProgress on
5652 // BrowsingContextWebProgress, potentially over IPC.
5653 //
5654 // NOTE: We don't notify for bubbled notifications (aProgress != this), as
5655 // BrowsingContextWebProgress independently handles event bubbling in the
5656 // parent process.
5657 //
5658 // NOTE: Tests depend on this happening before UpdateSecurityState.
5659 if (aProgress == this) {
5660 if (nsCOMPtr<nsIWebProgressListener> listener = BCWebProgressListener()) {
5661 listener->OnLocationChange(aProgress, aRequest, aURI, aFlags);
5662 }
5663 }
5664
5665 // Since we've now changed Documents, notify the BrowsingContext that we've
5666 // changed. Ideally we'd just let the BrowsingContext do this when it
5667 // changes the current window global, but that happens before this and we
5668 // have a lot of tests that depend on the specific ordering of messages.
5669 bool isTopLevel = false;
5670 if (XRE_IsParentProcess() &&
5671 !(aFlags & nsIWebProgressListener::LOCATION_CHANGE_SAME_DOCUMENT) &&
5672 NS_SUCCEEDED(aProgress->GetIsTopLevel(&isTopLevel))((bool)(__builtin_expect(!!(!NS_FAILED_impl(aProgress->GetIsTopLevel
(&isTopLevel))), 1)))
&& isTopLevel) {
5673 GetBrowsingContext()->Canonical()->UpdateSecurityState();
5674 }
5675 return NS_OK;
5676}
5677
5678void nsDocShell::OnRedirectStateChange(nsIChannel* aOldChannel,
5679 nsIChannel* aNewChannel,
5680 uint32_t aRedirectFlags,
5681 uint32_t aStateFlags) {
5682 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"
, 5683); MOZ_PretendNoReturn(); } } while (0)
5683 "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"
, 5683); MOZ_PretendNoReturn(); } } while (0)
;
5684
5685 if (!(aStateFlags & STATE_IS_DOCUMENT)) {
5686 return; // not a toplevel document
5687 }
5688
5689 nsCOMPtr<nsIURI> oldURI, newURI;
5690 aOldChannel->GetURI(getter_AddRefs(oldURI));
5691 aNewChannel->GetURI(getter_AddRefs(newURI));
5692 if (!oldURI || !newURI) {
5693 return;
5694 }
5695
5696 // DocumentChannel adds redirect chain to global history in the parent
5697 // process. The redirect chain can't be queried from the content process, so
5698 // there's no need to update global history here.
5699 RefPtr<DocumentChannel> docChannel = do_QueryObject(aOldChannel);
5700 if (!docChannel) {
5701 // Below a URI visit is saved (see AddURIVisit method doc).
5702 // The visit chain looks something like:
5703 // ...
5704 // Site N - 1
5705 // => Site N
5706 // (redirect to =>) Site N + 1 (we are here!)
5707
5708 // Get N - 1 and transition type
5709 nsCOMPtr<nsIURI> previousURI;
5710 uint32_t previousFlags = 0;
5711 ExtractLastVisit(aOldChannel, getter_AddRefs(previousURI), &previousFlags);
5712
5713 if (aRedirectFlags & nsIChannelEventSink::REDIRECT_INTERNAL ||
5714 net::ChannelIsPost(aOldChannel)) {
5715 // 1. Internal redirects are ignored because they are specific to the
5716 // channel implementation.
5717 // 2. POSTs are not saved by global history.
5718 //
5719 // Regardless, we need to propagate the previous visit to the new
5720 // channel.
5721 SaveLastVisit(aNewChannel, previousURI, previousFlags);
5722 } else {
5723 // Get the HTTP response code, if available.
5724 uint32_t responseStatus = 0;
5725 nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(aOldChannel);
5726 if (httpChannel) {
5727 (void)httpChannel->GetResponseStatus(&responseStatus);
5728 }
5729
5730 // Add visit N -1 => N
5731 AddURIVisit(oldURI, previousURI, previousFlags, responseStatus);
5732
5733 // Since N + 1 could be the final destination, we will not save N => N + 1
5734 // here. OnNewURI will do that, so we will cache it.
5735 SaveLastVisit(aNewChannel, oldURI, aRedirectFlags);
5736 }
5737 }
5738
5739 if (!(aRedirectFlags & nsIChannelEventSink::REDIRECT_INTERNAL) &&
5740 mLoadType & (LOAD_CMD_RELOAD | LOAD_CMD_HISTORY)) {
5741 mLoadType = LOAD_NORMAL_REPLACE;
5742 }
5743}
5744
5745NS_IMETHODIMPnsresult
5746nsDocShell::OnStatusChange(nsIWebProgress* aWebProgress, nsIRequest* aRequest,
5747 nsresult aStatus, const char16_t* aMessage) {
5748 // If we're receiving a notification on ourselves, also notify WebProgress on
5749 // BrowsingContextWebProgress, potentially over IPC.
5750 //
5751 // NOTE: We don't notify for bubbled notifications (aWebProgress != this), as
5752 // BrowsingContextWebProgress independently handles event bubbling in the
5753 // parent process.
5754 if (aWebProgress == this) {
5755 if (nsCOMPtr<nsIWebProgressListener> listener = BCWebProgressListener()) {
5756 listener->OnStatusChange(aWebProgress, aRequest, aStatus, aMessage);
5757 }
5758 }
5759
5760 return NS_OK;
5761}
5762
5763NS_IMETHODIMPnsresult
5764nsDocShell::OnSecurityChange(nsIWebProgress* aWebProgress, nsIRequest* aRequest,
5765 uint32_t aState) {
5766 // If we're receiving a notification on ourselves, also notify WebProgress on
5767 // BrowsingContextWebProgress, potentially over IPC.
5768 //
5769 // NOTE: We don't notify for bubbled notifications (aWebProgress != this), as
5770 // BrowsingContextWebProgress independently handles event bubbling in the
5771 // parent process.
5772 if (aWebProgress == this) {
5773 if (nsCOMPtr<nsIWebProgressListener> listener = BCWebProgressListener()) {
5774 listener->OnSecurityChange(aWebProgress, aRequest, aState);
5775 }
5776 }
5777
5778 return NS_OK;
5779}
5780
5781NS_IMETHODIMPnsresult
5782nsDocShell::OnContentBlockingEvent(nsIWebProgress* aWebProgress,
5783 nsIRequest* aRequest, uint32_t aEvent) {
5784 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"
, 5784); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "notification excluded in AddProgressListener(...)"
")"); do { MOZ_CrashSequence(__null, 5784); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5785 return NS_OK;
5786}
5787
5788already_AddRefed<nsIWebProgressListener> nsDocShell::BCWebProgressListener() {
5789 // If this BrowsingContext has been replaced, we should discard any
5790 // notifications which would otherwise be delivered in-process.
5791 if (XRE_IsParentProcess() && mBrowsingContext->Canonical()->IsReplaced()) {
5792 return nullptr;
5793 }
5794
5795 // Create a nsBrowserStatusFilter to perform some throttling of
5796 // OnProgressChange and OnStatusChange notifications which are delivered to
5797 // our BCWebProgress listener. This reduces the amount of IPC traffic.
5798 if (!mBCWebProgressStatusFilter && !mIsBeingDestroyed) {
5799 nsCOMPtr<nsIWebProgressListener> innerListener;
5800 if (XRE_IsParentProcess()) {
5801 innerListener = mBrowsingContext->Canonical()->GetWebProgress();
5802 } else {
5803 innerListener = do_QueryReferent(mBrowserChild);
5804 }
5805 if (innerListener) {
5806 // NOTE: We need to disable filtering of StateChange events here, as
5807 // listeners on BrowsingContextWebProgress may depend on state change
5808 // notifications are otherwise filtered.
5809 // NOTE: Unlike other nsIWebProgress types, nsBrowserStatusFilter holds a
5810 // strong cycle-collected reference to the inner listener.
5811 mBCWebProgressStatusFilter = MakeRefPtr<nsBrowserStatusFilter>(
5812 /* aDisableStateChangeFilters */ true);
5813 mBCWebProgressStatusFilter->AddProgressListener(
5814 innerListener, nsIWebProgress::NOTIFY_ALL);
5815 }
5816 }
5817
5818 return do_AddRef(mBCWebProgressStatusFilter);
5819}
5820
5821already_AddRefed<nsIURIFixupInfo> nsDocShell::KeywordToURI(
5822 const nsACString& aKeyword, bool aIsPrivateContext) {
5823 nsCOMPtr<nsIURIFixupInfo> info;
5824 if (!XRE_IsContentProcess()) {
5825 nsCOMPtr<nsIURIFixup> uriFixup = components::URIFixup::Service();
5826 if (uriFixup) {
5827 uriFixup->KeywordToURI(aKeyword, aIsPrivateContext, getter_AddRefs(info));
5828 }
5829 }
5830 return info.forget();
5831}
5832
5833/* static */
5834already_AddRefed<nsIURI> nsDocShell::MaybeFixBadCertDomainErrorURI(
5835 nsIChannel* aChannel, nsIURI* aUrl) {
5836 if (!aChannel) {
5837 return nullptr;
5838 }
5839
5840 nsresult rv = NS_OK;
5841 nsAutoCString host;
5842 rv = aUrl->GetAsciiHost(host);
5843 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"
, 5843)
) {
5844 return nullptr;
5845 }
5846
5847 // Return if fixup enable pref is turned off.
5848 if (!mozilla::StaticPrefs::security_bad_cert_domain_error_url_fix_enabled()) {
5849 return nullptr;
5850 }
5851
5852 // Return if scheme is not HTTPS.
5853 if (!aUrl->SchemeIs("https")) {
5854 return nullptr;
5855 }
5856
5857 nsCOMPtr<nsILoadInfo> info = aChannel->LoadInfo();
5858 if (!info) {
5859 return nullptr;
5860 }
5861
5862 // Skip doing the fixup if our channel was redirected, because we
5863 // shouldn't be guessing things about the post-redirect URI.
5864 if (!info->RedirectChain().IsEmpty()) {
5865 return nullptr;
5866 }
5867
5868 int32_t port = 0;
5869 rv = aUrl->GetPort(&port);
5870 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"
, 5870)
) {
5871 return nullptr;
5872 }
5873
5874 // Don't fix up hosts with ports.
5875 if (port != -1) {
5876 return nullptr;
5877 }
5878
5879 // Don't fix up localhost url.
5880 if (host == "localhost") {
5881 return nullptr;
5882 }
5883
5884 // Don't fix up hostnames with IP address.
5885 if (net_IsValidIPv4Addr(host) || net_IsValidIPv6Addr(host)) {
5886 return nullptr;
5887 }
5888
5889 nsAutoCString userPass;
5890 rv = aUrl->GetUserPass(userPass);
5891 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"
, 5891)
) {
5892 return nullptr;
5893 }
5894
5895 // Security - URLs with user / password info should NOT be modified.
5896 if (!userPass.IsEmpty()) {
5897 return nullptr;
5898 }
5899
5900 nsCOMPtr<nsITransportSecurityInfo> tsi;
5901 rv = aChannel->GetSecurityInfo(getter_AddRefs(tsi));
5902 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"
, 5902)
) {
5903 return nullptr;
5904 }
5905
5906 if (NS_WARN_IF(!tsi)NS_warn_if_impl(!tsi, "!tsi", "./../../../docshell/base/nsDocShell.cpp"
, 5906)
) {
5907 return nullptr;
5908 }
5909
5910 nsCOMPtr<nsIX509Cert> cert;
5911 rv = tsi->GetServerCert(getter_AddRefs(cert));
5912 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"
, 5912)
) {
5913 return nullptr;
5914 }
5915
5916 nsTArray<uint8_t> certBytes;
5917 rv = cert->GetRawDER(certBytes);
5918 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
5919 return nullptr;
5920 }
5921
5922 mozilla::pkix::Input serverCertInput;
5923 mozilla::pkix::Result result =
5924 serverCertInput.Init(certBytes.Elements(), certBytes.Length());
5925 if (result != mozilla::pkix::Success) {
5926 return nullptr;
5927 }
5928
5929 constexpr auto wwwPrefix = "www."_ns;
5930 nsAutoCString newHost;
5931 if (StringBeginsWith(host, wwwPrefix)) {
5932 // Try www.example.com -> example.com
5933 newHost.Assign(Substring(host, wwwPrefix.Length()));
5934 } else {
5935 // Try example.com -> www.example.com
5936 newHost.Assign(wwwPrefix);
5937 newHost.Append(host);
5938 }
5939
5940 mozilla::pkix::Input newHostInput;
5941 result = newHostInput.Init(
5942 BitwiseCast<const uint8_t*, const char*>(newHost.BeginReading()),
5943 newHost.Length());
5944 if (result != mozilla::pkix::Success) {
5945 return nullptr;
5946 }
5947
5948 // Because certificate verification returned Result::ERROR_BAD_CERT_DOMAIN /
5949 // SSL_ERROR_BAD_CERT_DOMAIN, a chain was built and we know whether or not
5950 // the root was a built-in.
5951 bool rootIsBuiltIn;
5952 if (NS_FAILED(tsi->GetIsBuiltCertChainRootBuiltInRoot(&rootIsBuiltIn))((bool)(__builtin_expect(!!(NS_FAILED_impl(tsi->GetIsBuiltCertChainRootBuiltInRoot
(&rootIsBuiltIn))), 0)))
) {
5953 return nullptr;
5954 }
5955 mozilla::psm::SkipInvalidSANsForNonBuiltInRootsPolicy nameMatchingPolicy(
5956 rootIsBuiltIn);
5957
5958 // Check if the certificate is valid for the new hostname.
5959 result = mozilla::pkix::CheckCertHostname(serverCertInput, newHostInput,
5960 nameMatchingPolicy);
5961 if (result != mozilla::pkix::Success) {
5962 return nullptr;
5963 }
5964
5965 nsCOMPtr<nsIURI> newURI;
5966 (void)NS_MutateURI(aUrl).SetHost(newHost).Finalize(getter_AddRefs(newURI));
5967
5968 return newURI.forget();
5969}
5970
5971/* static */
5972already_AddRefed<nsIURI> nsDocShell::AttemptURIFixup(
5973 nsIChannel* aChannel, nsresult aStatus,
5974 const mozilla::Maybe<nsCString>& aOriginalURIString, uint32_t aLoadType,
5975 bool aIsTopFrame, bool aAllowKeywordFixup, bool aUsePrivateBrowsing,
5976 bool aNotifyKeywordSearchLoading, nsIInputStream** aNewPostData,
5977 nsILoadInfo::SchemelessInputType* outSchemelessInput) {
5978 if (aStatus != NS_ERROR_UNKNOWN_HOST && aStatus != NS_ERROR_NET_RESET &&
5979 aStatus != NS_ERROR_CONNECTION_REFUSED &&
5980 aStatus !=
5981 mozilla::psm::GetXPCOMFromNSSError(SSL_ERROR_BAD_CERT_DOMAIN)) {
5982 return nullptr;
5983 }
5984
5985 if (!(aLoadType == LOAD_NORMAL && aIsTopFrame) && !aAllowKeywordFixup) {
5986 return nullptr;
5987 }
5988
5989 nsCOMPtr<nsIURI> url;
5990 nsresult rv = aChannel->GetURI(getter_AddRefs(url));
5991 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
5992 return nullptr;
5993 }
5994
5995 //
5996 // Try and make an alternative URI from the old one
5997 //
5998 nsCOMPtr<nsIURI> newURI;
5999 nsCOMPtr<nsIInputStream> newPostData;
6000
6001 nsAutoCString oldSpec;
6002 url->GetSpec(oldSpec);
6003
6004 //
6005 // First try keyword fixup
6006 //
6007 nsAutoString keywordProviderId, keywordAsSent;
6008 if (aStatus == NS_ERROR_UNKNOWN_HOST && aAllowKeywordFixup) {
6009 // we should only perform a keyword search under the following
6010 // conditions:
6011 // (0) Pref keyword.enabled is true
6012 // (1) the url scheme is http (or https)
6013 // (2) the url does not have a protocol scheme
6014 // If we don't enforce such a policy, then we end up doing
6015 // keyword searchs on urls we don't intend like imap, file,
6016 // mailbox, etc. This could lead to a security problem where we
6017 // send data to the keyword server that we shouldn't be.
6018 // Someone needs to clean up keywords in general so we can
6019 // determine on a per url basis if we want keywords
6020 // enabled...this is just a bandaid...
6021 if (Preferences::GetBool("keyword.enabled", false) &&
6022 net::SchemeIsHttpOrHttps(url)) {
6023 bool attemptFixup = false;
6024 nsAutoCString host;
6025 (void)url->GetHost(host);
6026 if (host.FindChar('.') == kNotFound) {
6027 attemptFixup = true;
6028 } else {
6029 // For domains with dots, we check the public suffix validity.
6030 nsCOMPtr<nsIEffectiveTLDService> tldService =
6031 do_GetService(NS_EFFECTIVETLDSERVICE_CONTRACTID"@mozilla.org/network/effective-tld-service;1");
6032 if (tldService) {
6033 nsAutoCString suffix;
6034 attemptFixup =
6035 NS_SUCCEEDED(tldService->GetKnownPublicSuffix(url, suffix))((bool)(__builtin_expect(!!(!NS_FAILED_impl(tldService->GetKnownPublicSuffix
(url, suffix))), 1)))
&&
6036 suffix.IsEmpty();
6037 }
6038 }
6039 if (attemptFixup) {
6040 nsCOMPtr<nsIURIFixupInfo> info;
6041 // only send non-qualified hosts to the keyword server
6042 if (aOriginalURIString && !aOriginalURIString->IsEmpty()) {
6043 info = KeywordToURI(*aOriginalURIString, aUsePrivateBrowsing);
6044 } else {
6045 //
6046 // If this string was passed through nsStandardURL by
6047 // chance, then it may have been converted from UTF-8 to
6048 // Punycode, which would result in a completely bogus keyword
6049 // query. Here we try to recover the original Unicode
6050 // value, but this is not 100% correct since the value may
6051 // have been normalized per the IDN normalization rules.
6052 //
6053 // Since we don't have access to the exact original string
6054 // that was entered by the user, this will just have to do.
6055 nsAutoCString utf8Host;
6056 mozilla_net_recover_keyword_from_punycode(&host, &utf8Host);
6057 info = KeywordToURI(utf8Host, aUsePrivateBrowsing);
6058 }
6059 if (info) {
6060 info->GetPreferredURI(getter_AddRefs(newURI));
6061 info->GetSchemelessInput(outSchemelessInput);
6062 if (newURI) {
6063 info->GetKeywordAsSent(keywordAsSent);
6064 info->GetKeywordProviderId(keywordProviderId);
6065 info->GetPostData(getter_AddRefs(newPostData));
6066 }
6067 }
6068 }
6069 }
6070 }
6071
6072 //
6073 // Now try change the address, e.g. turn http://foo into
6074 // http://www.foo.com, and if that doesn't work try https with
6075 // https://foo and https://www.foo.com.
6076 //
6077 if (aStatus == NS_ERROR_UNKNOWN_HOST || aStatus == NS_ERROR_NET_RESET) {
6078 // Skip fixup for anything except a normal document load
6079 // operation on the topframe.
6080 bool doCreateAlternate = aLoadType == LOAD_NORMAL && aIsTopFrame;
6081
6082 if (doCreateAlternate) {
6083 nsCOMPtr<nsILoadInfo> loadInfo = aChannel->LoadInfo();
6084 nsIPrincipal* principal = loadInfo->TriggeringPrincipal();
6085 // Only do this if our channel was loaded directly by the user from the
6086 // URL bar or similar (system principal) and not redirected, because we
6087 // shouldn't be guessing things about links from other sites, or a
6088 // post-redirect URI.
6089 doCreateAlternate = principal && principal->IsSystemPrincipal() &&
6090 loadInfo->RedirectChain().IsEmpty();
6091 }
6092 // Test if keyword lookup produced a new URI or not
6093 if (doCreateAlternate && newURI) {
6094 bool sameURI = false;
6095 url->Equals(newURI, &sameURI);
6096 if (!sameURI) {
6097 // Keyword lookup made a new URI so no need to try
6098 // an alternate one.
6099 doCreateAlternate = false;
6100 }
6101 }
6102 if (doCreateAlternate) {
6103 newURI = nullptr;
6104 newPostData = nullptr;
6105 keywordProviderId.Truncate();
6106 keywordAsSent.Truncate();
6107 nsCOMPtr<nsIURIFixup> uriFixup = components::URIFixup::Service();
6108 if (uriFixup) {
6109 nsCOMPtr<nsIURIFixupInfo> fixupInfo;
6110 uriFixup->GetFixupURIInfo(oldSpec, nsIURIFixup::FIXUP_FLAG_NONE,
6111 getter_AddRefs(fixupInfo));
6112 if (fixupInfo) {
6113 fixupInfo->GetPreferredURI(getter_AddRefs(newURI));
6114 }
6115 }
6116 }
6117 } else if (aStatus == NS_ERROR_CONNECTION_REFUSED &&
6118 Preferences::GetBool("browser.fixup.fallback-to-https", false)) {
6119 // Try HTTPS, since http didn't work
6120 if (url->SchemeIs("http")) {
6121 int32_t port = 0;
6122 url->GetPort(&port);
6123
6124 // Fall back to HTTPS only if port is default
6125 if (port == -1) {
6126 newURI = nullptr;
6127 newPostData = nullptr;
6128 (void)NS_MutateURI(url)
6129 .SetScheme("https"_ns)
6130 .Finalize(getter_AddRefs(newURI));
6131 }
6132 }
6133 }
6134
6135 // If we have a SSL_ERROR_BAD_CERT_DOMAIN error, try adding or removing
6136 // "www." to/from the beginning of the domain name to see if we can avoid
6137 // showing the cert error page. For example, https://example.com ->
6138 // https://www.example.com or https://www.example.com -> https://example.com.
6139 if (aStatus ==
6140 mozilla::psm::GetXPCOMFromNSSError(SSL_ERROR_BAD_CERT_DOMAIN)) {
6141 newPostData = nullptr;
6142 newURI = MaybeFixBadCertDomainErrorURI(aChannel, url);
6143 }
6144
6145 // Did we make a new URI that is different to the old one? If so
6146 // load it.
6147 //
6148 if (newURI) {
6149 // Make sure the new URI is different from the old one,
6150 // otherwise there's little point trying to load it again.
6151 bool sameURI = false;
6152 url->Equals(newURI, &sameURI);
6153 if (!sameURI) {
6154 if (aNewPostData) {
6155 newPostData.forget(aNewPostData);
6156 }
6157 if (aNotifyKeywordSearchLoading) {
6158 // This notification is meant for Firefox Health Report so it
6159 // can increment counts from the search engine
6160 MaybeNotifyKeywordSearchLoading(keywordProviderId, keywordAsSent);
6161 }
6162 return newURI.forget();
6163 }
6164 }
6165
6166 return nullptr;
6167}
6168
6169nsresult nsDocShell::FilterStatusForErrorPage(
6170 nsresult aStatus, nsIChannel* aChannel, uint32_t aLoadType,
6171 bool aIsTopFrame, bool aUseErrorPages,
6172 bool* aSkippedUnknownProtocolNavigation) {
6173 // Errors to be shown only on top-level frames
6174 if ((aStatus == NS_ERROR_UNKNOWN_HOST ||
6175 aStatus == NS_ERROR_CONNECTION_REFUSED ||
6176 aStatus == NS_ERROR_UNKNOWN_PROXY_HOST ||
6177 aStatus == NS_ERROR_PROXY_CONNECTION_REFUSED ||
6178 aStatus == NS_ERROR_PROXY_FORBIDDEN ||
6179 aStatus == NS_ERROR_PROXY_NOT_IMPLEMENTED ||
6180 aStatus == NS_ERROR_PROXY_AUTHENTICATION_FAILED ||
6181 aStatus == NS_ERROR_PROXY_TOO_MANY_REQUESTS ||
6182 aStatus == NS_ERROR_MALFORMED_URI ||
6183 aStatus == NS_ERROR_HARMFULADDON_URI ||
6184 aStatus == NS_ERROR_BLOCKED_BY_POLICY ||
6185 aStatus == NS_ERROR_DOM_COOP_FAILED ||
6186 aStatus == NS_ERROR_DOM_COEP_FAILED ||
6187 aStatus == NS_ERROR_DOM_INVALID_HEADER_VALUE) &&
6188 (aIsTopFrame || aUseErrorPages)) {
6189 return aStatus;
6190 }
6191
6192 if (aStatus == NS_ERROR_NET_TIMEOUT ||
6193 aStatus == NS_ERROR_NET_TIMEOUT_EXTERNAL ||
6194 aStatus == NS_ERROR_OS_LOCAL_NETWORK_ACCESS_DENIED ||
6195 aStatus == NS_ERROR_NET_EMPTY_RESPONSE ||
6196 aStatus == NS_ERROR_NET_ERROR_RESPONSE ||
6197 aStatus == NS_ERROR_PROXY_GATEWAY_TIMEOUT ||
6198 aStatus == NS_ERROR_REDIRECT_LOOP ||
6199 aStatus == NS_ERROR_UNKNOWN_SOCKET_TYPE ||
6200 aStatus == NS_ERROR_NET_INTERRUPT || aStatus == NS_ERROR_NET_RESET ||
6201 aStatus == NS_ERROR_NET_UNCLEAN_SHUTDOWN ||
6202 aStatus == NS_ERROR_PROXY_BAD_GATEWAY || aStatus == NS_ERROR_OFFLINE ||
6203 aStatus == NS_ERROR_MALWARE_URI || aStatus == NS_ERROR_PHISHING_URI ||
6204 aStatus == NS_ERROR_UNWANTED_URI || aStatus == NS_ERROR_HARMFUL_URI ||
6205 aStatus == NS_ERROR_UNSAFE_CONTENT_TYPE ||
6206 aStatus == NS_ERROR_INTERCEPTION_FAILED ||
6207 aStatus == NS_ERROR_NET_INADEQUATE_SECURITY ||
6208 aStatus == NS_ERROR_NET_HTTP2_SENT_GOAWAY ||
6209 aStatus == NS_ERROR_NET_HTTP3_PROTOCOL_ERROR ||
6210 aStatus == NS_ERROR_BASIC_HTTP_AUTH_DISABLED ||
6211 aStatus == NS_ERROR_DOM_BAD_URI || aStatus == NS_ERROR_FILE_NOT_FOUND ||
6212 aStatus == NS_ERROR_FILE_ACCESS_DENIED ||
6213 aStatus == NS_ERROR_CORRUPTED_CONTENT ||
6214 aStatus == NS_ERROR_INVALID_CONTENT_ENCODING ||
6215 NS_ERROR_GET_MODULE(aStatus) == NS_ERROR_MODULE_SECURITY21) {
6216 // Errors to be shown for any frame
6217 return aStatus;
6218 }
6219
6220 if (aStatus == NS_ERROR_UNKNOWN_PROTOCOL) {
6221 // For unknown protocols we only display an error if the load is triggered
6222 // by the browser itself. Showing the error for page-triggered navigations
6223 // causes annoying behavior for users when a page tries to open an external
6224 // app which has not been installed, see bug 1528305. A missing WebExtension
6225 // protocol handlers will however always load the error page, as it is not
6226 // expected to be opened externally, see bug 1921426.
6227 nsCOMPtr<nsILoadInfo> info = aChannel->LoadInfo();
6228 if (!info->TriggeringPrincipal()->IsSystemPrincipal() &&
6229 !BasePrincipal::Cast(info->TriggeringPrincipal())->AddonPolicy()) {
6230 if (aSkippedUnknownProtocolNavigation) {
6231 *aSkippedUnknownProtocolNavigation = true;
6232 }
6233 return NS_OK;
6234 }
6235 return aStatus;
6236 }
6237
6238 if (aStatus == NS_ERROR_DOCUMENT_NOT_CACHED) {
6239 // Non-caching channels will simply return NS_ERROR_OFFLINE.
6240 // Caching channels would have to look at their flags to work
6241 // out which error to return. Or we can fix up the error here.
6242 if (!(aLoadType & LOAD_CMD_HISTORY)) {
6243 return NS_ERROR_OFFLINE;
6244 }
6245 return aStatus;
6246 }
6247
6248 return NS_OK;
6249}
6250
6251nsresult nsDocShell::EndPageLoad(nsIWebProgress* aProgress,
6252 nsIChannel* aChannel, nsresult aStatus) {
6253 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)
6254 ("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)
6255 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)
;
6256 if (!aChannel) {
6257 return NS_ERROR_NULL_POINTER;
6258 }
6259
6260 // Make sure to discard the initial client if we never created the initial
6261 // about:blank document. Do this before possibly returning from the method
6262 // due to an error.
6263 mInitialClientSource.reset();
6264
6265 nsCOMPtr<nsIConsoleReportCollector> reporter = do_QueryInterface(aChannel);
6266 if (reporter) {
6267 nsCOMPtr<nsILoadGroup> loadGroup;
6268 aChannel->GetLoadGroup(getter_AddRefs(loadGroup));
6269 if (loadGroup) {
6270 reporter->FlushConsoleReports(loadGroup);
6271 } else {
6272 reporter->FlushConsoleReports(GetDocument());
6273 }
6274 }
6275
6276 nsCOMPtr<nsIURI> url;
6277 nsresult rv = aChannel->GetURI(getter_AddRefs(url));
6278 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
6279 return rv;
6280 }
6281
6282 nsCOMPtr<nsITimedChannel> timingChannel = do_QueryInterface(aChannel);
6283 if (timingChannel) {
6284 TimeStamp channelCreationTime;
6285 rv = timingChannel->GetChannelCreation(&channelCreationTime);
6286 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && !channelCreationTime.IsNull()) {
6287 glean::performance_page::total_content_page_load.AccumulateRawDuration(
6288 TimeStamp::Now() - channelCreationTime);
6289 }
6290 }
6291
6292 // Timing is picked up by the window, we don't need it anymore
6293 mTiming = nullptr;
6294
6295 // clean up reload state for meta charset
6296 if (eCharsetReloadRequested == mCharsetReloadState) {
6297 mCharsetReloadState = eCharsetReloadStopOrigional;
6298 } else {
6299 mCharsetReloadState = eCharsetReloadInit;
6300 }
6301
6302 //
6303 // one of many safeguards that prevent death and destruction if
6304 // someone is so very very rude as to bring this window down
6305 // during this load handler.
6306 //
6307 nsCOMPtr<nsIDocShell> kungFuDeathGrip(this);
6308
6309 // Notify the DocumentViewer that the Document has finished loading. This
6310 // will cause any OnLoad(...) and PopState(...) handlers to fire.
6311 if (!mEODForCurrentDocument && mDocumentViewer) {
6312 mIsExecutingOnLoadHandler = true;
6313 nsCOMPtr<nsIDocumentViewer> viewer = mDocumentViewer;
6314 viewer->LoadComplete(aStatus);
6315 mIsExecutingOnLoadHandler = false;
6316
6317 mEODForCurrentDocument = true;
6318 }
6319 /* Check if the httpChannel has any cache-control related response headers,
6320 * like no-store, no-cache. If so, update SHEntry so that
6321 * when a user goes back/forward to this page, we appropriately do
6322 * form value restoration or load from server.
6323 */
6324 nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(aChannel));
6325 if (!httpChannel) {
6326 // HttpChannel could be hiding underneath a Multipart channel.
6327 GetHttpChannel(aChannel, getter_AddRefs(httpChannel));
6328 }
6329
6330 mActiveEntryIsLoadingFromSessionHistory = false;
6331
6332 // if there's a refresh header in the channel, this method
6333 // will set it up for us.
6334 if (mBrowsingContext->IsActive() || !mDisableMetaRefreshWhenInactive)
6335 RefreshURIFromQueue();
6336
6337 // Test whether this is the top frame or a subframe
6338 bool isTopFrame = mBrowsingContext->IsTop();
6339
6340 bool hadErrorStatus = false;
6341 // If status code indicates an error it means that DocumentChannel already
6342 // tried to fixup the uri and failed. Throw an error dialog box here.
6343 if (NS_FAILED(aStatus)((bool)(__builtin_expect(!!(NS_FAILED_impl(aStatus)), 0)))) {
6344 // If we got CONTENT_BLOCKED from EndPageLoad, then we need to fire
6345 // the error event to our embedder, since tests are relying on this.
6346 // The error event is usually fired by the caller of InternalLoad, but
6347 // this particular error can happen asynchronously.
6348 // Bug 1629201 is filed for having much clearer decision making around
6349 // which cases need error events.
6350 bool fireFrameErrorEvent = (aStatus == NS_ERROR_CONTENT_BLOCKED_SHOW_ALT ||
6351 aStatus == NS_ERROR_CONTENT_BLOCKED);
6352 UnblockEmbedderLoadEventForFailure(fireFrameErrorEvent);
6353
6354 bool skippedUnknownProtocolNavigation = false;
6355 aStatus = FilterStatusForErrorPage(aStatus, aChannel, mLoadType, isTopFrame,
6356 mBrowsingContext->GetUseErrorPages(),
6357 &skippedUnknownProtocolNavigation);
6358 hadErrorStatus = true;
6359 if (NS_FAILED(aStatus)((bool)(__builtin_expect(!!(NS_FAILED_impl(aStatus)), 0)))) {
6360 if (!mIsBeingDestroyed) {
6361 DisplayLoadError(aStatus, url, nullptr, aChannel);
6362 }
6363 } else if (skippedUnknownProtocolNavigation) {
6364 nsAutoCString sanitized;
6365 nsTArray<nsString> params;
6366 if (NS_SUCCEEDED(NS_GetSanitizedURIStringFromURI(url, sanitized))((bool)(__builtin_expect(!!(!NS_FAILED_impl(NS_GetSanitizedURIStringFromURI
(url, sanitized))), 1)))
) {
6367 params.AppendElement(NS_ConvertUTF8toUTF16(sanitized));
6368 } else {
6369 params.AppendElement(u"(unknown uri)"_ns);
6370 }
6371 nsContentUtils::ReportToConsole(
6372 nsIScriptError::warningFlag, "DOM"_ns, GetExtantDocument(),
6373 PropertiesFile::DOM_PROPERTIES, "UnknownProtocolNavigationPrevented",
6374 params);
6375 }
6376 }
6377
6378 if (hadErrorStatus) {
6379 // Don't send session store updates if the reason EndPageLoad was called is
6380 // because we are process switching. Sometimes the update takes too long and
6381 // incorrectly overrides session store data from the following load.
6382 return NS_OK;
6383 }
6384 if (SessionStorePlatformCollection()) {
6385 if (WindowContext* windowContext =
6386 mBrowsingContext->GetCurrentWindowContext()) {
6387 using Change = SessionStoreChangeListener::Change;
6388
6389 // We've finished loading the page and now we want to collect all the
6390 // session store state that the page is initialized with.
6391 SessionStoreChangeListener::CollectSessionStoreData(
6392 windowContext,
6393 EnumSet<Change>(Change::Input, Change::Scroll, Change::SessionHistory,
6394 Change::WireFrame));
6395 }
6396 }
6397
6398 return NS_OK;
6399}
6400
6401//*****************************************************************************
6402// nsDocShell: Content Viewer Management
6403//*****************************************************************************
6404
6405bool nsDocShell::VerifyDocumentViewer() {
6406 if (mDocumentViewer) {
6407 return true;
6408 }
6409 if (mIsBeingDestroyed) {
6410 return false;
6411 }
6412 if (!mInitialized) {
6413 // The viewer should be created during docshell initialization. If something
6414 // wants a viewer or document, it has to initialize the docshell first.
6415 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"
, 6416); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "The docshell should be initialized to get a viewer."
")"); do { MOZ_CrashSequence(__null, 6416); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6416 "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"
, 6416); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "The docshell should be initialized to get a viewer."
")"); do { MOZ_CrashSequence(__null, 6416); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6417 } else {
6418 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", 6418)
;
6419 }
6420 return false;
6421}
6422
6423nsresult nsDocShell::CreateInitialDocumentViewer(
6424 nsIOpenWindowInfo* aOpenWindowInfo,
6425 mozilla::dom::WindowGlobalChild* aWindowActor) {
6426 if (mIsBeingDestroyed) {
6427 return NS_ERROR_FAILURE;
6428 }
6429 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", 6429); AnnotateMozCrashReason
("MOZ_DIAGNOSTIC_ASSERT" "(" "!mDocumentViewer" ")"); do { MOZ_CrashSequence
(__null, 6429); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
6430 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"
, 6430); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aOpenWindowInfo"
") (" "Why don't we have openwindowinfo?" ")"); do { MOZ_CrashSequence
(__null, 6430); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
6431
6432 nsCOMPtr<nsIPrincipal> principal =
6433 aOpenWindowInfo->PrincipalToInheritForAboutBlank();
6434 nsCOMPtr<nsIPrincipal> partitionedPrincipal =
6435 aOpenWindowInfo->PartitionedPrincipalToInheritForAboutBlank();
6436
6437 // Previously, CreateDocumentViewerForActor would've used the actor's
6438 // principal.
6439 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"
, 6439); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aWindowActor->DocumentPrincipal() == principal"
")"); do { MOZ_CrashSequence(__null, 6439); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
6440 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", 6441); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aWindowActor->DocumentPrincipal() == partitionedPrincipal"
")"); do { MOZ_CrashSequence(__null, 6441); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
6441 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", 6441); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aWindowActor->DocumentPrincipal() == partitionedPrincipal"
")"); do { MOZ_CrashSequence(__null, 6441); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
6442
6443 nsCOMPtr<nsIPolicyContainer> policyContainer =
6444 aOpenWindowInfo->PolicyContainerToInheritForAboutBlank();
6445 nsCOMPtr<nsIURI> base = aOpenWindowInfo->BaseUriToInheritForAboutBlank();
6446 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(); })
6447 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(); })
6448 /* 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(); })
6449 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(); })
6450 /* 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(); })
6451 /* 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(); })
;
6452
6453 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", 6453); return
NS_ERROR_UNEXPECTED; } } while (false)
;
6454
6455 RefPtr<Document> doc(GetDocument());
6456 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", 6457); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "doc" ") (" "Should have doc if CreateAboutBlankDocumentViewer succeeded!"
")"); do { MOZ_CrashSequence(__null, 6457); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6457 "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", 6457); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "doc" ") (" "Should have doc if CreateAboutBlankDocumentViewer succeeded!"
")"); do { MOZ_CrashSequence(__null, 6457); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6458 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"
, 6458); AnnotateMozCrashReason("MOZ_ASSERT" "(" "doc->IsInitialDocument()"
") (" "Document should be initial document" ")"); do { MOZ_CrashSequence
(__null, 6458); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
6459
6460 // Documents created using CreateInitialDocumentViewer may be transient
6461 // placeholders created by framescripts before content has a
6462 // chance to load. In some cases, window.open(..., "noopener")
6463 // will create such a document and then synchronously tear it
6464 // down, firing a "pagehide" event. Doing so violates our
6465 // assertions about DocGroups. It's easier to silence the
6466 // assertion here than to avoid creating the extra document.
6467 doc->IgnoreDocGroupMismatches();
6468
6469 return NS_OK;
6470}
6471
6472// Location.ancestorOrigins for about:blank, need special case handling.
6473// Particularly in the case for initial about:blank, which does not go through
6474// normal code that happen with navigations.
6475static void CreateAboutBlankAncestorOriginsForNonTopLevel(Document* aDoc) {
6476 BrowsingContext* bc = aDoc->GetBrowsingContext();
6477 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", 6477); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "bc && !bc->IsDiscarded() && bc->GetEmbedderElement()"
")"); do { MOZ_CrashSequence(__null, 6477); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6478 // We're not even going to attempt to deal with location.ancestorOrigins stuff
6479 // in the parent process.
6480 if (!XRE_IsContentProcess()) {
6481 return;
6482 }
6483
6484 const auto* frame = bc->GetEmbedderElement();
6485 const auto referrerPolicy = frame->GetReferrerPolicyAsEnum();
6486 // Inform the parent process that it needs to create an internal ancestor
6487 // origins list for this browsing context `bc`
6488 (void)ContentChild::GetSingleton()->SendUpdateAncestorOriginsList(bc);
6489
6490 const bool masked = referrerPolicy == ReferrerPolicy::No_referrer;
6491 BrowsingContext* parent = bc->GetParent();
6492 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", 6493); AnnotateMozCrashReason
("MOZ_DIAGNOSTIC_ASSERT" "(" "parent && parent->IsInProcess() && parent->GetExtantDocument()"
")"); do { MOZ_CrashSequence(__null, 6493); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6493 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", 6493); AnnotateMozCrashReason
("MOZ_DIAGNOSTIC_ASSERT" "(" "parent && parent->IsInProcess() && parent->GetExtantDocument()"
")"); do { MOZ_CrashSequence(__null, 6493); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6494
6495 nsTArray<nsCOMPtr<nsIPrincipal>> ancestorPrincipals;
6496 constexpr auto getPrincipal =
6497 [](const BrowsingContext* ctx) -> nsIPrincipal* {
6498 if (!ctx) {
6499 return nullptr;
6500 }
6501 auto* doc = ctx->GetExtantDocument();
6502 return doc ? doc->GetPrincipal() : nullptr;
6503 };
6504 BrowsingContext* ancestorContextToCopyAncestorListFrom = parent;
6505
6506 // about:blank is different from normal docs.
6507 // We only care about in-process, same-origin ancestors.
6508 // Therefore run the algorithm all the way up to the last same-origin doc
6509 // add that origin to the list, and then append that origin's ancestor origins
6510 // list
6511 if (masked) {
6512 ancestorPrincipals.AppendElement(nullptr);
6513 // 16.1.1. If ancestorOrigin is same origin with parentDoc's origin, then
6514 // append a new opaque origin to output.
6515 auto* parentDocPrincipal = getPrincipal(parent);
6516 for (auto* ancestor = parent->GetParent(); ancestor;
6517 ancestor = ancestor->GetParent()) {
6518 auto* principal = getPrincipal(ancestor);
6519 if (principal && principal->Equals(parentDocPrincipal)) {
6520 // same principal, same process, adding nullptr for
6521 // parentContextToCopyAncestorListFrom
6522 ancestorContextToCopyAncestorListFrom = ancestor;
6523 ancestorPrincipals.AppendElement(nullptr);
6524 } else {
6525 // 16.1.2 Otherwise, append ancestorOrigin to output and set masked to
6526 // false.
6527 // Note: But in the case of about:blank, ancestorOrigin can
6528 // potentially live in another process. So we stop right before it, and
6529 // just copy `ancestorContextToCopyAncestorListFrom` list, since the
6530 // masking steps should finish here.
6531 break;
6532 }
6533 }
6534 } else {
6535 ancestorPrincipals.AppendElement(getPrincipal(parent));
6536 }
6537
6538 nsTArray<nsString> list = ProduceAncestorOriginsList(ancestorPrincipals);
6539 Document* ancestorDoc =
6540 ancestorContextToCopyAncestorListFrom->GetExtantDocument();
6541 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"
, 6541); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "ancestorDoc"
")"); do { MOZ_CrashSequence(__null, 6541); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6542 list.AppendElements(ancestorDoc->GetAncestorOriginsList());
6543 aDoc->SetAncestorOriginsList(std::move(list));
6544}
6545
6546nsresult nsDocShell::CreateAboutBlankDocumentViewer(
6547 nsIPrincipal* aPrincipal, nsIPrincipal* aPartitionedPrincipal,
6548 nsIPolicyContainer* aPolicyContainer, nsIURI* aBaseURI,
6549 bool aIsInitialDocument,
6550 const Maybe<nsILoadInfo::CrossOriginEmbedderPolicy>& aCOEP,
6551 bool aTryToSaveOldPresentation, bool aCheckPermitUnload,
6552 WindowGlobalChild* aActor) {
6553 RefPtr<Document> blankDoc;
6554 nsCOMPtr<nsIDocumentViewer> viewer;
6555 nsresult rv = NS_ERROR_FAILURE;
6556
6557 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
)
6558 MarkerStack::Capture())do { ; do { if (profiler_is_collecting_markers()) { ::profiler_add_marker_impl
("CreateAboutBlankDocumentViewer", ::geckoprofiler::category::
DOM, MarkerStack::Capture()); } } while (false); } while (false
)
;
6559
6560 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", 6560); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aActor->DocumentPrincipal() == aPrincipal"
")"); do { MOZ_CrashSequence(__null, 6560); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
6561
6562 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"
, 6562); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "mInitialized"
") (" "Must initialize before viewer creation" ")"); do { MOZ_CrashSequence
(__null, 6562); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
6563
6564 /* mCreatingDocument should never be true at this point. However, it's
6565 a theoretical possibility. We want to know about it and make it stop,
6566 and this sounds like a job for an assertion. */
6567 NS_ASSERTION(!mCreatingDocument,do { if (!(!mCreatingDocument)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "infinite(?) loop creating document averted", "!mCreatingDocument"
, "./../../../docshell/base/nsDocShell.cpp", 6568); MOZ_PretendNoReturn
(); } } while (0)
6568 "infinite(?) loop creating document averted")do { if (!(!mCreatingDocument)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "infinite(?) loop creating document averted", "!mCreatingDocument"
, "./../../../docshell/base/nsDocShell.cpp", 6568); MOZ_PretendNoReturn
(); } } while (0)
;
6569 if (mCreatingDocument) {
6570 return NS_ERROR_FAILURE;
6571 }
6572
6573 if (!mBrowsingContext->AncestorsAreCurrent() ||
6574 mBrowsingContext->IsInBFCache()) {
6575 mBrowsingContext->RemoveRootFromBFCacheSync();
6576 return NS_ERROR_NOT_AVAILABLE;
6577 }
6578
6579 // mDocumentViewer->PermitUnload may release |this| docshell.
6580 nsCOMPtr<nsIDocShell> kungFuDeathGrip(this);
6581
6582 // Ensure that UsesOriginAgentCluster has been initialized for this
6583 // BrowsingContextGroup/principal pair before creating the document.
6584 if (aPrincipal) {
6585 mBrowsingContext->Group()->EnsureUsesOriginAgentClusterInitialized(
6586 aPrincipal);
6587 }
6588
6589 AutoRestore<bool> creatingDocument(mCreatingDocument);
6590 mCreatingDocument = true;
6591
6592 if (aPrincipal && !aPrincipal->IsSystemPrincipal() &&
6593 mItemType != typeChrome) {
6594 if (GetIsTopLevelContentDocShell()) {
6595 // Bug 1948216 tracks having a FPD for top-level initial about:blank
6596 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", 6597); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aPrincipal->OriginAttributesRef().EqualsIgnoringFPD( mBrowsingContext->OriginAttributesRef())"
")"); do { MOZ_CrashSequence(__null, 6597); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6597 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", 6597); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aPrincipal->OriginAttributesRef().EqualsIgnoringFPD( mBrowsingContext->OriginAttributesRef())"
")"); do { MOZ_CrashSequence(__null, 6597); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6598 } else {
6599 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", 6600); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aPrincipal->OriginAttributesRef() == mBrowsingContext->OriginAttributesRef()"
")"); do { MOZ_CrashSequence(__null, 6600); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6600 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", 6600); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aPrincipal->OriginAttributesRef() == mBrowsingContext->OriginAttributesRef()"
")"); do { MOZ_CrashSequence(__null, 6600); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6601 }
6602 }
6603
6604 // Make sure timing is created. But first record whether we had it
6605 // already, so we don't clobber the timing for an in-progress load.
6606 bool hadTiming = mTiming;
6607 bool toBeReset = MaybeInitTiming();
6608 if (mDocumentViewer) {
6609 if (aCheckPermitUnload) {
6610 // We've got a content viewer already. Make sure the user
6611 // permits us to discard the current document and replace it
6612 // with about:blank. And also ensure we fire the unload events
6613 // in the current document.
6614
6615 // Unload gets fired first for
6616 // document loaded from the session history.
6617 mTiming->NotifyBeforeUnload();
6618
6619 bool okToUnload;
6620 rv = mDocumentViewer->PermitUnload(&okToUnload);
6621 if (mIsBeingDestroyed) {
6622 // unload handler destroyed this docshell.
6623 return NS_ERROR_NOT_AVAILABLE;
6624 }
6625 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && !okToUnload) {
6626 // The user chose not to unload the page, interrupt the load.
6627 MaybeResetInitTiming(toBeReset);
6628 return NS_ERROR_FAILURE;
6629 }
6630 if (mTiming) {
6631 mTiming->NotifyUnloadAccepted(mCurrentURI);
6632 }
6633 }
6634
6635 // Make sure to blow away our mLoadingURI just in case. No loads
6636 // from inside this pagehide.
6637 mLoadingURI = nullptr;
6638
6639 // Stop any in-progress loading, so that we don't accidentally trigger any
6640 // PageShow notifications from Embed() interrupting our loading below.
6641 Stop();
6642
6643 // Notify the current document that it is about to be unloaded!!
6644 //
6645 // It is important to fire the unload() notification *before* any state
6646 // is changed within the DocShell - otherwise, javascript will get the
6647 // wrong information :-(
6648 //
6649 (void)FirePageHideNotification();
6650 // pagehide notification might destroy this docshell.
6651 if (mIsBeingDestroyed) {
6652 return NS_ERROR_DOCSHELL_DYING;
6653 }
6654 }
6655
6656 // Now make sure we don't think we're in the middle of firing unload after
6657 // this point. This will make us fire unload when the about:blank document
6658 // unloads... but that's ok, more or less. Would be nice if it fired load
6659 // too, of course.
6660 mFiredUnloadEvent = false;
6661
6662 nsCOMPtr<nsIDocumentLoaderFactory> docFactory =
6663 nsContentUtils::FindInternalDocumentViewer("text/html"_ns);
6664
6665 if (docFactory) {
6666 nsCOMPtr<nsIPrincipal> principal, partitionedPrincipal;
6667 const uint32_t sandboxFlags =
6668 mBrowsingContext->GetHasLoadedNonInitialDocument()
6669 ? mBrowsingContext->GetSandboxFlags()
6670 : mBrowsingContext->GetInitialSandboxFlags();
6671 // If we're sandboxed, then create a new null principal. We skip
6672 // this if we're being created from WindowGlobalChild, since in
6673 // that case we already have a null principal if required.
6674 // We can't compare againt the BrowsingContext sandbox flag, since
6675 // the value was taken when the load initiated and may have since
6676 // changed.
6677 if ((sandboxFlags & SANDBOXED_ORIGIN) && !aActor) {
6678 if (aPrincipal) {
6679 principal = NullPrincipal::CreateWithInheritedAttributes(aPrincipal);
6680 } else {
6681 principal = NullPrincipal::Create(GetOriginAttributes());
6682 }
6683 partitionedPrincipal = principal;
6684 } else {
6685 principal = aPrincipal;
6686 partitionedPrincipal = aPartitionedPrincipal;
6687 }
6688
6689 // We cannot get the foreign partitioned principal for the initial
6690 // about:blank page. So, we change to check if we need to use the
6691 // partitioned principal for the service worker here.
6692 MaybeCreateInitialClientSource(
6693 StoragePrincipalHelper::ShouldUsePartitionPrincipalForServiceWorker(
6694 this)
6695 ? partitionedPrincipal
6696 : principal);
6697
6698 // generate (about:blank) document to load
6699 blankDoc = nsContentDLF::CreateBlankDocument(mLoadGroup, principal,
6700 partitionedPrincipal, this);
6701 if (blankDoc) {
6702 // Hack: manually set the policyContainer for the new document
6703 // Please create an actual copy of the policyContainer (do not share the
6704 // same reference) otherwise modifying the new container (such as
6705 // appending a new policy to CSP) within the new document will be
6706 // incorrectly propagated to the opening doc.
6707 if (aPolicyContainer) {
6708 RefPtr policyContainerToInherit = MakeRefPtr<PolicyContainer>();
6709 policyContainerToInherit->InitFromOther(
6710 PolicyContainer::Cast(aPolicyContainer));
6711 blankDoc->SetPolicyContainer(policyContainerToInherit);
6712 if (!PolicyContainer::GetCSP(policyContainerToInherit)) {
6713 RefPtr newCsp = MakeRefPtr<nsCSPContext>();
6714 policyContainerToInherit->SetCSP(newCsp);
6715 nsresult rv = newCsp->SetRequestContextWithDocument(blankDoc);
6716 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"
, 6716)
) {
6717 return rv;
6718 }
6719 }
6720 }
6721
6722 blankDoc->SetInitialStatus(
6723 aIsInitialDocument ? Document::InitialStatus::IsInitialUncommitted
6724 : Document::InitialStatus::NeverInitial);
6725
6726 blankDoc->SetEmbedderPolicy(aCOEP);
6727
6728 // Hack: set the base URI manually, since this document never
6729 // got Reset() with a channel.
6730 blankDoc->SetBaseURI(aBaseURI);
6731
6732 // Copy our sandbox flags to the document. These are immutable
6733 // after being set here.
6734 blankDoc->SetSandboxFlags(sandboxFlags);
6735
6736 // We inherit the classification flags from the parent document if the
6737 // principal matches.
6738 nsCOMPtr<nsIDocShellTreeItem> parentItem;
6739 GetInProcessSameTypeParent(getter_AddRefs(parentItem));
6740 if (parentItem) {
6741 RefPtr<Document> parentDocument = parentItem->GetDocument();
6742 if (parentDocument && principal &&
6743 principal->Equals(parentDocument->NodePrincipal())) {
6744 blankDoc->SetClassificationFlags(
6745 parentDocument->GetClassificationFlags());
6746 }
6747 }
6748
6749 // create a content viewer for us and the new document
6750 docFactory->CreateInstanceForDocument(
6751 NS_ISUPPORTS_CAST(nsIDocShell*, this)static_cast<nsISupports*>(static_cast<nsIDocShell*>
(this))
, blankDoc, "view",
6752 getter_AddRefs(viewer));
6753
6754 // hook 'em up
6755 if (viewer) {
6756 viewer->SetContainer(this);
6757 if (mLoadingEntry && mBrowsingContext->IsTop()) {
6758 mLoadingEntry->mInfo.SetTransient();
6759 }
6760 const nsCOMPtr<nsIURI> uri = mCurrentURI;
6761 rv = Embed(viewer, aActor, true, nullptr, uri);
6762 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"
, 6762); return rv; } } while (false)
;
6763
6764 SetCurrentURI(blankDoc->GetDocumentURI(), nullptr,
6765 /* aFireLocationChange */ true,
6766 /* aIsInitialAboutBlank */ aIsInitialDocument,
6767 /* aLocationFlags */ 0);
6768 rv = mIsBeingDestroyed ? NS_ERROR_NOT_AVAILABLE : NS_OK;
6769 }
6770
6771 if (Element* embedderElement = blankDoc->GetEmbedderElement()) {
6772 blankDoc->InitPermissionsPolicy(AsVariant(embedderElement));
6773 } else {
6774 blankDoc->InitPermissionsPolicy(AsVariant(Nothing{}));
6775 }
6776
6777 // Perform redacted location.ancestorOrigins algorithm for about:blank
6778 if (BrowsingContext* bc = GetBrowsingContext();
6779 bc && bc->GetEmbedderElement()) {
6780 CreateAboutBlankAncestorOriginsForNonTopLevel(blankDoc);
6781 }
6782 }
6783 }
6784
6785 // Clear out our mTiming like we would in EndPageLoad, if we didn't
6786 // have one before entering this function.
6787 if (!hadTiming) {
6788 mTiming = nullptr;
6789 mBlankTiming = true;
6790 }
6791
6792 return rv;
6793}
6794
6795NS_IMETHODIMPnsresult
6796nsDocShell::CreateAboutBlankDocumentViewer(
6797 nsIPrincipal* aPrincipal, nsIPrincipal* aPartitionedPrincipal,
6798 nsIPolicyContainer* aPolicyContainer) {
6799 return CreateAboutBlankDocumentViewer(aPrincipal, aPartitionedPrincipal,
6800 aPolicyContainer, nullptr,
6801 /* aIsInitialDocument */ false);
6802}
6803
6804/* static */
6805void nsDocShell::ReportBFCacheComboTelemetry(uint32_t aCombo) {
6806 // There are 11 possible reasons to make a request fails to use BFCache
6807 // (see BFCacheStatus in dom/base/Document.h), and we'd like to record
6808 // the common combinations for reasons which make requests fail to use
6809 // BFCache. These combinations are generated based on some local browsings,
6810 // we need to adjust them when necessary.
6811 enum BFCacheStatusCombo : uint32_t {
6812 BFCACHE_SUCCESS,
6813 NOT_ONLY_TOPLEVEL = mozilla::dom::BFCacheStatus::NOT_ONLY_TOPLEVEL_IN_BCG,
6814 // If both unload and beforeunload listeners are presented, it'll be
6815 // recorded as unload
6816 UNLOAD = mozilla::dom::BFCacheStatus::UNLOAD_LISTENER,
6817 UNLOAD_REQUEST = mozilla::dom::BFCacheStatus::UNLOAD_LISTENER |
6818 mozilla::dom::BFCacheStatus::REQUEST,
6819 REQUEST = mozilla::dom::BFCacheStatus::REQUEST,
6820 UNLOAD_REQUEST_PEER = mozilla::dom::BFCacheStatus::UNLOAD_LISTENER |
6821 mozilla::dom::BFCacheStatus::REQUEST |
6822 mozilla::dom::BFCacheStatus::ACTIVE_PEER_CONNECTION,
6823 UNLOAD_REQUEST_PEER_MSE =
6824 mozilla::dom::BFCacheStatus::UNLOAD_LISTENER |
6825 mozilla::dom::BFCacheStatus::REQUEST |
6826 mozilla::dom::BFCacheStatus::ACTIVE_PEER_CONNECTION |
6827 mozilla::dom::BFCacheStatus::CONTAINS_MSE_CONTENT,
6828 UNLOAD_REQUEST_MSE = mozilla::dom::BFCacheStatus::UNLOAD_LISTENER |
6829 mozilla::dom::BFCacheStatus::REQUEST |
6830 mozilla::dom::BFCacheStatus::CONTAINS_MSE_CONTENT,
6831 SUSPENDED_UNLOAD_REQUEST_PEER =
6832 mozilla::dom::BFCacheStatus::SUSPENDED |
6833 mozilla::dom::BFCacheStatus::UNLOAD_LISTENER |
6834 mozilla::dom::BFCacheStatus::REQUEST |
6835 mozilla::dom::BFCacheStatus::ACTIVE_PEER_CONNECTION,
6836 REMOTE_SUBFRAMES = mozilla::dom::BFCacheStatus::CONTAINS_REMOTE_SUBFRAMES,
6837 BEFOREUNLOAD = mozilla::dom::BFCacheStatus::BEFOREUNLOAD_LISTENER,
6838 };
6839
6840 // Beforeunload is recorded as a blocker only if it is the only one to block
6841 // bfcache.
6842 if (aCombo != mozilla::dom::BFCacheStatus::BEFOREUNLOAD_LISTENER) {
6843 aCombo &= ~mozilla::dom::BFCacheStatus::BEFOREUNLOAD_LISTENER;
6844 }
6845 switch (aCombo) {
6846 case BFCACHE_SUCCESS:
6847 glean::bfcache::combo.EnumGet(glean::bfcache::ComboLabel::eBfcacheSuccess)
6848 .Add();
6849 break;
6850 case NOT_ONLY_TOPLEVEL:
6851 if (StaticPrefs::docshell_shistory_bfcache_require_no_opener()) {
6852 glean::bfcache::combo.EnumGet(glean::bfcache::ComboLabel::eOther).Add();
6853 break;
6854 }
6855 glean::bfcache::combo.EnumGet(glean::bfcache::ComboLabel::eBfcacheSuccess)
6856 .Add();
6857 glean::bfcache::combo
6858 .EnumGet(glean::bfcache::ComboLabel::eSuccessNotToplevel)
6859 .Add();
6860 break;
6861 case UNLOAD:
6862 glean::bfcache::combo.EnumGet(glean::bfcache::ComboLabel::eUnload).Add();
6863 break;
6864 case BEFOREUNLOAD:
6865 glean::bfcache::combo.EnumGet(glean::bfcache::ComboLabel::eBeforeunload)
6866 .Add();
6867 break;
6868 case UNLOAD_REQUEST:
6869 glean::bfcache::combo.EnumGet(glean::bfcache::ComboLabel::eUnloadReq)
6870 .Add();
6871 break;
6872 case REQUEST:
6873 glean::bfcache::combo.EnumGet(glean::bfcache::ComboLabel::eReq).Add();
6874 break;
6875 case UNLOAD_REQUEST_PEER:
6876 glean::bfcache::combo.EnumGet(glean::bfcache::ComboLabel::eUnloadReqPeer)
6877 .Add();
6878 break;
6879 case UNLOAD_REQUEST_PEER_MSE:
6880 glean::bfcache::combo
6881 .EnumGet(glean::bfcache::ComboLabel::eUnloadReqPeerMse)
6882 .Add();
6883 break;
6884 case UNLOAD_REQUEST_MSE:
6885 glean::bfcache::combo.EnumGet(glean::bfcache::ComboLabel::eUnloadReqMse)
6886 .Add();
6887 break;
6888 case SUSPENDED_UNLOAD_REQUEST_PEER:
6889 glean::bfcache::combo
6890 .EnumGet(glean::bfcache::ComboLabel::eSpdUnloadReqPeer)
6891 .Add();
6892 break;
6893 case REMOTE_SUBFRAMES:
6894 glean::bfcache::combo
6895 .EnumGet(glean::bfcache::ComboLabel::eRemoteSubframes)
6896 .Add();
6897 break;
6898 default:
6899 glean::bfcache::combo.EnumGet(glean::bfcache::ComboLabel::eOther).Add();
6900 break;
6901 }
6902};
6903
6904void nsDocShell::DetachEditorFromWindow() {
6905 if (!mEditorData || mEditorData->WaitingForLoad()) {
6906 // If there's nothing to detach, or if the editor data is actually set
6907 // up for the _new_ page that's coming in, don't detach.
6908 return;
6909 }
6910
6911 nsresult res = mEditorData->DetachFromWindow();
6912 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"
, 6912); MOZ_PretendNoReturn(); } } while (0)
;
6913
6914 if (NS_SUCCEEDED(res)((bool)(__builtin_expect(!!(!NS_FAILED_impl(res)), 1)))) {
6915 mEditorData = nullptr;
6916 }
6917
6918#ifdef DEBUG1
6919 {
6920 bool isEditable;
6921 GetEditable(&isEditable);
6922 NS_ASSERTION(!isEditable,do { if (!(!isEditable)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "Window is still editable after detaching editor."
, "!isEditable", "./../../../docshell/base/nsDocShell.cpp", 6923
); MOZ_PretendNoReturn(); } } while (0)
6923 "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", 6923
); MOZ_PretendNoReturn(); } } while (0)
;
6924 }
6925#endif // DEBUG
6926}
6927
6928NS_IMETHODIMPnsresult
6929nsDocShell::GetRestoringDocument(bool* aRestoring) {
6930 *aRestoring = mIsRestoringDocument;
6931 return NS_OK;
6932}
6933
6934bool nsDocShell::SandboxFlagsImplyCookies(const uint32_t& aSandboxFlags) {
6935 return (aSandboxFlags & (SANDBOXED_ORIGIN | SANDBOXED_SCRIPTS)) == 0;
6936}
6937
6938nsresult nsDocShell::CreateDocumentViewer(const nsACString& aContentType,
6939 nsIRequest* aRequest,
6940 nsIStreamListener** aContentHandler) {
6941 *aContentHandler = nullptr;
6942
6943 if (!mTreeOwner || mIsBeingDestroyed) {
6944 // If we don't have a tree owner, then we're in the process of being
6945 // destroyed. Rather than continue trying to load something, just give up.
6946 return NS_ERROR_DOCSHELL_DYING;
6947 }
6948
6949 if (!mBrowsingContext->AncestorsAreCurrent() ||
6950 mBrowsingContext->IsInBFCache()) {
6951 mBrowsingContext->RemoveRootFromBFCacheSync();
6952 return NS_ERROR_NOT_AVAILABLE;
6953 }
6954
6955 // Can we check the content type of the current content viewer
6956 // and reuse it without destroying it and re-creating it?
6957
6958 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", 6958
); MOZ_PretendNoReturn(); } } while (0)
;
6959
6960 // Instantiate the content viewer object
6961 nsCOMPtr<nsIDocumentViewer> viewer;
6962 nsresult rv = NewDocumentViewerObj(aContentType, aRequest, mLoadGroup,
6963 aContentHandler, getter_AddRefs(viewer));
6964
6965 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
6966 return rv;
6967 }
6968
6969 // Notify the current document that it is about to be unloaded!!
6970 //
6971 // It is important to fire the unload() notification *before* any state
6972 // is changed within the DocShell - otherwise, javascript will get the
6973 // wrong information :-(
6974 //
6975
6976 NS_ASSERTION(!mLoadingURI, "Re-entering unload?")do { if (!(!mLoadingURI)) { NS_DebugBreak(NS_DEBUG_ASSERTION,
"Re-entering unload?", "!mLoadingURI", "./../../../docshell/base/nsDocShell.cpp"
, 6976); MOZ_PretendNoReturn(); } } while (0)
;
6977
6978 nsCOMPtr<nsIChannel> aOpenedChannel = do_QueryInterface(aRequest);
6979 if (aOpenedChannel) {
6980 aOpenedChannel->GetURI(getter_AddRefs(mLoadingURI));
6981 }
6982
6983 // Grab the current URI, we need to pass it to Embed, and OnNewURI will reset
6984 // it before we do call Embed.
6985 nsCOMPtr<nsIURI> previousURI = mCurrentURI;
6986
6987 FirePageHideNotification();
6988 if (mIsBeingDestroyed) {
6989 // Force to stop the newly created orphaned viewer.
6990 viewer->Stop();
6991 return NS_ERROR_DOCSHELL_DYING;
6992 }
6993 mLoadingURI = nullptr;
6994
6995 // Set mFiredUnloadEvent = false so that the unload handler for the
6996 // *new* document will fire.
6997 mFiredUnloadEvent = false;
6998
6999 // we've created a new document so go ahead and call
7000 // OnNewURI(), but don't fire OnLocationChange()
7001 // notifications before we've called Embed(). See bug 284993.
7002 mURIResultedInDocument = true;
7003 bool errorOnLocationChangeNeeded = false;
7004 nsCOMPtr<nsIChannel> failedChannel = mFailedChannel;
7005 nsCOMPtr<nsIURI> failedURI;
7006
7007 // https://html.spec.whatwg.org/#finalize-a-cross-document-navigation
7008 // 9. If entryToReplace is null, then: ...
7009 // Otherwise: ...
7010 // 4. If historyEntry's document state's origin is same origin with
7011 // entryToReplace's document state's origin, then set
7012 // historyEntry's navigation API key to entryToReplace's
7013 // navigation API key.
7014 bool isReplace =
7015 mActiveEntry && mLoadingEntry &&
7016 mLoadingEntry->mTriggeringNavigationType
7017 .map([](auto type) { return type == NavigationType::Replace; })
7018 .valueOr(false);
7019 if (isReplace) {
7020 nsCOMPtr<nsIURI> uri = mActiveEntry->GetURIOrInheritedForAboutBlank();
7021 nsCOMPtr<nsIURI> targetURI =
7022 mLoadingEntry->mInfo.GetURIOrInheritedForAboutBlank();
7023 bool sameOrigin =
7024 NS_SUCCEEDED(nsContentUtils::GetSecurityManager()->CheckSameOriginURI(((bool)(__builtin_expect(!!(!NS_FAILED_impl(nsContentUtils::GetSecurityManager
()->CheckSameOriginURI( targetURI, uri, false, false))), 1
)))
7025 targetURI, uri, false, false))((bool)(__builtin_expect(!!(!NS_FAILED_impl(nsContentUtils::GetSecurityManager
()->CheckSameOriginURI( targetURI, uri, false, false))), 1
)))
;
7026 if (sameOrigin) {
7027 mLoadingEntry->mInfo.NavigationKey() = mActiveEntry->NavigationKey();
7028 }
7029 }
7030
7031 if (mLoadType == LOAD_ERROR_PAGE) {
7032 // We need to set the SH entry and our current URI here and not
7033 // at the moment we load the page. We want the same behavior
7034 // of Stop() as for a normal page load. See bug 514232 for details.
7035
7036 // Revert mLoadType to load type to state the page load failed,
7037 // following function calls need it.
7038 mLoadType = mFailedLoadType;
7039
7040 Document* doc = viewer->GetDocument();
7041 if (doc) {
7042 doc->SetFailedChannel(failedChannel);
7043 }
7044
7045 nsCOMPtr<nsIPrincipal> triggeringPrincipal;
7046 if (failedChannel) {
7047 // Make sure we have a URI to set currentURI.
7048 NS_GetFinalChannelURI(failedChannel, getter_AddRefs(failedURI));
7049 } else {
7050 // if there is no failed channel we have to explicitly provide
7051 // a triggeringPrincipal for the history entry.
7052 triggeringPrincipal = nsContentUtils::GetSystemPrincipal();
7053 }
7054
7055 if (!failedURI) {
7056 failedURI = mFailedURI;
7057 }
7058 if (!failedURI) {
7059 // We need a URI object to store a session history entry, so make up a URI
7060 NS_NewURI(getter_AddRefs(failedURI), "about:blank");
7061 }
7062
7063 // When we don't have failedURI, something wrong will happen. See
7064 // bug 291876.
7065 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", 7065); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "failedURI" ") (" "We don't have a URI for history APIs."
")"); do { MOZ_CrashSequence(__null, 7065); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7066
7067 mFailedChannel = nullptr;
7068 mFailedURI = nullptr;
7069
7070 // Create an shistory entry for the old load.
7071 if (failedURI) {
7072 errorOnLocationChangeNeeded =
7073 OnNewURI(failedURI, failedChannel, triggeringPrincipal, nullptr,
7074 nullptr, nullptr, false, false);
7075 }
7076
7077 mLoadType = LOAD_ERROR_PAGE;
7078 }
7079
7080 nsCOMPtr<nsIURI> finalURI;
7081 // If this a redirect, use the final url (uri)
7082 // else use the original url
7083 //
7084 // Note that this should match what documents do (see Document::Reset).
7085 NS_GetFinalChannelURI(aOpenedChannel, getter_AddRefs(finalURI));
7086
7087 bool onLocationChangeNeeded = false;
7088 if (finalURI) {
7089 // Pass false for aCloneSHChildren, since we're loading a new page here.
7090 onLocationChangeNeeded = OnNewURI(finalURI, aOpenedChannel, nullptr,
7091 nullptr, nullptr, nullptr, true, false);
7092 }
7093
7094 // We inherit the classification flags from the parent document if the
7095 // document is about:blank and the principal matches.
7096 nsCOMPtr<nsIDocShellTreeItem> parentItem;
7097 GetInProcessSameTypeParent(getter_AddRefs(parentItem));
7098 if (parentItem && finalURI && NS_IsAboutBlank(finalURI)) {
7099 RefPtr<Document> doc = viewer->GetDocument();
7100 RefPtr<Document> parentDocument = parentItem->GetDocument();
7101 if (parentDocument && doc &&
7102 doc->NodePrincipal()->Equals(parentDocument->NodePrincipal())) {
7103 doc->SetClassificationFlags(parentDocument->GetClassificationFlags());
7104 }
7105 }
7106
7107 // let's try resetting the load group if we need to...
7108 nsCOMPtr<nsILoadGroup> currentLoadGroup;
7109 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"
, 7111); return NS_ERROR_FAILURE; } } while (false)
7110 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"
, 7111); return NS_ERROR_FAILURE; } } while (false)
7111 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"
, 7111); return NS_ERROR_FAILURE; } } while (false)
;
7112
7113 if (currentLoadGroup != mLoadGroup) {
7114 nsLoadFlags loadFlags = 0;
7115
7116 // Cancel any URIs that are currently loading...
7117 // XXX: Need to do this eventually Stop();
7118 //
7119 // Retarget the document to this loadgroup...
7120 //
7121 /* First attach the channel to the right loadgroup
7122 * and then remove from the old loadgroup. This
7123 * puts the notifications in the right order and
7124 * we don't null-out mLSHE in OnStateChange() for
7125 * all redirected urls
7126 */
7127 aOpenedChannel->SetLoadGroup(mLoadGroup);
7128
7129 // Mark the channel as being a document URI...
7130 aOpenedChannel->GetLoadFlags(&loadFlags);
7131 loadFlags |= nsIChannel::LOAD_DOCUMENT_URI;
7132 nsCOMPtr<nsILoadInfo> loadInfo = aOpenedChannel->LoadInfo();
7133 if (SandboxFlagsImplyCookies(loadInfo->GetSandboxFlags())) {
7134 loadFlags |= nsIRequest::LOAD_DOCUMENT_NEEDS_COOKIE;
7135 }
7136
7137 aOpenedChannel->SetLoadFlags(loadFlags);
7138
7139 mLoadGroup->AddRequest(aRequest, nullptr);
7140 if (currentLoadGroup) {
7141 currentLoadGroup->RemoveRequest(aRequest, nullptr, NS_BINDING_RETARGETED);
7142 }
7143
7144 // Update the notification callbacks, so that progress and
7145 // status information are sent to the right docshell...
7146 aOpenedChannel->SetNotificationCallbacks(this);
7147 }
7148
7149 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"
, 7150); return NS_ERROR_FAILURE; } } while (false)
7150 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"
, 7150); return NS_ERROR_FAILURE; } } while (false)
;
7151
7152 if (!mBrowsingContext->GetHasLoadedNonInitialDocument()) {
7153 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", 7153); AnnotateMozCrashReason
("MOZ_CRASH(" "NS_SUCCEEDED(mBrowsingContext->SetHasLoadedNonInitialDocument(true))"
")"); do { MOZ_CrashSequence(__null, 7153); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
;
7154 }
7155
7156 mSavedRefreshURIList = nullptr;
7157 mEODForCurrentDocument = false;
7158
7159 // if this document is part of a multipart document,
7160 // the ID can be used to distinguish it from the other parts.
7161 nsCOMPtr<nsIMultiPartChannel> multiPartChannel(do_QueryInterface(aRequest));
7162 if (multiPartChannel) {
7163 if (PresShell* presShell = GetPresShell()) {
7164 if (Document* doc = presShell->GetDocument()) {
7165 uint32_t partID;
7166 multiPartChannel->GetPartID(&partID);
7167 doc->SetPartID(partID);
7168 }
7169 }
7170 }
7171
7172 if (errorOnLocationChangeNeeded) {
7173 FireOnLocationChange(this, failedChannel, failedURI,
7174 LOCATION_CHANGE_ERROR_PAGE);
7175 } else if (onLocationChangeNeeded) {
7176 uint32_t locationFlags =
7177 (mLoadType & LOAD_CMD_RELOAD) ? uint32_t(LOCATION_CHANGE_RELOAD) : 0;
7178 FireOnLocationChange(this, aRequest, mCurrentURI, locationFlags);
7179 }
7180
7181 return NS_OK;
7182}
7183
7184nsresult nsDocShell::NewDocumentViewerObj(const nsACString& aContentType,
7185 nsIRequest* aRequest,
7186 nsILoadGroup* aLoadGroup,
7187 nsIStreamListener** aContentHandler,
7188 nsIDocumentViewer** aViewer) {
7189 nsCOMPtr<nsIChannel> aOpenedChannel = do_QueryInterface(aRequest);
7190
7191 nsCOMPtr<nsIDocumentLoaderFactory> docLoaderFactory =
7192 nsContentUtils::FindInternalDocumentViewer(aContentType);
7193 if (!docLoaderFactory) {
7194 return NS_ERROR_FAILURE;
7195 }
7196
7197 // Now create an instance of the content viewer nsLayoutDLF makes the
7198 // determination if it should be a "view-source" instead of "view"
7199 nsresult rv = docLoaderFactory->CreateInstance(
7200 "view", aOpenedChannel, aLoadGroup, aContentType, this, nullptr,
7201 aContentHandler, aViewer);
7202 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"
, 7202); return rv; } } while (false)
;
7203
7204 (*aViewer)->SetContainer(this);
7205 return NS_OK;
7206}
7207
7208nsresult nsDocShell::SetupNewViewer(nsIDocumentViewer* aNewViewer,
7209 WindowGlobalChild* aWindowActor) {
7210 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", 7210); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!mIsBeingDestroyed" ")"); do { MOZ_CrashSequence
(__null, 7210); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
7211
7212 //
7213 // Copy content viewer state from previous or parent content viewer.
7214 //
7215 // The following logic is mirrored in nsHTMLDocument::StartDocumentLoad!
7216 //
7217 // Do NOT to maintain a reference to the old content viewer outside
7218 // of this "copying" block, or it will not be destroyed until the end of
7219 // this routine and all <SCRIPT>s and event handlers fail! (bug 20315)
7220 //
7221 // In this block of code, if we get an error result, we return it
7222 // but if we get a null pointer, that's perfectly legal for parent
7223 // and parentDocumentViewer.
7224 //
7225
7226 int32_t x = 0;
7227 int32_t y = 0;
7228 int32_t cx = 0;
7229 int32_t cy = 0;
7230
7231 // This will get the size from the current content viewer or from the
7232 // Init settings
7233 DoGetPositionAndSize(&x, &y, &cx, &cy);
7234
7235 nsCOMPtr<nsIDocShellTreeItem> parentAsItem;
7236 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"
, 7237); return NS_ERROR_FAILURE; } } while (false)
7237 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"
, 7237); return NS_ERROR_FAILURE; } } while (false)
;
7238 nsCOMPtr<nsIDocShell> parent(do_QueryInterface(parentAsItem));
7239
7240 const Encoding* reloadEncoding = nullptr;
7241 int32_t reloadEncodingSource = kCharsetUninitialized;
7242 // |newMUDV| also serves as a flag to set the data from the above vars
7243 nsCOMPtr<nsIDocumentViewer> newViewer;
7244
7245 if (mDocumentViewer || parent) {
7246 nsCOMPtr<nsIDocumentViewer> oldViewer;
7247 if (mDocumentViewer) {
7248 // Get any interesting state from old content viewer
7249 // XXX: it would be far better to just reuse the document viewer ,
7250 // since we know we're just displaying the same document as before
7251 oldViewer = mDocumentViewer;
7252 } else {
7253 // No old content viewer, so get state from parent's content viewer
7254 parent->GetDocViewer(getter_AddRefs(oldViewer));
7255 }
7256
7257 if (oldViewer) {
7258 newViewer = aNewViewer;
7259 if (newViewer) {
7260 reloadEncoding =
7261 oldViewer->GetReloadEncodingAndSource(&reloadEncodingSource);
7262 }
7263 }
7264 }
7265
7266 SingleCanvasBackground canvasBg = {};
7267 bool isUnderHiddenEmbedderElement = false;
7268 // Ensure that the content viewer is destroyed *after* the GC - bug 71515
7269 nsCOMPtr<nsIDocumentViewer> viewer = mDocumentViewer;
7270 if (viewer) {
7271 // Stop any activity that may be happening in the old document before
7272 // releasing it...
7273 viewer->Stop();
7274
7275 // Try to extract the canvas background color from the old
7276 // presentation shell, so we can use it for the next document.
7277 if (PresShell* presShell = viewer->GetPresShell()) {
7278 canvasBg = presShell->GetViewportCanvasBackground();
7279 isUnderHiddenEmbedderElement = presShell->IsUnderHiddenEmbedderElement();
7280 }
7281
7282 viewer->Close();
7283 aNewViewer->SetPreviousViewer(viewer);
7284 }
7285
7286 mDocumentViewer = nullptr;
7287
7288 // Now that we're about to switch documents, forget all of our children.
7289 // Note that we cached them as needed up in CaptureState above.
7290 DestroyChildren();
7291
7292 mDocumentViewer = aNewViewer;
7293
7294 nsCOMPtr<nsIWidget> widget = GetMainWidget();
7295 LayoutDeviceIntRect bounds(x, y, cx, cy);
7296
7297 mDocumentViewer->SetNavigationTiming(mTiming);
7298
7299 nsresult rv =
7300 MOZ_KnownLive(mDocumentViewer)(mDocumentViewer)->Init(widget, bounds, aWindowActor);
7301 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
7302 nsCOMPtr<nsIDocumentViewer> viewer = mDocumentViewer;
7303 viewer->Close();
7304 viewer->Destroy();
7305 mDocumentViewer = nullptr;
7306 SetCurrentURIInternal(nullptr);
7307 NS_WARNING("DocumentViewer Initialization failed")NS_DebugBreak(NS_DEBUG_WARNING, "DocumentViewer Initialization failed"
, nullptr, "./../../../docshell/base/nsDocShell.cpp", 7307)
;
7308 return rv;
7309 }
7310
7311 // If we have old state to copy, set the old state onto the new content
7312 // viewer
7313 if (newViewer) {
7314 newViewer->SetReloadEncodingAndSource(reloadEncoding, reloadEncodingSource);
7315 }
7316
7317 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", 7317); return
NS_ERROR_FAILURE; } } while (false)
;
7318
7319 // Stuff the bgcolor from the old pres shell into the new
7320 // pres shell. This improves page load continuity.
7321 if (RefPtr<PresShell> presShell = mDocumentViewer->GetPresShell()) {
7322 presShell->SetViewportCanvasBackground(canvasBg);
7323 presShell->ActivenessMaybeChanged();
7324 if (isUnderHiddenEmbedderElement) {
7325 presShell->SetIsUnderHiddenEmbedderElement(isUnderHiddenEmbedderElement);
7326 }
7327 }
7328
7329 // XXX: It looks like the LayoutState gets restored again in Embed()
7330 // right after the call to SetupNewViewer(...)
7331
7332 // We don't show the mDocumentViewer yet, since we want to draw the old page
7333 // until we have enough of the new page to show. Just return with the new
7334 // viewer still set to hidden.
7335
7336 return NS_OK;
7337}
7338
7339void nsDocShell::SetDocCurrentStateObj(SessionHistoryInfo* aInfo) {
7340 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", 7340); return
; } } while (false)
;
7341
7342 RefPtr<Document> document = GetDocument();
7343 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", 7343); return; }
} while (false)
;
7344
7345 nsCOMPtr<nsIStructuredCloneContainer> scContainer;
7346 // If aInfo is null, just set the document's state object to null.
7347 if (aInfo) {
7348 scContainer = aInfo->GetStateData();
7349 }
7350 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)
7351 ("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)
;
7352
7353 // It's OK for scContainer too be null here; that just means there's no
7354 // state data associated with this history entry.
7355 document->SetStateObject(scContainer);
7356}
7357
7358nsresult nsDocShell::CheckLoadingPermissions() {
7359 // This method checks whether the caller may load content into
7360 // this docshell. Even though we've done our best to hide windows
7361 // from code that doesn't have the right to access them, it's
7362 // still possible for an evil site to open a window and access
7363 // frames in the new window through window.frames[] (which is
7364 // allAccess for historic reasons), so we still need to do this
7365 // check on load.
7366 nsresult rv = NS_OK;
7367
7368 if (!IsSubframe()) {
7369 // We're not a frame. Permit all loads.
7370 return rv;
7371 }
7372
7373 // Note - The check for a current JSContext here isn't necessarily sensical.
7374 // It's just designed to preserve the old semantics during a mass-conversion
7375 // patch.
7376 if (!nsContentUtils::GetCurrentJSContext()) {
7377 return NS_OK;
7378 }
7379
7380 // Check if the caller is from the same origin as this docshell,
7381 // or any of its ancestors.
7382 nsIPrincipal* subjectPrincipal = nsContentUtils::SubjectPrincipal();
7383 for (RefPtr<BrowsingContext> bc = mBrowsingContext; bc;
7384 bc = bc->GetParent()) {
7385 // If the BrowsingContext is not in process, then it
7386 // is true by construction that its principal will not
7387 // subsume the current docshell principal.
7388 if (!bc->IsInProcess()) {
7389 continue;
7390 }
7391
7392 nsCOMPtr<nsIScriptGlobalObject> sgo =
7393 bc->GetDocShell()->GetScriptGlobalObject();
7394 nsCOMPtr<nsIScriptObjectPrincipal> sop(do_QueryInterface(sgo));
7395
7396 nsIPrincipal* p;
7397 if (!sop || !(p = sop->GetPrincipal())) {
7398 return NS_ERROR_UNEXPECTED;
7399 }
7400
7401 // file: URIs are considered the same domain for the purpose of frame
7402 // navigation by clicking a targeted link, regardless of script
7403 // accessibility (bug 1934807).
7404 if (subjectPrincipal->Subsumes(p) ||
7405 (subjectPrincipal->SchemeIs("file") && p->SchemeIs("file"))) {
7406 // Same origin, permit load
7407 return NS_OK;
7408 }
7409 }
7410
7411 return NS_ERROR_DOM_PROP_ACCESS_DENIED;
7412}
7413
7414//*****************************************************************************
7415// nsDocShell: Site Loading
7416//*****************************************************************************
7417
7418void nsDocShell::CopyFavicon(nsIURI* aOldURI, nsIURI* aNewURI,
7419 bool aInPrivateBrowsing) {
7420 if (XRE_IsContentProcess()) {
7421 dom::ContentChild* contentChild = dom::ContentChild::GetSingleton();
7422 if (contentChild) {
7423 contentChild->SendCopyFavicon(aOldURI, aNewURI, aInPrivateBrowsing);
7424 }
7425 return;
7426 }
7427
7428#ifdef MOZ_PLACES1
7429 auto* faviconService = nsFaviconService::GetFaviconService();
7430 if (faviconService) {
7431 faviconService->AsyncTryCopyFavicons(
7432 aOldURI, aNewURI,
7433 aInPrivateBrowsing ? nsIFaviconService::FAVICON_LOAD_PRIVATE
7434 : nsIFaviconService::FAVICON_LOAD_NON_PRIVATE);
7435 }
7436#endif
7437}
7438
7439class InternalLoadEvent : public Runnable {
7440 public:
7441 InternalLoadEvent(nsDocShell* aDocShell, nsDocShellLoadState* aLoadState)
7442 : mozilla::Runnable("InternalLoadEvent"),
7443 mDocShell(aDocShell),
7444 mLoadState(aLoadState) {
7445 // For events, both target and filename should be the version of "null" they
7446 // expect. By the time the event is fired, both window targeting and file
7447 // downloading have been handled, so we should never have an internal load
7448 // event that retargets or had a download.
7449 mLoadState->SetTarget(u""_ns);
7450 mLoadState->SetFileName(VoidString());
7451 }
7452
7453 NS_IMETHODvirtual nsresult
7454 Run() override {
7455#ifndef ANDROID
7456 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", 7457); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "mLoadState->TriggeringPrincipal()" ") ("
"InternalLoadEvent: Should always have a principal here" ")"
); do { MOZ_CrashSequence(__null, 7457); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
7457 "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", 7457); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "mLoadState->TriggeringPrincipal()" ") ("
"InternalLoadEvent: Should always have a principal here" ")"
); do { MOZ_CrashSequence(__null, 7457); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7458#endif
7459 return mDocShell->InternalLoad(mLoadState);
7460 }
7461
7462 private:
7463 RefPtr<nsDocShell> mDocShell;
7464 RefPtr<nsDocShellLoadState> mLoadState;
7465};
7466
7467/**
7468 * Returns true if we started an asynchronous load (i.e., from the network), but
7469 * the document we're loading there hasn't yet become this docshell's active
7470 * document.
7471 *
7472 * When JustStartedNetworkLoad is true, you should be careful about modifying
7473 * mLoadType and mLSHE. These are both set when the asynchronous load first
7474 * starts, and the load expects that, when it eventually runs InternalLoad,
7475 * mLoadType and mLSHE will have their original values.
7476 */
7477bool nsDocShell::JustStartedNetworkLoad() {
7478 return mDocumentRequest && mDocumentRequest != GetCurrentDocChannel();
7479}
7480
7481// The contentType will be INTERNAL_(I)FRAME if this docshell is for a
7482// non-toplevel browsing context in spec terms. (frame, iframe, <object>,
7483// <embed>, etc)
7484//
7485// This return value will be used when we call NS_CheckContentLoadPolicy, and
7486// later when we call DoURILoad.
7487nsContentPolicyType nsDocShell::DetermineContentType() {
7488 if (!IsSubframe()) {
7489 return nsIContentPolicy::TYPE_DOCUMENT;
7490 }
7491
7492 const auto& maybeEmbedderElementType =
7493 GetBrowsingContext()->GetEmbedderElementType();
7494 if (!maybeEmbedderElementType) {
7495 // If the EmbedderElementType hasn't been set yet, just assume we're
7496 // an iframe since that's more common.
7497 return nsIContentPolicy::TYPE_INTERNAL_IFRAME;
7498 }
7499
7500 return maybeEmbedderElementType->EqualsLiteral("iframe")
7501 ? nsIContentPolicy::TYPE_INTERNAL_IFRAME
7502 : nsIContentPolicy::TYPE_INTERNAL_FRAME;
7503}
7504
7505bool nsDocShell::NoopenerForceEnabled() {
7506 // If current's top-level browsing context's active document's
7507 // cross-origin-opener-policy is "same-origin" or "same-origin + COEP" then
7508 // if currentDoc's origin is not same origin with currentDoc's top-level
7509 // origin, noopener is force enabled, and name is cleared to "_blank".
7510 auto topPolicy = mBrowsingContext->Top()->GetOpenerPolicy();
7511 return (topPolicy == nsILoadInfo::OPENER_POLICY_SAME_ORIGIN ||
7512 topPolicy ==
7513 nsILoadInfo::
7514 OPENER_POLICY_SAME_ORIGIN_EMBEDDER_POLICY_REQUIRE_CORP) &&
7515 !mBrowsingContext->SameOriginWithTop();
7516}
7517
7518nsresult nsDocShell::ComputeNamedTargetBrowsingContext(
7519 nsDocShellLoadState* aLoadState) {
7520 if (aLoadState->HasComputedNamedTargetBrowsingContext() ||
7521 aLoadState->Target().IsEmpty()) {
7522 return NS_OK;
7523 }
7524 // Only _self, _parent, and _top are supported in noopener case. But we
7525 // have to be careful to not apply that to the noreferrer case. See bug
7526 // 1358469.
7527 bool allowNamedTarget =
7528 !aLoadState->HasInternalLoadFlags(INTERNAL_LOAD_FLAGS_NO_OPENER) ||
7529 aLoadState->HasInternalLoadFlags(INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER);
7530 if (allowNamedTarget ||
7531 aLoadState->Target().LowerCaseEqualsLiteral("_self") ||
7532 aLoadState->Target().LowerCaseEqualsLiteral("_parent") ||
7533 aLoadState->Target().LowerCaseEqualsLiteral("_top")) {
7534 Document* document = GetDocument();
7535 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", 7535); return NS_ERROR_FAILURE
; } } while (false)
;
7536 WindowGlobalChild* wgc = document->GetWindowGlobalChild();
7537 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"
, 7537); return NS_ERROR_FAILURE; } } while (false)
;
7538 aLoadState->SetTargetBrowsingContext(wgc->FindBrowsingContextWithName(
7539 aLoadState->Target(), /* aUseEntryGlobalForAccessCheck */ false));
7540 }
7541 aLoadState->SetHasComputedNamedTargetBrowsingContext(true);
7542 return NS_OK;
7543}
7544
7545nsresult nsDocShell::PerformRetargeting(nsDocShellLoadState* aLoadState) {
7546 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", 7546); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aLoadState" ") (" "need a load state!" ")"
); do { MOZ_CrashSequence(__null, 7546); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7547 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", 7547); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!aLoadState->Target().IsEmpty()" ") (" "should have a target here!"
")"); do { MOZ_CrashSequence(__null, 7547); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7548
7549 nsresult rv = NS_OK;
7550
7551 rv = ComputeNamedTargetBrowsingContext(aLoadState);
7552 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"
, 7552); return rv; } } while (false)
;
7553 const MaybeDiscarded<BrowsingContext>& targetBCMaybeDiscarded =
7554 aLoadState->TargetBrowsingContext();
7555 if (targetBCMaybeDiscarded.IsDiscarded()) {
7556 // e.g. target frame navigated to cross-origin site before async navigation
7557 // happened
7558 return NS_BINDING_ABORTED;
7559 }
7560 RefPtr<BrowsingContext> targetContext =
7561 targetBCMaybeDiscarded.GetMaybeDiscarded();
7562
7563 if (!targetContext) {
7564 // If the targetContext doesn't exist, then this is a new docShell and we
7565 // should consider this a TYPE_DOCUMENT load
7566 //
7567 // For example, when target="_blank"
7568
7569 // If there's no targetContext, that means we are about to create a new
7570 // window. Perform a content policy check before creating the window. Please
7571 // note for all other docshell loads content policy checks are performed
7572 // within the contentSecurityManager when the channel is about to be
7573 // openend.
7574 nsISupports* requestingContext = nullptr;
7575 if (XRE_IsContentProcess()) {
7576 // In e10s the child process doesn't have access to the element that
7577 // contains the browsing context (because that element is in the chrome
7578 // process). So we just pass mScriptGlobal.
7579 requestingContext = ToSupports(mScriptGlobal);
7580 } else {
7581 // This is for loading non-e10s tabs and toplevel windows of various
7582 // sorts.
7583 // For the toplevel window cases, requestingElement will be null.
7584 nsCOMPtr<Element> requestingElement =
7585 mScriptGlobal->GetFrameElementInternal();
7586 requestingContext = requestingElement;
7587 }
7588
7589 // Ideally we should use the same loadinfo as within DoURILoad which
7590 // should match this one when both are applicable.
7591 RefPtr secCheckLoadInfo = MakeRefPtr<LoadInfo>(
7592 mScriptGlobal, aLoadState->URI(), aLoadState->TriggeringPrincipal(),
7593 requestingContext, nsILoadInfo::SEC_ONLY_FOR_EXPLICIT_CONTENTSEC_CHECK,
7594 0);
7595
7596 // Since Content Policy checks are performed within docShell as well as
7597 // the ContentSecurityManager we need a reliable way to let certain
7598 // nsIContentPolicy consumers ignore duplicate calls.
7599 secCheckLoadInfo->SetSkipContentPolicyCheckForWebRequest(true);
7600
7601 int16_t shouldLoad = nsIContentPolicy::ACCEPT;
7602 rv = NS_CheckContentLoadPolicy(aLoadState->URI(), secCheckLoadInfo,
7603 &shouldLoad);
7604
7605 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) || NS_CP_REJECTED(shouldLoad)((shouldLoad) != nsIContentPolicy::ACCEPT)) {
7606 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
7607 if (shouldLoad == nsIContentPolicy::REJECT_TYPE) {
7608 return NS_ERROR_CONTENT_BLOCKED_SHOW_ALT;
7609 }
7610 if (shouldLoad == nsIContentPolicy::REJECT_POLICY) {
7611 return NS_ERROR_BLOCKED_BY_POLICY;
7612 }
7613 }
7614
7615 return NS_ERROR_CONTENT_BLOCKED;
7616 }
7617 }
7618
7619 //
7620 // Resolve the window target before going any further...
7621 // If the load has been targeted to another DocShell, then transfer the
7622 // load to it...
7623 //
7624
7625 // We've already done our owner-inheriting. Mask out that bit, so we
7626 // don't try inheriting an owner from the target window if we came up
7627 // with a null owner above.
7628 aLoadState->UnsetInternalLoadFlag(INTERNAL_LOAD_FLAGS_INHERIT_PRINCIPAL);
7629
7630 if (!targetContext) {
7631 // If the docshell's document is sandboxed, only open a new window
7632 // if the document's SANDBOXED_AUXILLARY_NAVIGATION flag is not set.
7633 // (i.e. if allow-popups is specified)
7634 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", 7634); return
NS_ERROR_FAILURE; } } while (false)
;
7635 Document* doc = mDocumentViewer->GetDocument();
7636
7637 const bool isDocumentAuxSandboxed =
7638 doc && (doc->GetSandboxFlags() & SANDBOXED_AUXILIARY_NAVIGATION);
7639
7640 if (isDocumentAuxSandboxed) {
7641 return NS_ERROR_DOM_INVALID_ACCESS_ERR;
7642 }
7643
7644 nsCOMPtr<nsPIDOMWindowOuter> win = GetWindow();
7645 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"
, 7645); return NS_ERROR_NOT_AVAILABLE; } } while (false)
;
7646
7647 RefPtr<BrowsingContext> newBC;
7648 nsAutoCString spec;
7649 aLoadState->URI()->GetSpec(spec);
7650
7651 // If we are a noopener load, we just hand the whole thing over to our
7652 // window.
7653 if (aLoadState->HasInternalLoadFlags(INTERNAL_LOAD_FLAGS_NO_OPENER) ||
7654 NoopenerForceEnabled()) {
7655 // Various asserts that we know to hold because NO_OPENER loads can only
7656 // happen for links.
7657 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"
, 7657); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aLoadState->LoadReplace()"
")"); do { MOZ_CrashSequence(__null, 7657); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7658 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", 7659); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aLoadState->PrincipalToInherit() == aLoadState->TriggeringPrincipal()"
")"); do { MOZ_CrashSequence(__null, 7659); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
7659 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", 7659); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aLoadState->PrincipalToInherit() == aLoadState->TriggeringPrincipal()"
")"); do { MOZ_CrashSequence(__null, 7659); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7660 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", 7664); 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, 7664); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
7661 ~(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", 7664); 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, 7664); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
7662 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", 7664); 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, 7664); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
7663 "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", 7664); 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, 7664); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
7664 "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", 7664); 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, 7664); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7665 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"
, 7666); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->IsFormSubmission()"
")"); do { MOZ_CrashSequence(__null, 7666); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
7666 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"
, 7666); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->IsFormSubmission()"
")"); do { MOZ_CrashSequence(__null, 7666); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
7667 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"
, 7667); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aLoadState->HeadersStream()"
")"); do { MOZ_CrashSequence(__null, 7667); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7668 // If OnLinkClickSync was invoked inside the onload handler, the load
7669 // type would be set to LOAD_NORMAL_REPLACE; otherwise it should be
7670 // LOAD_LINK.
7671 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", 7672); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aLoadState->LoadType() == LOAD_LINK || aLoadState->LoadType() == LOAD_NORMAL_REPLACE"
")"); do { MOZ_CrashSequence(__null, 7672); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
7672 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", 7672); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aLoadState->LoadType() == LOAD_LINK || aLoadState->LoadType() == LOAD_NORMAL_REPLACE"
")"); do { MOZ_CrashSequence(__null, 7672); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7673 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", 7673); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!aLoadState->LoadIsFromSessionHistory()"
")"); do { MOZ_CrashSequence(__null, 7673); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7674 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", 7674); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aLoadState->FirstParty()" ")"); do { MOZ_CrashSequence
(__null, 7674); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
; // Windowwatcher will assume this.
7675
7676 RefPtr loadState = MakeRefPtr<nsDocShellLoadState>(aLoadState->URI());
7677
7678 // Set up our loadinfo so it will do the load as much like we would have
7679 // as possible.
7680 loadState->SetReferrerInfo(aLoadState->GetReferrerInfo());
7681 loadState->SetOriginalURI(aLoadState->OriginalURI());
7682
7683 Maybe<nsCOMPtr<nsIURI>> resultPrincipalURI;
7684 aLoadState->GetMaybeResultPrincipalURI(resultPrincipalURI);
7685
7686 loadState->SetMaybeResultPrincipalURI(resultPrincipalURI);
7687 loadState->SetKeepResultPrincipalURIIfSet(
7688 aLoadState->KeepResultPrincipalURIIfSet());
7689 // LoadReplace will always be false due to asserts above, skip setting
7690 // it.
7691 loadState->SetTriggeringPrincipal(aLoadState->TriggeringPrincipal());
7692 loadState->SetTriggeringSandboxFlags(
7693 aLoadState->TriggeringSandboxFlags());
7694 loadState->SetTriggeringWindowId(aLoadState->TriggeringWindowId());
7695 loadState->SetTriggeringClassificationFlags(
7696 aLoadState->TriggeringClassificationFlags());
7697 loadState->SetPolicyContainer(aLoadState->PolicyContainer());
7698 loadState->SetInheritPrincipal(aLoadState->HasInternalLoadFlags(
7699 INTERNAL_LOAD_FLAGS_INHERIT_PRINCIPAL));
7700 // Explicit principal because we do not want any guesses as to what the
7701 // principal to inherit is: it should be aTriggeringPrincipal.
7702 loadState->SetPrincipalIsExplicit(true);
7703 loadState->SetLoadType(aLoadState->LoadType());
7704 loadState->SetForceAllowDataURI(aLoadState->HasInternalLoadFlags(
7705 INTERNAL_LOAD_FLAGS_FORCE_ALLOW_DATA_URI));
7706
7707 loadState->SetHasValidUserGestureActivation(
7708 aLoadState->HasValidUserGestureActivation());
7709
7710 loadState->SetTextDirectiveUserActivation(
7711 aLoadState->GetTextDirectiveUserActivation());
7712
7713 // Propagate POST data to the new load.
7714 loadState->SetPostDataStream(aLoadState->PostDataStream());
7715 loadState->SetIsFormSubmission(aLoadState->IsFormSubmission());
7716
7717 loadState->SetNavigationAPIState(aLoadState->GetNavigationAPIState());
7718
7719 rv = win->Open(spec,
7720 aLoadState->Target(), // window name
7721 u""_ns, // Features
7722 loadState,
7723 true, // aForceNoOpener
7724 getter_AddRefs(newBC));
7725 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"
, 7725); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!newBC" ")"
); do { MOZ_CrashSequence(__null, 7725); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7726 return rv;
7727 }
7728
7729 rv = win->OpenNoNavigate(spec,
7730 aLoadState->Target(), // window name
7731 u""_ns, // Features
7732 getter_AddRefs(newBC));
7733
7734 // In some cases the Open call doesn't actually result in a new
7735 // window being opened. We can detect these cases by examining the
7736 // document in |newBC|, if any.
7737 nsCOMPtr<nsPIDOMWindowOuter> piNewWin =
7738 newBC ? newBC->GetDOMWindow() : nullptr;
7739 if (piNewWin) {
7740 RefPtr<Document> newDoc = piNewWin->GetExtantDoc();
7741 if (!newDoc || newDoc->IsInitialDocument()) {
7742 aLoadState->SetInternalLoadFlag(INTERNAL_LOAD_FLAGS_FIRST_LOAD);
7743 }
7744 }
7745
7746 if (newBC) {
7747 targetContext = newBC;
7748 }
7749 }
7750 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"
, 7750); return rv; } } while (false)
;
7751 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", 7751); return
rv; } } while (false)
;
7752
7753 // If our target BrowsingContext is still pending initialization, ignore the
7754 // navigation request targeting it.
7755 if (NS_WARN_IF(targetContext->GetPendingInitialization())NS_warn_if_impl(targetContext->GetPendingInitialization(),
"targetContext->GetPendingInitialization()", "./../../../docshell/base/nsDocShell.cpp"
, 7755)
) {
7756 return NS_OK;
7757 }
7758
7759 aLoadState->SetTargetBrowsingContext(targetContext);
7760 if (aLoadState->IsFormSubmission()) {
7761 aLoadState->SetLoadType(
7762 GetLoadTypeForFormSubmission(targetContext, aLoadState));
7763 }
7764
7765 //
7766 // Transfer the load to the target BrowsingContext... Clear the window target
7767 // name to the empty string to prevent recursive retargeting!
7768 //
7769 // No window target
7770 aLoadState->SetTarget(u""_ns);
7771 // No forced download
7772 aLoadState->SetFileName(VoidString());
7773 return targetContext->InternalLoad(aLoadState);
7774}
7775
7776static nsAutoCString RefMaybeNull(nsIURI* aURI) {
7777 nsAutoCString result;
7778 if (NS_FAILED(aURI->GetRef(result))((bool)(__builtin_expect(!!(NS_FAILED_impl(aURI->GetRef(result
))), 0)))
) {
7779 result.SetIsVoid(true);
7780 }
7781 return result;
7782}
7783
7784uint32_t nsDocShell::GetSameDocumentNavigationFlags(nsIURI* aNewURI) {
7785 uint32_t flags = LOCATION_CHANGE_SAME_DOCUMENT;
7786
7787 bool equal = false;
7788 if (mCurrentURI &&
7789 NS_SUCCEEDED(mCurrentURI->EqualsExceptRef(aNewURI, &equal))((bool)(__builtin_expect(!!(!NS_FAILED_impl(mCurrentURI->EqualsExceptRef
(aNewURI, &equal))), 1)))
&& equal &&
7790 RefMaybeNull(mCurrentURI) != RefMaybeNull(aNewURI)) {
7791 flags |= LOCATION_CHANGE_HASHCHANGE;
7792 }
7793
7794 return flags;
7795}
7796
7797struct SameDocumentNavigationState {
7798 nsAutoCString mCurrentHash;
7799 nsAutoCString mNewHash;
7800 nsTArray<TextDirective> mTextDirectives;
7801 bool mCurrentURIHasRef = false;
7802 bool mNewURIHasRef = false;
7803 bool mSameExceptHashes = false;
7804 bool mSecureUpgradeURI = false;
7805 bool mHistoryNavBetweenSameDoc = false;
7806 bool mIdentical = false;
7807};
7808
7809static bool IsSamePrincipalForDocumentURI(nsIPrincipal* aCurrentPrincipal,
7810 nsIURI* aCurrentURI,
7811 nsIURI* aNewURI) {
7812 nsCOMPtr<nsIURI> principalURI = aCurrentPrincipal->GetURI();
7813 if (aCurrentPrincipal->GetIsNullPrincipal()) {
7814 if (nsCOMPtr<nsIPrincipal> precursor =
7815 aCurrentPrincipal->GetPrecursorPrincipal()) {
7816 principalURI = precursor->GetURI();
7817 }
7818 }
7819
7820 return !nsScriptSecurityManager::IsHttpOrHttpsAndCrossOrigin(principalURI,
7821 aNewURI) &&
7822 !nsScriptSecurityManager::IsHttpOrHttpsAndCrossOrigin(principalURI,
7823 aCurrentURI) &&
7824 !nsScriptSecurityManager::IsHttpOrHttpsAndCrossOrigin(aCurrentURI,
7825 aNewURI);
7826}
7827
7828bool nsDocShell::IsSameDocumentNavigation(nsDocShellLoadState* aLoadState,
7829 SameDocumentNavigationState& aState) {
7830 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"
, 7830); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState"
")"); do { MOZ_CrashSequence(__null, 7830); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7831 if (!(aLoadState->LoadType() == LOAD_NORMAL ||
7832 aLoadState->LoadType() == LOAD_STOP_CONTENT ||
7833 LOAD_TYPE_HAS_FLAGS(aLoadState->LoadType(),((aLoadState->LoadType()) & ((LOAD_FLAGS_REPLACE_HISTORY
) << 16))
7834 LOAD_FLAGS_REPLACE_HISTORY)((aLoadState->LoadType()) & ((LOAD_FLAGS_REPLACE_HISTORY
) << 16))
||
7835 aLoadState->LoadType() == LOAD_HISTORY ||
7836 aLoadState->LoadType() == LOAD_LINK)) {
7837 return false;
7838 }
7839
7840 if (GetExtantDocument() &&
7841 GetExtantDocument()->IsUncommittedInitialDocument()) {
7842 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)
7843 ("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)
7844 "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)
7845 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)
;
7846 return false;
7847 }
7848
7849 nsCOMPtr<nsIURI> currentURI = mCurrentURI;
7850
7851 nsresult rvURINew = aLoadState->URI()->GetRef(aState.mNewHash);
7852 if (NS_SUCCEEDED(rvURINew)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rvURINew)), 1)))) {
7853 rvURINew = aLoadState->URI()->GetHasRef(&aState.mNewURIHasRef);
7854 }
7855
7856 // A Fragment Directive must be removed from the new hash in order to allow
7857 // fallback element id scroll.
7858 FragmentDirective::ParseAndRemoveFragmentDirectiveFromFragmentString(
7859 aState.mNewHash, &aState.mTextDirectives, aLoadState->URI());
7860
7861 if (currentURI && NS_SUCCEEDED(rvURINew)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rvURINew)), 1)))) {
7862 nsresult rvURIOld = currentURI->GetRef(aState.mCurrentHash);
7863 if (NS_SUCCEEDED(rvURIOld)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rvURIOld)), 1)))) {
7864 rvURIOld = currentURI->GetHasRef(&aState.mCurrentURIHasRef);
7865 }
7866 if (NS_SUCCEEDED(rvURIOld)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rvURIOld)), 1)))) {
7867 if (NS_FAILED(currentURI->EqualsExceptRef(aLoadState->URI(),((bool)(__builtin_expect(!!(NS_FAILED_impl(currentURI->EqualsExceptRef
(aLoadState->URI(), &aState.mSameExceptHashes))), 0)))
7868 &aState.mSameExceptHashes))((bool)(__builtin_expect(!!(NS_FAILED_impl(currentURI->EqualsExceptRef
(aLoadState->URI(), &aState.mSameExceptHashes))), 0)))
) {
7869 aState.mSameExceptHashes = false;
7870 }
7871 }
7872 }
7873
7874 if (!aState.mSameExceptHashes && currentURI && NS_SUCCEEDED(rvURINew)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rvURINew)), 1)))) {
7875 // Maybe aLoadState->URI() came from the exposable form of currentURI?
7876 nsCOMPtr<nsIURI> currentExposableURI =
7877 nsIOService::CreateExposableURI(currentURI);
7878 nsresult rvURIOld = currentExposableURI->GetRef(aState.mCurrentHash);
7879 if (NS_SUCCEEDED(rvURIOld)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rvURIOld)), 1)))) {
7880 rvURIOld = currentExposableURI->GetHasRef(&aState.mCurrentURIHasRef);
7881 }
7882 if (NS_SUCCEEDED(rvURIOld)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rvURIOld)), 1)))) {
7883 if (NS_FAILED(currentExposableURI->EqualsExceptRef(((bool)(__builtin_expect(!!(NS_FAILED_impl(currentExposableURI
->EqualsExceptRef( aLoadState->URI(), &aState.mSameExceptHashes
))), 0)))
7884 aLoadState->URI(), &aState.mSameExceptHashes))((bool)(__builtin_expect(!!(NS_FAILED_impl(currentExposableURI
->EqualsExceptRef( aLoadState->URI(), &aState.mSameExceptHashes
))), 0)))
) {
7885 aState.mSameExceptHashes = false;
7886 }
7887 // HTTPS-Only Mode upgrades schemes from http to https in Necko, hence we
7888 // have to perform a special check here to avoid an actual navigation. If
7889 // HTTPS-Only Mode is enabled and the two URIs are same-origin (modulo the
7890 // fact that the new URI is currently http), then set mSameExceptHashes to
7891 // true and only perform a fragment navigation.
7892 if (!aState.mSameExceptHashes) {
7893 if (nsCOMPtr<nsIChannel> docChannel = GetCurrentDocChannel()) {
7894 nsCOMPtr<nsILoadInfo> docLoadInfo = docChannel->LoadInfo();
7895 nsHTTPSOnlyUtils::UpgradeMode upgradeMode =
7896 nsHTTPSOnlyUtils::GetUpgradeMode(docLoadInfo);
7897 if (!docLoadInfo->GetLoadErrorPage() &&
7898 (upgradeMode == nsHTTPSOnlyUtils::HTTPS_ONLY_MODE ||
7899 upgradeMode == nsHTTPSOnlyUtils::HTTPS_FIRST_MODE) &&
7900 nsHTTPSOnlyUtils::IsHttpDowngrade(currentExposableURI,
7901 aLoadState->URI())) {
7902 uint32_t status = docLoadInfo->GetHttpsOnlyStatus();
7903 if ((status &
7904 (nsILoadInfo::HTTPS_ONLY_UPGRADED_LISTENER_REGISTERED |
7905 nsILoadInfo::HTTPS_ONLY_UPGRADED_HTTPS_FIRST)) &&
7906 !(status & nsILoadInfo::HTTPS_ONLY_EXEMPT)) {
7907 // At this point the requested URI is for sure a fragment
7908 // navigation via HTTP and HTTPS-Only mode or HTTPS-First is
7909 // enabled. Also it is not interfering the upgrade order of
7910 // https://searchfox.org/firefox-main/source/netwerk/base/nsNetUtil.cpp#2948-2953.
7911 // Since we are on an HTTPS site the fragment
7912 // navigation should also be an HTTPS.
7913 // For that reason we should upgrade the URI to HTTPS.
7914 aState.mSecureUpgradeURI = true;
7915 aState.mSameExceptHashes = true;
7916 }
7917 }
7918 }
7919 }
7920 }
7921 }
7922
7923 if (mActiveEntry && aLoadState->LoadIsFromSessionHistory()) {
7924 aState.mHistoryNavBetweenSameDoc = mActiveEntry->SharesDocumentWith(
7925 aLoadState->GetLoadingSessionHistoryInfo()->mInfo);
7926 }
7927
7928 // Two URIs are identical if they're same except hashes, they both have
7929 // hashes, and their hashes are the same.
7930 aState.mIdentical = aState.mSameExceptHashes &&
7931 (aState.mNewURIHasRef == aState.mCurrentURIHasRef) &&
7932 aState.mCurrentHash.Equals(aState.mNewHash);
7933
7934 // A same document navigation happens when we navigate between two SHEntries
7935 // for the same document. We do a same document navigation under two
7936 // circumstances. Either
7937 //
7938 // a) we're navigating between two different SHEntries which share a
7939 // document, or
7940 //
7941 // b) we're navigating to a new shentry whose URI differs from the
7942 // current URI only in its hash, the new hash is non-empty, and
7943 // we're not doing a POST.
7944 //
7945 // The restriction that the SHEntries in (a) must be different ensures
7946 // that history.go(0) and the like trigger full refreshes, rather than
7947 // same document navigations.
7948 if (aLoadState->LoadIsFromSessionHistory()) {
7949 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 history nav %p "
"NavBetweenSameDoc=%d", this, aState.mHistoryNavBetweenSameDoc
); } } while (0)
7950 ("nsDocShell::IsSameDocumentNavigation history nav %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::IsSameDocumentNavigation history nav %p "
"NavBetweenSameDoc=%d", this, aState.mHistoryNavBetweenSameDoc
); } } while (0)
7951 "NavBetweenSameDoc=%d",do { const ::mozilla::LogModule* moz_real_module = gSHLog; if
((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "nsDocShell::IsSameDocumentNavigation history nav %p "
"NavBetweenSameDoc=%d", this, aState.mHistoryNavBetweenSameDoc
); } } while (0)
7952 this, aState.mHistoryNavBetweenSameDoc))do { const ::mozilla::LogModule* moz_real_module = gSHLog; if
((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "nsDocShell::IsSameDocumentNavigation history nav %p "
"NavBetweenSameDoc=%d", this, aState.mHistoryNavBetweenSameDoc
); } } while (0)
;
7953 if (!aState.mHistoryNavBetweenSameDoc ||
7954 aLoadState->GetLoadingSessionHistoryInfo()->mLoadingCurrentEntry) {
7955 return false;
7956 }
7957 } else {
7958 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 new shentry %p "
"!PostDataStream: %s mSameExceptHashes: %s mNewURIHasRef: %s"
, this, !aLoadState->PostDataStream() ? "true" : "false", aState
.mSameExceptHashes ? "true" : "false", aState.mNewURIHasRef ?
"true" : "false"); } } while (0)
7959 ("nsDocShell::IsSameDocumentNavigation new shentry %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::IsSameDocumentNavigation new shentry %p "
"!PostDataStream: %s mSameExceptHashes: %s mNewURIHasRef: %s"
, this, !aLoadState->PostDataStream() ? "true" : "false", aState
.mSameExceptHashes ? "true" : "false", aState.mNewURIHasRef ?
"true" : "false"); } } while (0)
7960 "!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 new shentry %p "
"!PostDataStream: %s mSameExceptHashes: %s mNewURIHasRef: %s"
, this, !aLoadState->PostDataStream() ? "true" : "false", aState
.mSameExceptHashes ? "true" : "false", aState.mNewURIHasRef ?
"true" : "false"); } } while (0)
7961 this, !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 new shentry %p "
"!PostDataStream: %s mSameExceptHashes: %s mNewURIHasRef: %s"
, this, !aLoadState->PostDataStream() ? "true" : "false", aState
.mSameExceptHashes ? "true" : "false", aState.mNewURIHasRef ?
"true" : "false"); } } while (0)
7962 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 new shentry %p "
"!PostDataStream: %s mSameExceptHashes: %s mNewURIHasRef: %s"
, this, !aLoadState->PostDataStream() ? "true" : "false", aState
.mSameExceptHashes ? "true" : "false", aState.mNewURIHasRef ?
"true" : "false"); } } while (0)
7963 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 new shentry %p "
"!PostDataStream: %s mSameExceptHashes: %s mNewURIHasRef: %s"
, this, !aLoadState->PostDataStream() ? "true" : "false", aState
.mSameExceptHashes ? "true" : "false", aState.mNewURIHasRef ?
"true" : "false"); } } while (0)
;
7964 if (aLoadState->PostDataStream() || !aState.mSameExceptHashes ||
7965 !aState.mNewURIHasRef) {
7966 return false;
7967 }
7968 }
7969
7970 // The navigation looks same-document, but check if documentPrincipal,
7971 // mCurrentURI, and new URI are same origin to avoid failing
7972 // UpdateDocumentURI checks in the parent (bug 1783504).
7973 nsCOMPtr<nsIURI> newURI = aLoadState->URI();
7974 if (aState.mSecureUpgradeURI) {
7975 // We need to upgrade the new URI from http: to https:
7976 nsresult rv =
7977 NS_GetSecureUpgradedURI(aLoadState->URI(), getter_AddRefs(newURI));
7978 NS_ENSURE_SUCCESS(rv, false)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "false", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "./../../../docshell/base/nsDocShell.cpp"
, 7978); return false; } } while (false)
;
7979 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)
7980 ("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)
;
7981 }
7982 RefPtr<Document> doc = GetExtantDocument();
7983 NS_ENSURE_TRUE(doc, false)do { if ((__builtin_expect(!!(!(doc)), 0))) { NS_DebugBreak(NS_DEBUG_WARNING
, "NS_ENSURE_TRUE(" "doc" ") failed", nullptr, "./../../../docshell/base/nsDocShell.cpp"
, 7983); return false; } } while (false)
;
7984 if (!IsSamePrincipalForDocumentURI(doc->NodePrincipal(), mCurrentURI,
7985 newURI)) {
7986 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, possible "
"violation of the same origin policy", this); } } while (0)
7987 ("nsDocShell::IsSameDocumentNavigation %p false, possible "do { const ::mozilla::LogModule* moz_real_module = 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, possible "
"violation of the same origin policy", this); } } while (0)
7988 "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::IsSameDocumentNavigation %p false, possible "
"violation of the same origin policy", this); } } while (0)
7989 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, possible "
"violation of the same origin policy", this); } } while (0)
;
7990 return false;
7991 }
7992
7993 return true;
7994}
7995
7996nsresult nsDocShell::HandleSameDocumentNavigation(
7997 nsDocShellLoadState* aLoadState, SameDocumentNavigationState& aState) {
7998 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)
7999 ("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)
8000 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)
8001 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)
;
8002
8003 RefPtr<Document> doc = GetDocument();
8004 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"
, 8004); return NS_ERROR_FAILURE; } } while (false)
;
8005
8006 nsCOMPtr<nsIURI> currentURI = mCurrentURI;
8007
8008 // We need to upgrade the new URI from http: to https:
8009 nsCOMPtr<nsIURI> newURI = aLoadState->URI();
8010 if (aState.mSecureUpgradeURI) {
8011 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(); })
;
8012 }
8013
8014 // https://html.spec.whatwg.org/#navigate-fragid
8015 // Step 2
8016 RefPtr<nsIStructuredCloneContainer> destinationNavigationAPIState =
8017 mActiveEntry ? mActiveEntry->GetNavigationAPIState() : nullptr;
8018 // Step 3
8019 if (auto* navigationAPIState = aLoadState->GetNavigationAPIState()) {
8020 destinationNavigationAPIState = navigationAPIState;
8021 }
8022
8023 if (nsCOMPtr<nsPIDOMWindowInner> window = doc->GetInnerWindow();
8024 window && !aState.mHistoryNavBetweenSameDoc) {
8025 // https://html.spec.whatwg.org/#navigate-fragid
8026 // Step 1
8027 if (RefPtr<Navigation> navigation = window->Navigation()) {
8028 AutoJSAPI jsapi;
8029 if (jsapi.Init(window)) {
8030 RefPtr<Element> sourceElement = aLoadState->GetSourceElement();
8031 // Step 4
8032 RefPtr apiMethodTracker = aLoadState->GetNavigationAPIMethodTracker();
8033 bool shouldContinue = navigation->FirePushReplaceReloadNavigateEvent(
8034 jsapi.cx(), aLoadState->GetNavigationType(), newURI,
8035 /* aIsSameDocument */ true,
8036 Some(aLoadState->UserNavigationInvolvement()), sourceElement,
8037 /* aFormDataEntryList */ nullptr,
8038 /* aNavigationAPIState */ destinationNavigationAPIState,
8039 /* aClassicHistoryAPIState */ nullptr, apiMethodTracker);
8040
8041 // Step 5
8042 if (!shouldContinue) {
8043 return NS_OK;
8044 }
8045 }
8046 }
8047 }
8048
8049 doc->DoNotifyPossibleTitleChange();
8050
8051 // Store the pending uninvoked directives if it is a same document
8052 // navigation. We need to set it here, in case the navigation happens before
8053 // the document has actually finished loading.
8054 doc->FragmentDirective()->SetTextDirectives(
8055 std::move(aState.mTextDirectives));
8056
8057#ifdef DEBUG1
8058 if (aState.mSameExceptHashes) {
8059 bool sameExceptHashes = false;
8060 currentURI->EqualsExceptRef(newURI, &sameExceptHashes);
8061 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", 8061); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "sameExceptHashes" ")"); do { MOZ_CrashSequence
(__null, 8061); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
8062 }
8063#endif
8064 const nsCOMPtr<nsILoadInfo> loadInfo =
8065 doc->GetChannel() ? doc->GetChannel()->LoadInfo() : nullptr;
8066 if (loadInfo) {
8067 loadInfo->SetIsSameDocumentNavigation(true);
8068 }
8069 // Save the position of the scrollers.
8070 nsPoint scrollPos = GetCurScrollPos();
8071
8072 // Reset mLoadType to its original value once we exit this block, because this
8073 // same document navigation might have started after a normal, network load,
8074 // and we don't want to clobber its load type. See bug 737307.
8075 Maybe<AutoRestore<uint32_t>> loadTypeResetter;
8076 if (StaticPrefs::
8077 docshell_shistory_sameDocumentNavigationOverridesLoadType() &&
8078 !doc->NodePrincipal()->IsURIInPrefList(
8079 "docshell.shistory.sameDocumentNavigationOverridesLoadType."
8080 "forceDisable")) {
8081 loadTypeResetter.emplace(mLoadType);
8082 }
8083 if (JustStartedNetworkLoad() && !loadTypeResetter.isSome()) {
8084 loadTypeResetter.emplace(mLoadType);
8085 }
8086
8087 // If a non-same-document-navigation (i.e., a network load) is pending, make
8088 // this a replacement load, so that we don't add a SHEntry here and the
8089 // network load goes into the SHEntry it expects to.
8090 if (JustStartedNetworkLoad() && (aLoadState->LoadType() & LOAD_CMD_NORMAL)) {
8091 mLoadType = LOAD_NORMAL_REPLACE;
8092 } else {
8093 mLoadType = aLoadState->LoadType();
8094 }
8095
8096 mURIResultedInDocument = true;
8097
8098 // we need to assign aLoadState->SHEntry() to mLoadingEntry right here, so
8099 // that on History loads, SetCurrentURI() called from OnNewURI() will send
8100 // proper onLocationChange() notifications to the browser to update
8101 // back/forward buttons.
8102 UniquePtr<mozilla::dom::LoadingSessionHistoryInfo> oldLoadingEntry;
8103 mLoadingEntry.swap(oldLoadingEntry);
8104 if (aLoadState->GetLoadingSessionHistoryInfo()) {
8105 mLoadingEntry = MakeUnique<LoadingSessionHistoryInfo>(
8106 *aLoadState->GetLoadingSessionHistoryInfo());
8107 mNeedToReportActiveAfterLoadingBecomesActive = false;
8108 }
8109
8110 // Set the doc's URI according to the new history entry's URI.
8111 doc->SetDocumentURI(newURI);
8112
8113 /* This is a anchor traversal within the same page.
8114 * call OnNewURI() so that, this traversal will be
8115 * recorded in session and global history.
8116 */
8117 nsCOMPtr<nsIPrincipal> newURITriggeringPrincipal, newURIPrincipalToInherit,
8118 newURIPartitionedPrincipalToInherit;
8119 nsCOMPtr<nsIPolicyContainer> newPolicyContainer;
8120 if (mActiveEntry) {
8121 newURITriggeringPrincipal = mActiveEntry->GetTriggeringPrincipal();
8122 newURIPrincipalToInherit = mActiveEntry->GetPrincipalToInherit();
8123 newURIPartitionedPrincipalToInherit =
8124 mActiveEntry->GetPartitionedPrincipalToInherit();
8125 newPolicyContainer = mActiveEntry->GetPolicyContainer();
8126 } else {
8127 newURITriggeringPrincipal = aLoadState->TriggeringPrincipal();
8128 newURIPrincipalToInherit = doc->NodePrincipal();
8129 newURIPartitionedPrincipalToInherit = doc->PartitionedPrincipal();
8130 newPolicyContainer = doc->GetPolicyContainer();
8131 }
8132
8133 uint32_t locationChangeFlags = GetSameDocumentNavigationFlags(newURI);
8134
8135 // Pass true for aCloneSHChildren, since we're not
8136 // changing documents here, so all of our subframes are
8137 // still relevant to the new session history entry.
8138 //
8139 // It also makes OnNewURI(...) set LOCATION_CHANGE_SAME_DOCUMENT
8140 // flag on firing onLocationChange(...).
8141 // Anyway, aCloneSHChildren param is simply reflecting
8142 // doSameDocumentNavigation in this scope.
8143 //
8144 // Note: we'll actually fire onLocationChange later, in order to preserve
8145 // ordering of HistoryCommit() in the parent vs onLocationChange (bug
8146 // 1668126)
8147 bool locationChangeNeeded = OnNewURI(
8148 newURI, nullptr, newURITriggeringPrincipal, newURIPrincipalToInherit,
8149 newURIPartitionedPrincipalToInherit, newPolicyContainer, true, true);
8150
8151 nsCOMPtr<nsIInputStream> postData;
8152 nsCOMPtr<nsIReferrerInfo> referrerInfo;
8153 uint32_t cacheKey = 0;
8154
8155 bool scrollRestorationIsManual = false;
8156 if (mActiveEntry) {
8157 mActiveEntry->SetScrollPosition(scrollPos.x, scrollPos.y);
8158 if (mBrowsingContext) {
8159 CollectWireframe();
8160 if (XRE_IsParentProcess()) {
8161 SessionHistoryEntry* entry =
8162 mBrowsingContext->Canonical()->GetActiveSessionHistoryEntry();
8163 if (entry) {
8164 entry->SetScrollPosition(scrollPos.x, scrollPos.y);
8165 }
8166 } else {
8167 (void)ContentChild::GetSingleton()
8168 ->SendSessionHistoryEntryScrollPosition(mBrowsingContext,
8169 scrollPos.x, scrollPos.y);
8170 }
8171 }
8172 }
8173 if (mLoadingEntry && !mLoadingEntry->mLoadIsFromSessionHistory) {
8174 // If we're not doing a history load, scroll restoration
8175 // should be inherited from the previous session history entry.
8176 // XXX This needs most probably tweaks once fragment navigation is
8177 // fixed to work with session-history-in-parent.
8178 SetScrollRestorationIsManualOnHistoryEntry(scrollRestorationIsManual);
8179 }
8180
8181 // If we're doing a history load, use its scroll restoration state.
8182 if (aLoadState->LoadIsFromSessionHistory()) {
8183 scrollRestorationIsManual = aLoadState->GetLoadingSessionHistoryInfo()
8184 ->mInfo.GetScrollRestorationIsManual();
8185 }
8186
8187 /* Make a new mActiveEntry. This will either be a new entry created
8188 * by OnNewURI() for normal loads or aLoadState->SHEntry() for history
8189 * loads.
8190 */
8191 if (aLoadState->LoadIsFromSessionHistory()) {
8192 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)
8193 ("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)
8194 "%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)
8195 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)
;
8196
8197 nsCOMPtr<nsILayoutHistoryState> currentLayoutHistoryState;
8198 if (mActiveEntry) {
8199 currentLayoutHistoryState = mActiveEntry->GetLayoutHistoryState();
8200 }
8201
8202 UniquePtr<SessionHistoryInfo> previousActiveEntry(mActiveEntry.release());
8203 mActiveEntry = MakeUnique<SessionHistoryInfo>(mLoadingEntry->mInfo);
8204 if (currentLayoutHistoryState) {
8205 // Restore the existing nsILayoutHistoryState object, since it is
8206 // possibly being used by the layout. When doing a new load, the
8207 // shared state is copied from the existing active entry, so this
8208 // special case is needed only with the history loads.
8209 mActiveEntry->SetLayoutHistoryState(currentLayoutHistoryState);
8210 }
8211
8212 if (cacheKey != 0) {
8213 mActiveEntry->SetCacheKey(cacheKey);
8214 }
8215
8216 // We're passing in mCurrentURI, which could be null. SessionHistoryCommit
8217 // does require a non-null uri if this is for a refresh load of the same
8218 // URI, but in that case mCurrentURI won't be null here.
8219 mBrowsingContext->SessionHistoryCommit(
8220 *mLoadingEntry, mLoadType, mCurrentURI, previousActiveEntry.get(), true,
8221 /* No expiration update on the same document loads*/
8222 false, cacheKey);
8223 // FIXME Need to set postdata.
8224
8225 // Set the title for the SH entry for this target url so that
8226 // SH menus in go/back/forward buttons won't be empty for this.
8227 // Note, when session history lives in the parent process, this does not
8228 // update the title there.
8229 SetTitleOnHistoryEntry(false);
8230 } else {
8231 Maybe<bool> scrollRestorationIsManual;
8232 if (mActiveEntry) {
8233 scrollRestorationIsManual.emplace(
8234 mActiveEntry->GetScrollRestorationIsManual());
8235
8236 // Get the postdata, page ident and referrer info from the current page,
8237 // if the new load is being done via normal means. Note that "normal
8238 // means" can be checked for just by checking for LOAD_CMD_NORMAL, given
8239 // the loadType and allowScroll check above -- it filters out some
8240 // LOAD_CMD_NORMAL cases that we wouldn't want here.
8241 if (aLoadState->LoadType() & LOAD_CMD_NORMAL) {
8242 postData = mActiveEntry->GetPostData();
8243 cacheKey = mActiveEntry->GetCacheKey();
8244 referrerInfo = mActiveEntry->GetReferrerInfo();
8245 }
8246 }
8247
8248 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)
8249 ("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)
8250 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)
;
8251 UniquePtr<SessionHistoryInfo> previousActiveEntry(mActiveEntry.release());
8252 if (previousActiveEntry) {
8253 mActiveEntry =
8254 MakeUnique<SessionHistoryInfo>(*previousActiveEntry, newURI);
8255 } else {
8256 mActiveEntry = MakeUnique<SessionHistoryInfo>(
8257 newURI, newURITriggeringPrincipal, newURIPrincipalToInherit,
8258 newURIPartitionedPrincipalToInherit, newPolicyContainer,
8259 mContentTypeHint);
8260 }
8261
8262 // Save the postData obtained from the previous page in to the session
8263 // history entry created for the anchor page, so that any history load of
8264 // the anchor page will restore the appropriate postData.
8265 if (postData) {
8266 mActiveEntry->SetPostData(postData);
8267 }
8268
8269 // Make sure we won't just repost without hitting the
8270 // cache first
8271 if (cacheKey != 0) {
8272 mActiveEntry->SetCacheKey(cacheKey);
8273 }
8274
8275 // As the document has not changed, the referrer info hasn't changed too,
8276 // so we can just copy it over.
8277 if (referrerInfo) {
8278 mActiveEntry->SetReferrerInfo(referrerInfo);
8279 }
8280
8281 // Set the title for the SH entry for this target url so that
8282 // SH menus in go/back/forward buttons won't be empty for this.
8283 mActiveEntry->SetTitle(mTitle);
8284
8285 if (scrollRestorationIsManual.isSome()) {
8286 mActiveEntry->SetScrollRestorationIsManual(
8287 scrollRestorationIsManual.value());
8288 }
8289
8290 if (destinationNavigationAPIState) {
8291 mActiveEntry->SetNavigationAPIState(destinationNavigationAPIState);
8292 }
8293
8294 if (LOAD_TYPE_HAS_FLAGS(mLoadType, LOAD_FLAGS_REPLACE_HISTORY)((mLoadType) & ((LOAD_FLAGS_REPLACE_HISTORY) << 16)
)
) {
8295 if (previousActiveEntry) {
8296 mActiveEntry->NavigationKey() = previousActiveEntry->NavigationKey();
8297 }
8298 mBrowsingContext->ReplaceActiveSessionHistoryEntry(mActiveEntry.get());
8299 } else {
8300 mBrowsingContext->IncrementHistoryEntryCountForBrowsingContext();
8301 // FIXME We should probably just compute mChildOffset in the parent
8302 // instead of passing it over IPC here.
8303 mBrowsingContext->SetActiveSessionHistoryEntry(
8304 Some(scrollPos), mActiveEntry.get(), previousActiveEntry.get(),
8305 mLoadType, cacheKey);
8306 // FIXME Do we need to update mPreviousEntryIndex and mLoadedEntryIndex?
8307 }
8308 }
8309
8310 if (locationChangeNeeded) {
8311 FireOnLocationChange(this, nullptr, newURI, locationChangeFlags);
8312 }
8313
8314 /* Restore the original LSHE if we were loading something
8315 * while same document navigation was initiated.
8316 */
8317 mLoadingEntry.swap(oldLoadingEntry);
8318
8319 /* Set the title for the Global History entry for this anchor url.
8320 */
8321 UpdateGlobalHistoryTitle(newURI);
8322
8323 SetDocCurrentStateObj(mActiveEntry.get());
8324
8325 // Inform the favicon service that the favicon for oldURI also
8326 // applies to newURI.
8327 CopyFavicon(currentURI, newURI, UsePrivateBrowsing());
8328
8329 RefPtr<nsGlobalWindowOuter> scriptGlobal = mScriptGlobal;
8330 nsCOMPtr<nsPIDOMWindowInner> win =
8331 scriptGlobal ? scriptGlobal->GetCurrentInnerWindow() : nullptr;
8332
8333 // https://html.spec.whatwg.org/#scroll-to-fragid
8334 // 14. Update document for history step application given navigable's
8335 // active document, historyEntry, true, scriptHistoryIndex,
8336 // scriptHistoryLength, and historyHandling.
8337 if (RefPtr navigation = win ? win->Navigation() : nullptr) {
8338 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)
8339 ("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)
8340 "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)
8341 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)
;
8342 // https://html.spec.whatwg.org/#update-document-for-history-step-application
8343 // 6.4.2. Update the navigation API entries for a same-document
8344 // navigation given navigation, entry, and navigationType.
8345 navigation->UpdateEntriesForSameDocumentNavigation(
8346 mActiveEntry.get(),
8347 NavigationUtils::NavigationTypeFromLoadType(mLoadType).valueOr(
8348 NavigationType::Push));
8349 }
8350
8351 // The check for uninvoked directives must come before ScrollToAnchor() is
8352 // called.
8353 const bool hasTextDirectives =
8354 doc->FragmentDirective()->HasUninvokedDirectives();
8355
8356 // https://html.spec.whatwg.org/#scroll-to-fragid
8357 // 15. Scroll to the fragment given navigable's active document.
8358
8359 // ScrollToAnchor doesn't necessarily cause us to scroll the window;
8360 // the function decides whether a scroll is appropriate based on the
8361 // arguments it receives. But even if we don't end up scrolling,
8362 // ScrollToAnchor performs other important tasks, such as informing
8363 // the presShell that we have a new hash. See bug 680257.
8364 nsresult rv = ScrollToAnchor(aState.mCurrentURIHasRef, aState.mNewURIHasRef,
8365 aState.mNewHash, aLoadState->LoadType());
8366 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"
, 8366); return rv; } } while (false)
;
8367
8368 /* restore previous position of scroller(s), if we're moving
8369 * back in history (bug 59774)
8370 */
8371 nscoord bx = 0;
8372 nscoord by = 0;
8373 bool needsScrollPosUpdate = false;
8374 if (mActiveEntry &&
8375 (aLoadState->LoadType() == LOAD_HISTORY ||
8376 aLoadState->LoadType() == LOAD_RELOAD_NORMAL) &&
8377 !scrollRestorationIsManual) {
8378 needsScrollPosUpdate = true;
8379 mActiveEntry->GetScrollPosition(&bx, &by);
8380 }
8381
8382 // Dispatch the popstate and hashchange events, as appropriate.
8383 //
8384 // The event dispatch below can cause us to re-enter script and
8385 // destroy the docshell, nulling out mScriptGlobal. Hold a stack
8386 // reference to avoid null derefs. See bug 914521.
8387 if (win) {
8388 // Fire a hashchange event URIs differ, and only in their hashes.
8389 // If the fragment contains a directive, compare hasRef.
8390 bool doHashchange = aState.mSameExceptHashes &&
8391 (!aState.mCurrentHash.Equals(aState.mNewHash) ||
8392 (hasTextDirectives &&
8393 aState.mCurrentURIHasRef != aState.mNewURIHasRef));
8394
8395 // We enqueue the hashchange event first before dispatching popstate,
8396 // differing from the spec.
8397 // See: https://github.com/whatwg/html/issues/12190
8398 if (doHashchange) {
8399 // Note that currentURI hasn't changed because it's on the
8400 // stack, so we can just use it directly as the old URI.
8401 win->DispatchAsyncHashchange(currentURI, newURI);
8402 }
8403
8404 if (aState.mHistoryNavBetweenSameDoc || doHashchange) {
8405 win->DispatchSyncPopState();
8406 }
8407
8408 if (needsScrollPosUpdate && win->HasActiveDocument()) {
8409 SetCurScrollPosEx(bx, by);
8410 }
8411 }
8412
8413 return NS_OK;
8414}
8415
8416static bool NavigationShouldTakeFocus(nsDocShell* aDocShell,
8417 nsDocShellLoadState* aLoadState) {
8418 if (!aLoadState->AllowFocusMove()) {
8419 return false;
8420 }
8421 if (!aLoadState->HasValidUserGestureActivation()) {
8422 return false;
8423 }
8424 const auto& sourceBC = aLoadState->SourceBrowsingContext();
8425 if (!sourceBC || !sourceBC->IsActive()) {
8426 // If the navigation didn't come from a foreground tab, then we don't steal
8427 // focus.
8428 return false;
8429 }
8430 auto* bc = aDocShell->GetBrowsingContext();
8431 if (sourceBC.get() == bc) {
8432 // If it comes from the same tab / frame, don't steal focus either.
8433 return false;
8434 }
8435 auto* fm = nsFocusManager::GetFocusManager();
8436 if (fm && bc->IsActive() && fm->IsInActiveWindow(bc)) {
8437 // If we're already on the foreground tab of the foreground window, then we
8438 // don't need to do this. This helps to e.g. not steal focus from the
8439 // browser chrome unnecessarily.
8440 return false;
8441 }
8442 if (auto* doc = aDocShell->GetExtantDocument()) {
8443 if (doc->IsInitialDocument()) {
8444 // If we're the initial load for the browsing context, the browser
8445 // chrome determines what to focus. This is important because the
8446 // browser chrome may want to e.g focus the url-bar
8447 return false;
8448 }
8449 }
8450 // Take loadDivertedInBackground into account so the behavior would be the
8451 // same as how the tab first opened.
8452 return !Preferences::GetBool("browser.tabs.loadDivertedInBackground", false);
8453}
8454
8455uint32_t nsDocShell::GetLoadTypeForFormSubmission(
8456 BrowsingContext* aTargetBC, nsDocShellLoadState* aLoadState) {
8457 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"
, 8457); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->IsFormSubmission()"
")"); do { MOZ_CrashSequence(__null, 8457); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8458
8459 // https://html.spec.whatwg.org/#form-submission-algorithm
8460 // 22. Let historyHandling be "push".
8461 // 23. If form document equals targetNavigable's active document, and
8462 // form document has not yet completely loaded, then set
8463 // historyHandling to "replace".
8464 return GetBrowsingContext() == aTargetBC && !mEODForCurrentDocument
8465 ? LOAD_NORMAL_REPLACE
8466 : LOAD_LINK;
8467}
8468
8469static void MaybeConvertToReplaceLoad(nsDocShellLoadState* aLoadState,
8470 Document* aExtantDocument,
8471 bool aIdenticalURI,
8472 bool aHasActiveEntry) {
8473 // MaybeConvertToReplaceLoad implements steps 12 and 13 of #navigate, but
8474 // since we're not yet using historyBehavior for all types of loads and
8475 // configurations, we need to sometimes bail and revert to the old way of
8476 // handling push to replace load conversion. The different cases we can't
8477 // handle are:
8478 //
8479 // * When we don't have an active document
8480 // * When a document doesn't yet have a session history entry
8481 // * When we don't use historyBehavior
8482 if (!aExtantDocument || !aHasActiveEntry || !aLoadState->HistoryBehavior()) {
8483 aLoadState->ResetHistoryBehavior();
8484 return;
8485 }
8486
8487 bool convertToReplaceLoad = aLoadState->NeedsCompletelyLoadedDocument() &&
8488 !aExtantDocument->IsCompletelyLoaded();
8489 if (const auto& historyBehavior = aLoadState->HistoryBehavior();
8490 !convertToReplaceLoad && historyBehavior &&
8491 *historyBehavior == NavigationHistoryBehavior::Auto) {
8492 convertToReplaceLoad = aIdenticalURI;
8493 if (convertToReplaceLoad && aExtantDocument->GetPrincipal()) {
8494 aExtantDocument->GetPrincipal()->Equals(aLoadState->TriggeringPrincipal(),
8495 &convertToReplaceLoad);
8496 }
8497 } else if (aLoadState->HistoryBehavior() ==
8498 Some(NavigationHistoryBehavior::Replace)) {
8499 // This load is supposed to be a replace, regardless of completely loaded.
8500 // This can happen for form submissions since the planned form
8501 // navigation might be queued before the document is completely loaded
8502 // and then actually run after it is completely loaded:
8503 // https://html.spec.whatwg.org/#concept-form-submit
8504 convertToReplaceLoad = true;
8505 }
8506
8507 convertToReplaceLoad =
8508 convertToReplaceLoad || nsContentUtils::NavigationMustBeAReplace(
8509 *aLoadState->URI(), *aExtantDocument);
8510
8511 if (convertToReplaceLoad) {
8512 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)
8513 "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)
8514 *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)
8515 (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)
8516 !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)
8517 *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)
8518 ? "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)
8519 : "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)
;
8520 // There is no replace variant for LOAD_LINK, so we convert it to
8521 // LOAD_NORMAL_REPLACE just like in nsDocShell::OnNewURI.
8522 if (aLoadState->LoadType() == LOAD_LINK) {
8523 aLoadState->SetLoadType(LOAD_NORMAL_REPLACE);
8524 } else {
8525 aLoadState->SetLoadType(
8526 MaybeAddLoadFlags(aLoadState->LoadType(),
8527 nsIWebNavigation::LOAD_FLAGS_REPLACE_HISTORY));
8528 }
8529 aLoadState->SetHistoryBehavior(NavigationHistoryBehavior::Replace);
8530 } else {
8531 aLoadState->SetHistoryBehavior(NavigationHistoryBehavior::Push);
8532 }
8533}
8534
8535// InternalLoad performs several of the steps from
8536// https://html.spec.whatwg.org/#navigate.
8537nsresult nsDocShell::InternalLoad(nsDocShellLoadState* aLoadState,
8538 Maybe<uint32_t> aCacheKey) {
8539 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", 8539); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aLoadState" ") (" "need a load state!" ")"
); do { MOZ_CrashSequence(__null, 8539); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8540 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", 8541); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aLoadState->TriggeringPrincipal()" ") ("
"need a valid TriggeringPrincipal" ")"); do { MOZ_CrashSequence
(__null, 8541); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
8541 "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", 8541); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aLoadState->TriggeringPrincipal()" ") ("
"need a valid TriggeringPrincipal" ")"); do { MOZ_CrashSequence
(__null, 8541); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
8542
8543 if (!aLoadState->TriggeringPrincipal()) {
8544 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", 8544); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "false" ") (" "InternalLoad needs a valid triggeringPrincipal"
")"); do { MOZ_CrashSequence(__null, 8544); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8545 return NS_ERROR_FAILURE;
8546 }
8547 if (NS_WARN_IF(mBrowsingContext->GetPendingInitialization())NS_warn_if_impl(mBrowsingContext->GetPendingInitialization
(), "mBrowsingContext->GetPendingInitialization()", "./../../../docshell/base/nsDocShell.cpp"
, 8547)
) {
8548 return NS_ERROR_NOT_AVAILABLE;
8549 }
8550
8551 const bool shouldTakeFocus = NavigationShouldTakeFocus(this, aLoadState);
8552
8553 mOriginalUriString.Truncate();
8554
8555 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)
8556 ("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)
8557 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)
;
8558
8559 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", 8559); return NS_ERROR_INVALID_ARG
; } } while (false)
;
8560
8561 // Cancel loads coming from Docshells that are being destroyed.
8562 if (mIsBeingDestroyed) {
8563 return NS_ERROR_NOT_AVAILABLE;
8564 }
8565
8566 nsresult rv = EnsureScriptEnvironment();
8567 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
8568 return rv;
8569 }
8570
8571 // If we have a target to move to, do that now.
8572 if (!aLoadState->Target().IsEmpty()) {
8573 return PerformRetargeting(aLoadState);
8574 }
8575
8576 // This is the non-retargeting load path, we've already set the right loadtype
8577 // for form submissions in nsDocShell::OnLinkClickSync.
8578 if (aLoadState->TargetBrowsingContext().IsNull()) {
8579 aLoadState->SetTargetBrowsingContext(GetBrowsingContext());
8580 }
8581
8582 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"
, 8584); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "aLoadState->TargetBrowsingContext() == GetBrowsingContext()"
") (" "Load must be targeting this BrowsingContext" ")"); do
{ MOZ_CrashSequence(__null, 8584); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
8583 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"
, 8584); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "aLoadState->TargetBrowsingContext() == GetBrowsingContext()"
") (" "Load must be targeting this BrowsingContext" ")"); do
{ MOZ_CrashSequence(__null, 8584); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
8584 "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"
, 8584); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "aLoadState->TargetBrowsingContext() == GetBrowsingContext()"
") (" "Load must be targeting this BrowsingContext" ")"); do
{ MOZ_CrashSequence(__null, 8584); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
8585
8586 MOZ_TRY(CheckDisallowedJavascriptLoad(aLoadState))__extension__({ auto mozTryVarTempResult = ::mozilla::ToResult
(CheckDisallowedJavascriptLoad(aLoadState)); if ((__builtin_expect
(!!(mozTryVarTempResult.isErr()), 0))) { return mozTryVarTempResult
.propagateErr(); } mozTryVarTempResult.unwrap(); })
;
8587
8588 // If we don't have a target, we're loading into ourselves, and our load
8589 // delegate may want to intercept that load.
8590 SameDocumentNavigationState sameDocumentNavigationState;
8591 bool sameDocument =
8592 IsSameDocumentNavigation(aLoadState, sameDocumentNavigationState) &&
8593 !aLoadState->GetPendingRedirectedChannel();
8594
8595 if (mLoadType != LOAD_ERROR_PAGE &&
8596 !aLoadState->HasLoadFlags(LOAD_FLAGS_FROM_EXTERNAL)) {
8597 MaybeConvertToReplaceLoad(aLoadState, GetExtantDocument(),
8598 sameDocumentNavigationState.mIdentical,
8599 !!mActiveEntry);
8600 }
8601
8602 // Note: We do this check both here and in BrowsingContext::
8603 // LoadURI/InternalLoad, since document-specific sandbox flags are only
8604 // available in the process triggering the load, and we don't want the target
8605 // process to have to trust the triggering process to do the appropriate
8606 // checks for the BrowsingContext's sandbox flags.
8607 MOZ_TRY(mBrowsingContext->EnsureSourceSandboxAllowsNavigation(aLoadState))__extension__({ auto mozTryVarTempResult = ::mozilla::ToResult
(mBrowsingContext->EnsureSourceSandboxAllowsNavigation(aLoadState
)); if ((__builtin_expect(!!(mozTryVarTempResult.isErr()), 0)
)) { return mozTryVarTempResult.propagateErr(); } mozTryVarTempResult
.unwrap(); })
;
8608 MOZ_TRY(mBrowsingContext->CheckFramebusting(aLoadState))__extension__({ auto mozTryVarTempResult = ::mozilla::ToResult
(mBrowsingContext->CheckFramebusting(aLoadState)); if ((__builtin_expect
(!!(mozTryVarTempResult.isErr()), 0))) { return mozTryVarTempResult
.propagateErr(); } mozTryVarTempResult.unwrap(); })
;
8609
8610 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"
, 8610); return NS_ERROR_UNEXPECTED; } } while (false)
;
8611
8612 rv = CheckLoadingPermissions();
8613 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
8614 return rv;
8615 }
8616
8617 if (mFiredUnloadEvent) {
8618 if (IsOKToLoadURI(aLoadState->URI())) {
8619 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", 8620); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aLoadState->Target().IsEmpty()" ") (" "Shouldn't have a window target here!"
")"); do { MOZ_CrashSequence(__null, 8620); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
8620 "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", 8620); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aLoadState->Target().IsEmpty()" ") (" "Shouldn't have a window target here!"
")"); do { MOZ_CrashSequence(__null, 8620); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8621
8622 // If this is a replace load, make whatever load triggered
8623 // the unload event also a replace load, so we don't
8624 // create extra history entries.
8625 if (LOAD_TYPE_HAS_FLAGS(aLoadState->LoadType(),((aLoadState->LoadType()) & ((LOAD_FLAGS_REPLACE_HISTORY
) << 16))
8626 LOAD_FLAGS_REPLACE_HISTORY)((aLoadState->LoadType()) & ((LOAD_FLAGS_REPLACE_HISTORY
) << 16))
) {
8627 mLoadType = LOAD_NORMAL_REPLACE;
8628 }
8629
8630 // Do this asynchronously
8631 RefPtr ev = MakeRefPtr<InternalLoadEvent>(this, aLoadState);
8632 return Dispatch(ev.forget());
8633 }
8634
8635 // Just ignore this load attempt
8636 return NS_OK;
8637 }
8638
8639 // If we are loading a URI that should inherit a security context (basically
8640 // javascript: at this point), and the caller has said that principal
8641 // inheritance is allowed, there are a few possible cases:
8642 //
8643 // 1) We are provided with the principal to inherit. In that case, we just use
8644 // it.
8645 //
8646 // 2) The load is coming from some other application. In this case we don't
8647 // want to inherit from whatever document we have loaded now, since the
8648 // load is unrelated to it.
8649 //
8650 // 3) It's a load from our application, but does not provide an explicit
8651 // principal to inherit. In that case, we want to inherit the principal of
8652 // our current document, or of our parent document (if any) if we don't
8653 // have a current document.
8654 {
8655 bool inherits;
8656
8657 if (!aLoadState->HasLoadFlags(LOAD_FLAGS_FROM_EXTERNAL) &&
8658 !aLoadState->PrincipalToInherit() &&
8659 (aLoadState->HasInternalLoadFlags(
8660 INTERNAL_LOAD_FLAGS_INHERIT_PRINCIPAL)) &&
8661 NS_SUCCEEDED(nsContentUtils::URIInheritsSecurityContext(((bool)(__builtin_expect(!!(!NS_FAILED_impl(nsContentUtils::URIInheritsSecurityContext
( aLoadState->URI(), &inherits))), 1)))
8662 aLoadState->URI(), &inherits))((bool)(__builtin_expect(!!(!NS_FAILED_impl(nsContentUtils::URIInheritsSecurityContext
( aLoadState->URI(), &inherits))), 1)))
&&
8663 inherits) {
8664 aLoadState->SetPrincipalToInherit(GetInheritedPrincipal(true));
8665 }
8666 // If principalToInherit is still null (e.g. if some of the conditions of
8667 // were not satisfied), then no inheritance of any sort will happen: the
8668 // load will just get a principal based on the URI being loaded.
8669 }
8670
8671 // If this docshell is owned by a frameloader, make sure to cancel
8672 // possible frameloader initialization before loading a new page.
8673 nsCOMPtr<nsIDocShellTreeItem> parent = GetInProcessParentDocshell();
8674 if (parent) {
8675 RefPtr<Document> doc = parent->GetDocument();
8676 if (doc) {
8677 doc->TryCancelFrameLoaderInitialization(this);
8678 }
8679 }
8680
8681 // Before going any further vet loads initiated by external programs.
8682 if (aLoadState->HasLoadFlags(LOAD_FLAGS_FROM_EXTERNAL)) {
8683 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", 8683); AnnotateMozCrashReason
("MOZ_DIAGNOSTIC_ASSERT" "(" "aLoadState->LoadType() == LOAD_NORMAL"
")"); do { MOZ_CrashSequence(__null, 8683); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8684
8685 // Disallow external chrome: loads targetted at content windows
8686 if (aLoadState->URI()->SchemeIs("chrome")) {
8687 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", 8687)
;
8688 return NS_ERROR_FAILURE;
8689 }
8690
8691 // clear the decks to prevent context bleed-through (bug 298255)
8692 rv = CreateAboutBlankDocumentViewer(nullptr, nullptr, nullptr, nullptr,
8693 /* aIsInitialDocument */ false);
8694 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
8695 return NS_ERROR_FAILURE;
8696 }
8697
8698 if (Document* doc = GetDocument()) {
8699 doc->DisallowBFCaching();
8700 }
8701 }
8702
8703 mAllowKeywordFixup = aLoadState->HasInternalLoadFlags(
8704 INTERNAL_LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP);
8705 mURIResultedInDocument = false; // reset the clock...
8706
8707 // If container is an iframe element and will lazy load element steps given
8708 // container returns true, then stop intersection-observing a lazy loading
8709 // element container and set container's lazy load resumption steps to null.
8710 if (IsSubframe()) {
8711 if (auto* iframe = HTMLIFrameElement::FromNodeOrNull(
8712 mBrowsingContext->GetEmbedderElement())) {
8713 // Per spec, reload doesn't cancel lazy loading iframes.
8714 if (!(aLoadState->LoadType() & LOAD_RELOAD_NORMAL)) {
8715 iframe->StopLazyLoading(HTMLIFrameElement::TriggerLoad::No);
8716 }
8717 }
8718 }
8719
8720 CallerType callerType = aLoadState->TriggeringPrincipal()->IsSystemPrincipal()
8721 ? CallerType::System
8722 : CallerType::NonSystem;
8723
8724 if (!aLoadState->LoadIsFromSessionHistory() &&
8725 !mBrowsingContext->CheckNavigationRateLimit(callerType)) {
8726 return NS_OK;
8727 }
8728
8729 // See if this is actually a load between two history entries for the same
8730 // document. If the process fails, or if we successfully navigate within the
8731 // same document, return.
8732 if (sameDocument) {
8733 nsresult rv =
8734 HandleSameDocumentNavigation(aLoadState, sameDocumentNavigationState);
8735 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"
, 8735); return rv; } } while (false)
;
8736 if (shouldTakeFocus) {
8737 mBrowsingContext->Focus(CallerType::System, IgnoreErrors());
8738 }
8739 if (aLoadState->LoadIsFromSessionHistory() &&
8740 (mLoadType & LOAD_CMD_HISTORY) &&
8741 !aLoadState->IsResumingInterceptedNavigation()) {
8742 // We must ensure to not abort intercepted history navigations. See
8743 // https://github.com/whatwg/html/issues/12407
8744 SetOngoingNavigation(Nothing());
8745 }
8746 return rv;
8747 }
8748
8749 // mDocumentViewer->PermitUnload can destroy |this| docShell, which
8750 // causes the next call of CanSavePresentation to crash.
8751 // Hold onto |this| until we return, to prevent a crash from happening.
8752 // (bug#331040)
8753 nsCOMPtr<nsIDocShell> kungFuDeathGrip(this);
8754
8755 // Don't init timing for javascript:, since it generally doesn't
8756 // actually start a load or anything. If it does, we'll init
8757 // timing then, from OnStateChange.
8758
8759 // XXXbz mTiming should know what channel it's for, so we don't
8760 // need this hackery.
8761 const bool isJavaScript = aLoadState->URI()->SchemeIs("javascript");
8762 const bool isExternalProtocol =
8763 nsContentUtils::IsExternalProtocol(aLoadState->URI());
8764 const bool isDownload = !aLoadState->FileName().IsVoid();
8765 const bool toBeReset = !isJavaScript && MaybeInitTiming();
8766
8767 // FIXME(emilio): Should this be done by javascript: uris? What about external
8768 // protocols?
8769 if (mTiming && !isDownload) {
8770 mTiming->NotifyBeforeUnload();
8771 }
8772
8773 // The following steps are from https://html.spec.whatwg.org/#navigate
8774 // 20. Set the ongoing navigation for navigable to navigationId.
8775 SetOngoingNavigation(Some(OngoingNavigation::NavigationID));
8776
8777 // 21. If url's scheme is "javascript":
8778 if (isJavaScript) {
8779 // 21.1 Queue a global task on the navigation and traversal task source
8780 // given navigable's active window to navigate to a javascript: URL
8781 // given navigable, url, historyHandling, sourceSnapshotParams,
8782 // initiatorOriginSnapshot, userInvolvement, cspNavigationType,
8783 // initialInsertion, and navigationId.
8784 // 21.2 Return.
8785 //
8786 // Note: We don't queue a task, so instead we run step 3 of
8787 // https://html.spec.whatwg.org/#navigate-to-a-javascript:-url
8788 // 3. Set the ongoing navigation for targetNavigable to null.
8789 SetOngoingNavigation(Nothing());
8790 }
8791
8792 // 22. If all of the following are true:
8793 // * userInvolvement is not "browser UI";
8794 // * navigable's active document's origin is same origin-domain with
8795 // sourceDocument's origin;
8796 // * navigable's active document's is initial about:blank is false; and
8797 // * url's scheme is a fetch scheme,
8798 // then:
8799 if (RefPtr<Document> document = GetDocument();
8800 !aLoadState->LoadIsFromSessionHistory() && document &&
8801 aLoadState->UserNavigationInvolvement() !=
8802 UserNavigationInvolvement::BrowserUI &&
8803 !document->IsInitialDocument() &&
8804 !NS_IsAboutBlankAllowQueryAndFragment(document->GetDocumentURI()) &&
8805 NS_IsFetchScheme(aLoadState->URI()) &&
8806 document->NodePrincipal()->EqualsConsideringDomain(
8807 aLoadState->TriggeringPrincipal())) {
8808 if (nsCOMPtr<nsPIDOMWindowInner> window = document->GetInnerWindow()) {
8809 // 22.1 Let navigation be navigable's active window's navigation API.
8810 if (RefPtr<Navigation> navigation = window->Navigation()) {
8811 AutoJSAPI jsapi;
8812 if (jsapi.Init(window)) {
8813 RefPtr<Element> sourceElement = aLoadState->GetSourceElement();
8814
8815 // 22.2 Let entryListForFiring be formDataEntryList if
8816 // documentResource is a POST resource; otherwise, null.
8817 RefPtr<FormData> formData = aLoadState->GetFormDataEntryList();
8818
8819 // 22.3 Let navigationAPIStateForFiring be navigationAPIState if
8820 // navigationAPIState is not null; otherwise,
8821 // StructuredSerializeForStorage(undefined).
8822 RefPtr<nsIStructuredCloneContainer> navigationAPIStateForFiring =
8823 aLoadState->GetNavigationAPIState();
8824
8825 nsCOMPtr<nsIURI> destinationURL = aLoadState->URI();
8826 // 22.4 Let continue be the result of firing a push/replace/reload
8827 // navigate event at navigation with navigationType set to
8828 // historyHandling, isSameDocument set to false, userInvolvement
8829 // set to userInvolvement, sourceElement set to sourceElement,
8830 // formDataEntryList set to entryListForFiring, destinationURL
8831 // set to url, navigationAPIState set to
8832 // navigationAPIStateForFiring, and apiMethodTracker set to
8833 // apiMethodTracker.
8834 RefPtr apiMethodTracker = aLoadState->GetNavigationAPIMethodTracker();
8835 bool shouldContinue = navigation->FirePushReplaceReloadNavigateEvent(
8836 jsapi.cx(), aLoadState->GetNavigationType(), destinationURL,
8837 /* aIsSameDocument */ false,
8838 Some(aLoadState->UserNavigationInvolvement()), sourceElement,
8839 formData, navigationAPIStateForFiring,
8840 /* aClassicHistoryAPIState */ nullptr, apiMethodTracker);
8841
8842 // 22.5 If continue is false, then return.
8843 if (!shouldContinue) {
8844 return NS_OK;
8845 }
8846 }
8847 }
8848 }
8849 }
8850
8851 // Check if the page doesn't want to be unloaded. The javascript:
8852 // protocol handler deals with this for javascript: URLs.
8853 // NOTE(emilio): As of this writing, other browsers fire beforeunload for
8854 // external protocols, so keep doing that even though they don't return data
8855 // and thus we won't really unload this...
8856 if (!isJavaScript && !isDownload &&
8857 !aLoadState->NotifiedBeforeUnloadListeners() && mDocumentViewer) {
8858 // Check if request is exempted from HTTPSOnlyMode and if https-first is
8859 // enabled, if so it means:
8860 // * https-first failed to upgrade request to https
8861 // * we already asked for permission to unload and the user accepted
8862 // otherwise we wouldn't be here.
8863 const bool isPrivateWin = GetOriginAttributes().IsPrivateBrowsing();
8864 const uint32_t loadType = aLoadState->LoadType();
8865
8866 // Check if request is a reload.
8867 const bool isHistoryOrReload =
8868 loadType == LOAD_RELOAD_NORMAL ||
8869 loadType == LOAD_RELOAD_BYPASS_CACHE ||
8870 loadType == LOAD_RELOAD_BYPASS_PROXY ||
8871 loadType == LOAD_RELOAD_BYPASS_PROXY_AND_CACHE ||
8872 loadType == LOAD_HISTORY;
8873
8874 // If it isn't a reload, the request already failed to be upgraded and
8875 // https-first is enabled then don't ask the user again for permission to
8876 // unload and just unload.
8877 bool okToUnload;
8878 if (!isHistoryOrReload && aLoadState->IsExemptFromHTTPSFirstMode() &&
8879 nsHTTPSOnlyUtils::GetUpgradeMode(isPrivateWin) ==
8880 nsHTTPSOnlyUtils::HTTPS_FIRST_MODE) {
8881 rv = mDocumentViewer->PermitUnload(
8882 nsIDocumentViewer::PermitUnloadAction::eDontPromptAndUnload,
8883 &okToUnload);
8884 } else {
8885 rv = mDocumentViewer->PermitUnload(&okToUnload);
8886 if (mIsBeingDestroyed) {
8887 // unload handler destroyed this docshell.
8888 return NS_ERROR_NOT_AVAILABLE;
8889 }
8890 }
8891
8892 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && !okToUnload) {
8893 // The user chose not to unload the page, interrupt the
8894 // load.
8895 MaybeResetInitTiming(toBeReset);
8896 return NS_OK;
8897 }
8898 }
8899
8900 if (mTiming && !isDownload) {
8901 mTiming->NotifyUnloadAccepted(mCurrentURI);
8902 }
8903
8904 // In e10s, in the parent process, we refuse to load anything other than
8905 // "safe" resources that we ship or trust enough to give "special" URLs.
8906 // Similar check will be performed by the ParentProcessDocumentChannel if in
8907 // use.
8908 if (XRE_IsE10sParentProcess() &&
8909 !DocumentChannel::CanUseDocumentChannel(aLoadState->URI()) &&
8910 !CanLoadInParentProcess(aLoadState->URI())) {
8911 return NS_ERROR_FAILURE;
8912 }
8913
8914 // Whenever a top-level browsing context is navigated, the user agent MUST
8915 // lock the orientation of the document to the document's default
8916 // orientation. We don't explicitly check for a top-level browsing context
8917 // here because orientation is only set on top-level browsing contexts.
8918 if (mBrowsingContext->GetOrientationLock() != hal::ScreenOrientation::None) {
8919 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"
, 8919); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mBrowsingContext->IsTop()"
")"); do { MOZ_CrashSequence(__null, 8919); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8920 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", 8921); AnnotateMozCrashReason
("MOZ_CRASH(" "NS_SUCCEEDED(mBrowsingContext->SetOrientationLock(hal::ScreenOrientation::None))"
")"); do { MOZ_CrashSequence(__null, 8921); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
8921 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", 8921); AnnotateMozCrashReason
("MOZ_CRASH(" "NS_SUCCEEDED(mBrowsingContext->SetOrientationLock(hal::ScreenOrientation::None))"
")"); do { MOZ_CrashSequence(__null, 8921); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
;
8922 if (mBrowsingContext->IsActive()) {
8923 ScreenOrientation::UpdateActiveOrientationLock(
8924 hal::ScreenOrientation::None);
8925 }
8926 }
8927
8928 // Do a check so that we know if there are ongoing requests
8929 // before calling Stop() below.
8930 Document* document = GetDocument();
8931 uint32_t flags = 0;
8932 if (document && !document->CanSavePresentation(nullptr, flags, true)) {
8933 // This forces some flags into the WindowGlobalParent's mBFCacheStatus,
8934 // which we'll then use in CanonicalBrowsingContext::AllowedInBFCache,
8935 // and in particular we'll store BFCacheStatus::REQUEST if needed.
8936 // Also, we want to report all the flags to the parent process here (and
8937 // not just BFCacheStatus::NOT_ALLOWED), so that it can update the
8938 // telemetry data correctly.
8939 document->DisallowBFCaching(flags);
8940 }
8941
8942 if (aLoadState->LoadIsFromSessionHistory() &&
8943 (mLoadType & LOAD_CMD_HISTORY)) {
8944 SetOngoingNavigation(Nothing());
8945 }
8946
8947 // Don't stop current network activity for javascript: URL's since they might
8948 // not result in any data, and thus nothing should be stopped in those cases.
8949 // In the case where they do result in data, the javascript: URL channel takes
8950 // care of stopping current network activity. Similarly, downloads don't
8951 // unload this document...
8952 if (!isJavaScript && !isDownload && !isExternalProtocol) {
8953 // Stop any current network activity.
8954 // Also stop content if this is a zombie doc. otherwise
8955 // the onload will be delayed by other loads initiated in the
8956 // background by the first document that
8957 // didn't fully load before the next load was initiated.
8958 // If not a zombie, don't stop content until data
8959 // starts arriving from the new URI...
8960 if ((mDocumentViewer && mDocumentViewer->GetPreviousViewer()) ||
8961 LOAD_TYPE_HAS_FLAGS(aLoadState->LoadType(), LOAD_FLAGS_STOP_CONTENT)((aLoadState->LoadType()) & ((LOAD_FLAGS_STOP_CONTENT)
<< 16))
) {
8962 rv = StopInternal(nsIWebNavigation::STOP_ALL, UnsetOngoingNavigation::No);
8963 } else {
8964 rv = StopInternal(nsIWebNavigation::STOP_NETWORK,
8965 UnsetOngoingNavigation::No);
8966 }
8967
8968 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
8969 return rv;
8970 }
8971 }
8972
8973 mLoadType = aLoadState->LoadType();
8974
8975 if (aLoadState->LoadIsFromSessionHistory() &&
8976 (mLoadType & LOAD_CMD_HISTORY)) {
8977 if (RefPtr window = GetActiveWindow()) {
8978 if (RefPtr navigation = window->Navigation()) {
8979 if (const LoadingSessionHistoryInfo* loadingInfo =
8980 GetLoadingSessionHistoryInfo()) {
8981 navigation->CreateNavigationActivationFrom(
8982 loadingInfo->mPreviousEntry,
8983 NavigationUtils::NavigationTypeFromLoadType(mLoadType));
8984 }
8985 }
8986 }
8987
8988 // https://html.spec.whatwg.org/#history-traversal:
8989 // To traverse the history
8990 // "If entry has a different Document object than the current entry, then
8991 // run the following substeps: Remove any tasks queued by the history
8992 // traversal task source..."
8993 // Same document object case was handled already above with
8994 // HandleSameDocumentNavigation call.
8995 RefPtr<ChildSHistory> shistory = GetRootSessionHistory();
8996 if (shistory) {
8997 shistory->RemovePendingHistoryNavigations();
8998 }
8999 }
9000
9001 bool isTopLevelDoc = mBrowsingContext->IsTopContent();
9002
9003 OriginAttributes attrs = GetOriginAttributes();
9004 attrs.SetFirstPartyDomain(isTopLevelDoc, aLoadState->URI());
9005
9006 nsCOMPtr<nsIRequest> req;
9007 rv = DoURILoad(aLoadState, aCacheKey, getter_AddRefs(req));
9008
9009 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
9010 if (shouldTakeFocus) {
9011 mBrowsingContext->Focus(CallerType::System, IgnoreErrors());
9012 }
9013 }
9014
9015 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
9016 nsCOMPtr<nsIChannel> chan(do_QueryInterface(req));
9017 UnblockEmbedderLoadEventForFailure();
9018
9019 // The spec says no exception should be raised for pre-navigation check
9020 // failures.
9021 if (NS_ERROR_DOM_SECURITY_ERR == rv) {
9022 return NS_OK;
9023 }
9024
9025 nsCOMPtr<nsIURI> uri = aLoadState->URI();
9026 if (DisplayLoadError(rv, uri, nullptr, chan) &&
9027 // FIXME: At this point code was using internal load flags, but checking
9028 // non-internal load flags?
9029 aLoadState->HasLoadFlags(LOAD_FLAGS_ERROR_LOAD_CHANGES_RV)) {
9030 return NS_ERROR_LOAD_SHOWED_ERRORPAGE;
9031 }
9032
9033 // We won't report any error if this is an unknown protocol error. The
9034 // reason behind this is that it will allow enumeration of external
9035 // protocols if we report an error for each unknown protocol.
9036 if (NS_ERROR_UNKNOWN_PROTOCOL == rv) {
9037 return NS_OK;
9038 }
9039 }
9040
9041 return rv;
9042}
9043
9044/* static */
9045bool nsDocShell::CanLoadInParentProcess(nsIURI* aURI) {
9046 nsCOMPtr<nsIURI> uri = aURI;
9047 // In e10s, in the parent process, we refuse to load anything other than
9048 // "safe" resources that we ship or trust enough to give "special" URLs.
9049 bool canLoadInParent = false;
9050 if (NS_SUCCEEDED(NS_URIChainHasFlags(((bool)(__builtin_expect(!!(!NS_FAILED_impl(NS_URIChainHasFlags
( uri, nsIProtocolHandler::URI_IS_UI_RESOURCE, &canLoadInParent
))), 1)))
9051 uri, nsIProtocolHandler::URI_IS_UI_RESOURCE, &canLoadInParent))((bool)(__builtin_expect(!!(!NS_FAILED_impl(NS_URIChainHasFlags
( uri, nsIProtocolHandler::URI_IS_UI_RESOURCE, &canLoadInParent
))), 1)))
&&
9052 canLoadInParent) {
9053 // We allow UI resources.
9054 return true;
9055 }
9056 // For about: and extension-based URIs, which don't get
9057 // URI_IS_UI_RESOURCE, first remove layers of view-source:, if present.
9058 while (uri && uri->SchemeIs("view-source")) {
9059 nsCOMPtr<nsINestedURI> nested = do_QueryInterface(uri);
9060 if (nested) {
9061 nested->GetInnerURI(getter_AddRefs(uri));
9062 } else {
9063 break;
9064 }
9065 }
9066 // Allow about: URIs, execept about:srcdoc, which can include arbitrary code.
9067 // And allow moz-extension ones if we're running extension content in the
9068 // parent process.
9069 if (!uri || (uri->SchemeIs("about") && !NS_IsAboutSrcdoc(uri)) ||
9070 (!StaticPrefs::extensions_webextensions_remote() &&
9071 uri->SchemeIs("moz-extension"))) {
9072 return true;
9073 }
9074#ifdef MOZ_THUNDERBIRD
9075 if (uri->SchemeIs("imap") || uri->SchemeIs("mailbox") ||
9076 uri->SchemeIs("news") || uri->SchemeIs("nntp") ||
9077 uri->SchemeIs("snews") || uri->SchemeIs("x-moz-ews") ||
9078 uri->SchemeIs("x-moz-graph")) {
9079 return true;
9080 }
9081#endif
9082 nsAutoCString scheme;
9083 uri->GetScheme(scheme);
9084 // Allow ext+foo URIs (extension-registered custom protocols). See
9085 // https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/protocol_handlers
9086 if (StringBeginsWith(scheme, "ext+"_ns) &&
9087 !StaticPrefs::extensions_webextensions_remote()) {
9088 return true;
9089 }
9090 // Final exception for some legacy automated tests:
9091 if (xpc::IsInAutomation() &&
9092 StaticPrefs::security_allow_unsafe_parent_loads()) {
9093 return true;
9094 }
9095 return false;
9096}
9097
9098nsIPrincipal* nsDocShell::GetInheritedPrincipal(
9099 bool aConsiderCurrentDocument, bool aConsiderPartitionedPrincipal) {
9100 RefPtr<Document> document;
9101 bool inheritedFromCurrent = false;
9102
9103 if (aConsiderCurrentDocument && mDocumentViewer) {
9104 document = mDocumentViewer->GetDocument();
9105 inheritedFromCurrent = true;
9106 }
9107
9108 if (!document) {
9109 nsCOMPtr<nsIDocShellTreeItem> parentItem;
9110 GetInProcessSameTypeParent(getter_AddRefs(parentItem));
9111 if (parentItem) {
9112 document = parentItem->GetDocument();
9113 }
9114 }
9115
9116 if (!document) {
9117 if (!aConsiderCurrentDocument) {
9118 return nullptr;
9119 }
9120
9121 // Make sure we end up with _something_ as the principal no matter
9122 // what.If this fails, we'll just get a null docViewer and bail.
9123 if (!VerifyDocumentViewer()) {
9124 return nullptr;
9125 }
9126 document = mDocumentViewer->GetDocument();
9127 }
9128
9129 //-- Get the document's principal
9130 if (document) {
9131 nsIPrincipal* docPrincipal = aConsiderPartitionedPrincipal
9132 ? document->PartitionedPrincipal()
9133 : document->NodePrincipal();
9134
9135 // Don't allow loads in typeContent docShells to inherit the system
9136 // principal from existing documents.
9137 if (inheritedFromCurrent && mItemType == typeContent &&
9138 docPrincipal->IsSystemPrincipal()) {
9139 return nullptr;
9140 }
9141
9142 return docPrincipal;
9143 }
9144
9145 return nullptr;
9146}
9147
9148/* static */ nsresult nsDocShell::CreateRealChannelForDocument(
9149 nsIChannel** aChannel, nsIURI* aURI, nsILoadInfo* aLoadInfo,
9150 nsIInterfaceRequestor* aCallbacks, nsLoadFlags aLoadFlags,
9151 const nsAString& aSrcdoc, nsIURI* aBaseURI) {
9152 nsCOMPtr<nsIChannel> channel;
9153 if (aSrcdoc.IsVoid()) {
9154 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(); })
9155 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(); })
9156 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(); })
9157 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(); })
;
9158
9159 if (aBaseURI) {
9160 nsCOMPtr<nsIViewSourceChannel> vsc = do_QueryInterface(channel);
9161 if (vsc) {
9162 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", 9162); AnnotateMozCrashReason
("MOZ_CRASH(" "NS_SUCCEEDED(vsc->SetBaseURI(aBaseURI))" ")"
); do { MOZ_CrashSequence(__null, 9162); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
;
9163 }
9164 }
9165 } else if (aURI->SchemeIs("view-source")) {
9166 // Instantiate view source handler protocol, if it doesn't exist already.
9167 nsCOMPtr<nsIIOService> io(do_GetIOService());
9168 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"
, 9168); AnnotateMozCrashReason("MOZ_ASSERT" "(" "io" ")"); do
{ MOZ_CrashSequence(__null, 9168); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
9169 nsCOMPtr<nsIProtocolHandler> handler;
9170 nsresult rv =
9171 io->GetProtocolHandler("view-source", getter_AddRefs(handler));
9172 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
9173 return rv;
9174 }
9175
9176 nsViewSourceHandler* vsh = nsViewSourceHandler::GetInstance();
9177 if (!vsh) {
9178 return NS_ERROR_FAILURE;
9179 }
9180
9181 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(); })
9182 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(); })
;
9183 } else {
9184 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", 9184); AnnotateMozCrashReason
("MOZ_RELEASE_ASSERT" "(" "NS_IsAboutSrcdoc(aURI)" ")"); do {
MOZ_CrashSequence(__null, 9184); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
9185
9186 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(); })
9187 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(); })
9188 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(); })
;
9189 nsCOMPtr<nsIInputStreamChannel> isc = do_QueryInterface(channel);
9190 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"
, 9190); AnnotateMozCrashReason("MOZ_ASSERT" "(" "isc" ")"); do
{ MOZ_CrashSequence(__null, 9190); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
9191 isc->SetBaseURI(aBaseURI);
9192 }
9193
9194 if (aLoadFlags != nsIRequest::LOAD_NORMAL) {
9195 nsresult rv = channel->SetLoadFlags(aLoadFlags);
9196 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"
, 9196); return rv; } } while (false)
;
9197 }
9198
9199 channel.forget(aChannel);
9200 return NS_OK;
9201}
9202
9203/* static */ bool nsDocShell::CreateAndConfigureRealChannelForLoadState(
9204 BrowsingContext* aBrowsingContext, nsDocShellLoadState* aLoadState,
9205 LoadInfo* aLoadInfo, nsIInterfaceRequestor* aCallbacks,
9206 nsDocShell* aDocShell, const OriginAttributes& aOriginAttributes,
9207 nsLoadFlags aLoadFlags, uint32_t aCacheKey, nsresult& aRv,
9208 nsIChannel** aChannel) {
9209 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"
, 9209); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadInfo" ")"
); do { MOZ_CrashSequence(__null, 9209); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9210
9211 nsString srcdoc = VoidString();
9212 bool isSrcdoc =
9213 aLoadState->HasInternalLoadFlags(INTERNAL_LOAD_FLAGS_IS_SRCDOC);
9214 if (isSrcdoc) {
9215 srcdoc = aLoadState->SrcdocData();
9216 }
9217
9218 aLoadInfo->SetTriggeringRemoteType(
9219 aLoadState->GetEffectiveTriggeringRemoteType());
9220
9221 if (aLoadState->PrincipalToInherit()) {
9222 aLoadInfo->SetPrincipalToInherit(aLoadState->PrincipalToInherit());
9223 }
9224 aLoadInfo->SetLoadTriggeredFromExternal(
9225 aLoadState->HasLoadFlags(LOAD_FLAGS_FROM_EXTERNAL));
9226 aLoadInfo->SetForceAllowDataURI(aLoadState->HasInternalLoadFlags(
9227 INTERNAL_LOAD_FLAGS_FORCE_ALLOW_DATA_URI));
9228 aLoadInfo->SetOriginalFrameSrcLoad(
9229 aLoadState->HasInternalLoadFlags(INTERNAL_LOAD_FLAGS_ORIGINAL_FRAME_SRC));
9230 aLoadInfo->SetIsNewWindowTarget(
9231 aLoadState->HasInternalLoadFlags(INTERNAL_LOAD_FLAGS_FIRST_LOAD));
9232 aLoadInfo->SetForceMediaDocument(aLoadState->GetForceMediaDocument());
9233
9234 bool inheritAttrs = false;
9235 if (aLoadState->PrincipalToInherit()) {
9236 inheritAttrs = nsContentUtils::ChannelShouldInheritPrincipal(
9237 aLoadState->PrincipalToInherit(), aLoadState->URI(),
9238 true, // aInheritForAboutBlank
9239 isSrcdoc);
9240 }
9241
9242 // Strip the target query parameters before creating the channel.
9243 aLoadState->MaybeStripTrackerQueryStrings(aBrowsingContext);
9244
9245 OriginAttributes attrs;
9246
9247 // Inherit origin attributes from PrincipalToInherit if inheritAttrs is
9248 // true. Otherwise we just use the origin attributes from docshell.
9249 if (inheritAttrs) {
9250 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", 9251); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aLoadState->PrincipalToInherit()" ") ("
"We should have PrincipalToInherit here." ")"); do { MOZ_CrashSequence
(__null, 9251); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
9251 "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", 9251); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aLoadState->PrincipalToInherit()" ") ("
"We should have PrincipalToInherit here." ")"); do { MOZ_CrashSequence
(__null, 9251); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
9252 attrs = aLoadState->PrincipalToInherit()->OriginAttributesRef();
9253 // If firstPartyIsolation is not enabled, then PrincipalToInherit should
9254 // have the same origin attributes with docshell.
9255 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", 9256); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "attrs == aOriginAttributes" ")"); do { MOZ_CrashSequence
(__null, 9256); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false); } } while (false)
9256 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", 9256); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "attrs == aOriginAttributes" ")"); do { MOZ_CrashSequence
(__null, 9256); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false); } } while (false)
;
9257 } else {
9258 attrs = aOriginAttributes;
9259 attrs.SetFirstPartyDomain(IsTopLevelDoc(aBrowsingContext, aLoadInfo),
9260 aLoadState->URI());
9261 }
9262
9263 aRv = aLoadInfo->SetOriginAttributes(attrs);
9264 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"
, 9264)
) {
9265 return false;
9266 }
9267
9268 if (aLoadState->GetIsFromProcessingFrameAttributes()) {
9269 aLoadInfo->SetIsFromProcessingFrameAttributes();
9270 }
9271
9272 // Propagate the IsFormSubmission flag to the loadInfo.
9273 if (aLoadState->IsFormSubmission()) {
9274 aLoadInfo->SetIsFormSubmission(true);
9275 }
9276
9277 aLoadInfo->SetUnstrippedURI(aLoadState->GetUnstrippedURI());
9278
9279 nsCOMPtr<nsIChannel> channel;
9280 aRv = CreateRealChannelForDocument(getter_AddRefs(channel), aLoadState->URI(),
9281 aLoadInfo, aCallbacks, aLoadFlags, srcdoc,
9282 aLoadState->BaseURI());
9283 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"
, 9283); return false; } } while (false)
;
9284
9285 if (!channel) {
9286 return false;
9287 }
9288
9289 // If the HTTPS-Only mode is enabled, every insecure request gets upgraded to
9290 // HTTPS by default. This behavior can be disabled through the loadinfo flag
9291 // HTTPS_ONLY_EXEMPT.
9292 nsHTTPSOnlyUtils::TestSitePermissionAndPotentiallyAddExemption(channel);
9293
9294 // hack
9295 nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(channel));
9296 nsCOMPtr<nsIHttpChannelInternal> httpChannelInternal(
9297 do_QueryInterface(channel));
9298 nsCOMPtr<nsIURI> referrer;
9299 nsIReferrerInfo* referrerInfo = aLoadState->GetReferrerInfo();
9300 if (referrerInfo) {
9301 referrerInfo->GetOriginalReferrer(getter_AddRefs(referrer));
9302 }
9303 if (httpChannelInternal) {
9304 if (aLoadState->FirstParty()) {
9305 aRv = httpChannelInternal->SetDocumentURI(aLoadState->URI());
9306 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"
, 9306); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(aRv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 9306); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9307 } else {
9308 aRv = httpChannelInternal->SetDocumentURI(referrer);
9309 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"
, 9309); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(aRv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 9309); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9310 }
9311 aRv = httpChannelInternal->SetRedirectMode(
9312 nsIHttpChannelInternal::REDIRECT_MODE_MANUAL);
9313 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"
, 9313); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(aRv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 9313); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9314 }
9315
9316 if (httpChannel) {
9317 if (aLoadState->HeadersStream()) {
9318 aRv = AddHeadersToChannel(aLoadState->HeadersStream(), httpChannel);
9319 }
9320 // Set the referrer explicitly
9321 // Referrer is currenly only set for link clicks here.
9322 if (referrerInfo) {
9323 aRv = httpChannel->SetReferrerInfo(referrerInfo);
9324 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"
, 9324); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(aRv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 9324); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9325 }
9326
9327 // Mark the http channel as UrgentStart for top level document loading in
9328 // active tab.
9329 if (IsUrgentStart(aBrowsingContext, aLoadInfo, aLoadState->LoadType())) {
9330 nsCOMPtr<nsIClassOfService> cos(do_QueryInterface(channel));
9331 if (cos) {
9332 cos->AddClassFlags(nsIClassOfService::UrgentStart);
9333 if (StaticPrefs::dom_document_priority_incremental()) {
9334 cos->SetIncremental(true);
9335 }
9336 }
9337 }
9338 }
9339
9340 channel->SetOriginalURI(aLoadState->OriginalURI() ? aLoadState->OriginalURI()
9341 : aLoadState->URI());
9342
9343 const nsACString& typeHint = aLoadState->TypeHint();
9344 if (!typeHint.IsVoid()) {
9345 channel->SetContentType(typeHint);
9346 }
9347
9348 const nsAString& fileName = aLoadState->FileName();
9349 if (!fileName.IsVoid()) {
9350 aRv = channel->SetContentDisposition(nsIChannel::DISPOSITION_ATTACHMENT);
9351 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"
, 9351); return false; } } while (false)
;
9352 if (!fileName.IsEmpty()) {
9353 aRv = channel->SetContentDispositionFilename(fileName);
9354 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"
, 9354); return false; } } while (false)
;
9355 }
9356 }
9357
9358 if (nsCOMPtr<nsIWritablePropertyBag2> props = do_QueryInterface(channel)) {
9359 nsCOMPtr<nsIURI> referrer;
9360 nsIReferrerInfo* referrerInfo = aLoadState->GetReferrerInfo();
9361 if (referrerInfo) {
9362 referrerInfo->GetOriginalReferrer(getter_AddRefs(referrer));
9363 }
9364 // save true referrer for those who need it (e.g. xpinstall whitelisting)
9365 // Currently only http and ftp channels support this.
9366 props->SetPropertyAsInterface(u"docshell.internalReferrer"_ns, referrer);
9367 }
9368
9369 nsCOMPtr<nsICacheInfoChannel> cacheChannel(do_QueryInterface(channel));
9370 auto loadType = aLoadState->LoadType();
9371
9372 if (loadType == LOAD_RELOAD_NORMAL &&
9373 StaticPrefs::
9374 browser_soft_reload_only_force_validate_top_level_document()) {
9375 nsCOMPtr<nsICacheInfoChannel> cachingChannel = do_QueryInterface(channel);
9376 if (cachingChannel) {
9377 cachingChannel->SetForceValidateCacheContent(true);
9378 }
9379 }
9380
9381 // figure out if we need to set the post data stream on the channel...
9382 if (aLoadState->PostDataStream()) {
9383 if (nsCOMPtr<nsIFormPOSTActionChannel> postChannel =
9384 do_QueryInterface(channel)) {
9385 // XXX it's a bit of a hack to rewind the postdata stream here but
9386 // it has to be done in case the post data is being reused multiple
9387 // times.
9388 nsCOMPtr<nsISeekableStream> postDataSeekable =
9389 do_QueryInterface(aLoadState->PostDataStream());
9390 if (postDataSeekable) {
9391 aRv = postDataSeekable->Seek(nsISeekableStream::NS_SEEK_SET, 0);
9392 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"
, 9392); return false; } } while (false)
;
9393 }
9394
9395 // we really need to have a content type associated with this stream!!
9396 postChannel->SetUploadStream(aLoadState->PostDataStream(), ""_ns, -1);
9397
9398 // Ownership of the stream has transferred to the channel, clear our
9399 // reference.
9400 aLoadState->SetPostDataStream(nullptr);
9401 }
9402
9403 /* If there is a valid postdata *and* it is a History Load,
9404 * set up the cache key on the channel, to retrieve the
9405 * data *only* from the cache. If it is a normal reload, the
9406 * cache is free to go to the server for updated postdata.
9407 */
9408 if (cacheChannel && aCacheKey != 0) {
9409 if (loadType == LOAD_HISTORY || loadType == LOAD_RELOAD_CHARSET_CHANGE) {
9410 cacheChannel->SetCacheKey(aCacheKey);
9411 uint32_t loadFlags;
9412 if (NS_SUCCEEDED(channel->GetLoadFlags(&loadFlags))((bool)(__builtin_expect(!!(!NS_FAILED_impl(channel->GetLoadFlags
(&loadFlags))), 1)))
) {
9413 channel->SetLoadFlags(loadFlags |
9414 nsICachingChannel::LOAD_ONLY_FROM_CACHE);
9415 }
9416 } else if (loadType == LOAD_RELOAD_NORMAL) {
9417 cacheChannel->SetCacheKey(aCacheKey);
9418 }
9419 }
9420 } else {
9421 /* If there is no postdata, set the cache key on the channel, and
9422 * do not set the LOAD_ONLY_FROM_CACHE flag, so that the channel
9423 * will be free to get it from net if it is not found in cache.
9424 * New cache may use it creatively on CGI pages with GET
9425 * method and even on those that say "no-cache"
9426 */
9427 if (loadType == LOAD_HISTORY || loadType == LOAD_RELOAD_NORMAL ||
9428 loadType == LOAD_RELOAD_CHARSET_CHANGE ||
9429 loadType == LOAD_RELOAD_CHARSET_CHANGE_BYPASS_CACHE ||
9430 loadType == LOAD_RELOAD_CHARSET_CHANGE_BYPASS_PROXY_AND_CACHE) {
9431 if (cacheChannel && aCacheKey != 0) {
9432 cacheChannel->SetCacheKey(aCacheKey);
9433 }
9434 }
9435 }
9436
9437 if (nsCOMPtr<nsIScriptChannel> scriptChannel = do_QueryInterface(channel)) {
9438 // Allow execution against our context if the principals match
9439 scriptChannel->SetExecutionPolicy(nsIScriptChannel::EXECUTE_NORMAL);
9440 }
9441
9442 if (nsCOMPtr<nsITimedChannel> timedChannel = do_QueryInterface(channel)) {
9443 nsString initiatorType;
9444 switch (aLoadInfo->InternalContentPolicyType()) {
9445 case nsIContentPolicy::TYPE_INTERNAL_EMBED:
9446 initiatorType = u"embed"_ns;
9447 break;
9448 case nsIContentPolicy::TYPE_INTERNAL_OBJECT:
9449 initiatorType = u"object"_ns;
9450 break;
9451 default: {
9452 const auto& embedderElementType =
9453 aBrowsingContext->GetEmbedderElementType();
9454 if (embedderElementType) {
9455 initiatorType = *embedderElementType;
9456 }
9457 break;
9458 }
9459 }
9460
9461 if (!initiatorType.IsEmpty()) {
9462 timedChannel->SetInitiatorType(initiatorType);
9463 }
9464 }
9465
9466 nsCOMPtr<nsIURI> rpURI;
9467 aLoadInfo->GetResultPrincipalURI(getter_AddRefs(rpURI));
9468 Maybe<nsCOMPtr<nsIURI>> originalResultPrincipalURI;
9469 aLoadState->GetMaybeResultPrincipalURI(originalResultPrincipalURI);
9470 if (originalResultPrincipalURI &&
9471 (!aLoadState->KeepResultPrincipalURIIfSet() || !rpURI)) {
9472 // Unconditionally override, we want the replay to be equal to what has
9473 // been captured.
9474 aLoadInfo->SetResultPrincipalURI(originalResultPrincipalURI.ref());
9475 }
9476
9477 if (aLoadState->OriginalURI() && aLoadState->LoadReplace()) {
9478 // The LOAD_REPLACE flag and its handling here will be removed as part
9479 // of bug 1319110. For now preserve its restoration here to not break
9480 // any code expecting it being set specially on redirected channels.
9481 // If the flag has originally been set to change result of
9482 // NS_GetFinalChannelURI it won't have any effect and also won't cause
9483 // any harm.
9484 uint32_t loadFlags;
9485 aRv = channel->GetLoadFlags(&loadFlags);
9486 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"
, 9486); return false; } } while (false)
;
9487 channel->SetLoadFlags(loadFlags | nsIChannel::LOAD_REPLACE);
9488 }
9489
9490 nsCOMPtr<nsIPolicyContainer> policyContainer = aLoadState->PolicyContainer();
9491 if (nsCOMPtr<nsIContentSecurityPolicy> csp =
9492 PolicyContainer::GetCSP(policyContainer)) {
9493 // Navigational requests that are same origin need to be upgraded in case
9494 // upgrade-insecure-requests is present. Please note that for document
9495 // navigations that bit is re-computed in case we encounter a server
9496 // side redirect so the navigation is not same-origin anymore.
9497 bool upgradeInsecureRequests = false;
9498 csp->GetUpgradeInsecureRequests(&upgradeInsecureRequests);
9499 if (upgradeInsecureRequests) {
9500 // only upgrade if the navigation is same origin
9501 nsCOMPtr<nsIPrincipal> resultPrincipal;
9502 aRv = nsContentUtils::GetSecurityManager()->GetChannelResultPrincipal(
9503 channel, getter_AddRefs(resultPrincipal));
9504 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"
, 9504); return false; } } while (false)
;
9505 if (nsContentSecurityUtils::IsConsideredSameOriginForUIR(
9506 aLoadState->TriggeringPrincipal(), resultPrincipal)) {
9507 aLoadInfo->SetUpgradeInsecureRequests(true);
9508 }
9509 }
9510 }
9511
9512 if (policyContainer) {
9513 // For document loads we store the policyContainer that potentially needs to
9514 // be inherited by the new document, e.g. in case we are loading
9515 // an opaque origin like a data: URI. The actual inheritance
9516 // check happens within Document::InitPolicyContainer().
9517 // Please create an actual copy of the policyContainer (do not share the
9518 // same reference) otherwise modifications done (such as the meta CSP of the
9519 // new doc) in an opaque origin will incorrectly be propagated to the
9520 // embedding document.
9521 RefPtr policyContainerToInherit = MakeRefPtr<PolicyContainer>();
9522 policyContainerToInherit->InitFromOther(
9523 PolicyContainer::Cast(policyContainer));
9524 aLoadInfo->SetPolicyContainerToInherit(policyContainerToInherit);
9525 }
9526
9527 channel.forget(aChannel);
9528 return true;
9529}
9530
9531bool nsDocShell::ShouldDoInitialAboutBlankSyncLoad(
9532 nsIURI* aURI, nsDocShellLoadState* aLoadState,
9533 nsIPrincipal* aPrincipalToInherit) {
9534 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", 9534); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "mDocumentViewer" ")"); do { MOZ_CrashSequence
(__null, 9534); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
9535
9536 if (!NS_IsAboutBlankAllowQueryAndFragment(aURI)) {
9537 return false;
9538 }
9539
9540 if (aLoadState->IsInitialAboutBlankHandlingProhibited()) {
9541 return false;
9542 }
9543
9544 Document* doc = mDocumentViewer->GetDocument();
9545
9546 if (mHasStartedLoadingOtherThanInitialBlankURI || !mDocumentViewer || !doc ||
9547 !doc->IsUncommittedInitialDocument()) {
9548 return false;
9549 }
9550
9551 if (!aPrincipalToInherit) {
9552 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", 9554); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "mDocumentViewer->GetDocument()->NodePrincipal()->GetIsNullPrincipal()"
") (" "Load looks like first load but does not want principal inheritance."
")"); do { MOZ_CrashSequence(__null, 9554); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
9553 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", 9554); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "mDocumentViewer->GetDocument()->NodePrincipal()->GetIsNullPrincipal()"
") (" "Load looks like first load but does not want principal inheritance."
")"); do { MOZ_CrashSequence(__null, 9554); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
9554 "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", 9554); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "mDocumentViewer->GetDocument()->NodePrincipal()->GetIsNullPrincipal()"
") (" "Load looks like first load but does not want principal inheritance."
")"); do { MOZ_CrashSequence(__null, 9554); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9555 } else {
9556 if (XRE_IsContentProcess()) {
9557 RefPtr<LoadedOriginSet> loadedOrigins = CurrentLoadedOriginSet();
9558 if (!loadedOrigins->ValidatePrincipal(aPrincipalToInherit)) {
9559 // We can't directly load this principal, so we need the normal load
9560 // path to do a process switch.
9561 return false;
9562 }
9563 }
9564
9565 // If a page opens about:blank, it will have a content principal.
9566 // If it is then restored after a restart, we might not have initialized
9567 // UsesOAC for it. If this is the case, do a normal load (bug 2004165).
9568 // XXX bug 2005205 tracks removing this workaround.
9569 if (aLoadState->LoadIsFromSessionHistory() &&
9570 !mBrowsingContext->Group()
9571 ->UsesOriginAgentCluster(aPrincipalToInherit)
9572 .isSome()) {
9573 return false;
9574 }
9575
9576 // Initial about:blank from SH is kind of broken.
9577 // - The IPC round-trip in MaybeHandleSubframeHistory will make the load
9578 // async, but CompleteInitialAboutBlankLoad might at least not replace
9579 // the document. See bug 2007894.
9580 // - If an xorigin iframe navigates itself to about:blank and is then
9581 // restored during a parent document reload / traversal, we get here with
9582 // an xorigin about:blank. See bug 2021375.
9583 // So at least block xorigin initial about:blank.
9584 if (aLoadState->LoadIsFromSessionHistory() &&
9585 !aPrincipalToInherit->Equals(doc->GetPrincipal())) {
9586 return false;
9587 }
9588 }
9589
9590 return true;
9591}
9592
9593void nsDocShell::UnsuppressPaintingIfNoNavigationAwayFromAboutBlank(
9594 mozilla::PresShell* aPresShell) {
9595 if (mHasStartedLoadingOtherThanInitialBlankURI || !mDocumentViewer) {
9596 return;
9597 }
9598 Document* doc = mDocumentViewer->GetDocument();
9599 if (!doc || !doc->IsInitialDocument()) {
9600 return;
9601 }
9602 if (mDocumentViewer->GetPresShell() != aPresShell) {
9603 return;
9604 }
9605 // Our surroundings appear to remain in the same state
9606 // as before posting the runnable.
9607 aPresShell->UnsuppressPainting();
9608 // The content viewer's mPresShell could have been removed now, see bug
9609 // 378682/421432
9610 if ((aPresShell = mDocumentViewer->GetPresShell())) {
9611 aPresShell->LoadComplete();
9612 }
9613}
9614
9615nsresult nsDocShell::PerformTrustedTypesPreNavigationCheck(
9616 nsDocShellLoadState* aLoadState, nsGlobalWindowInner* aWindow) const {
9617 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"
, 9617); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aWindow" ")"
); do { MOZ_CrashSequence(__null, 9617); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9618 RefPtr<nsIContentSecurityPolicy> csp =
9619 PolicyContainer::GetCSP(aWindow->GetPolicyContainer());
9620 if (csp->GetRequireTrustedTypesForDirectiveState() ==
9621 RequireTrustedTypesForDirectiveState::NONE) {
9622 return NS_OK;
9623 }
9624
9625 // Exempt web extension content scripts from trusted types policies defined by
9626 // the page in which they are running.
9627 if (auto principal = BasePrincipal::Cast(aLoadState->TriggeringPrincipal())) {
9628 if (principal->ContentScriptAddonPolicyCore()) {
9629 return NS_OK;
9630 }
9631 }
9632
9633 // If disposion is enforce for require-trusted-types-for, then we return
9634 // errors in order to block navigation. If it's report-only, errors are
9635 // ignored and the URL is unchanged.
9636 bool shouldBlockOnError = csp->GetRequireTrustedTypesForDirectiveState() ==
9637 RequireTrustedTypesForDirectiveState::ENFORCE;
9638
9639 // 2. Let urlString be the result of running the URL serializer on
9640 // request’s url.
9641 nsAutoCString urlString;
9642 aLoadState->URI()->GetSpec(urlString);
9643
9644 // 3. Let encodedScriptSource be the result of removing the leading
9645 // "javascript:" from urlString.
9646 constexpr auto javascriptScheme = "javascript:"_ns;
9647 const nsDependentCSubstring encodedScriptSource =
9648 Substring(urlString, javascriptScheme.Length());
9649
9650 // 4. Let convertedScriptSource be the result of executing Process value
9651 // with a default policy algorithm
9652 Maybe<nsAutoString> compliantStringHolder;
9653 NS_ConvertUTF8toUTF16 encodedScriptSourceUTF16(encodedScriptSource);
9654 constexpr nsLiteralString sink = u"Location href"_ns;
9655 auto reportPreNavigationCheckViolations = [&csp, &sink,
9656 &encodedScriptSourceUTF16] {
9657 // Report violation the same way as for "Should sink type mismatch
9658 // violation be blocked by Content Security Policy", since that's what
9659 // other browsers do. See
9660 // https://github.com/w3c/trusted-types/issues/584.
9661 auto location = JSCallingLocation::Get();
9662 TrustedTypeUtils::ReportSinkTypeMismatchViolations(
9663 csp, nullptr /* aCSPEventListener */, location.FileName(),
9664 location.mLine, location.mColumn, sink, kTrustedTypesOnlySinkGroup,
9665 encodedScriptSourceUTF16);
9666 };
9667 ErrorResult error;
9668 auto convertedScriptSource =
9669 TrustedTypeUtils::GetConvertedScriptSourceForPreNavigationCheck(
9670 *aWindow, encodedScriptSourceUTF16, sink, compliantStringHolder,
9671 error);
9672 error.WouldReportJSException();
9673 if (error.Failed()) {
9674 reportPreNavigationCheckViolations();
9675 if (shouldBlockOnError) {
9676 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"
, 9676); return (error).StealNSResult(); } } while (0)
;
9677 }
9678 error.SuppressException();
9679 return NS_OK;
9680 }
9681
9682 // 5. Set urlString to be the result of prepending "javascript:" to
9683 // stringified convertedScriptSource.
9684 urlString = javascriptScheme + NS_ConvertUTF16toUTF8(*convertedScriptSource);
9685
9686 // 6. Let newURL be the result of running the URL parser on urlString.
9687 nsCOMPtr<nsIURI> newURL;
9688 nsresult rv = NS_NewURI(getter_AddRefs(newURL), urlString);
9689 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
9690 reportPreNavigationCheckViolations();
9691 return shouldBlockOnError ? rv : NS_OK;
9692 }
9693
9694 // 7. Set request’s url to newURL.
9695 aLoadState->SetURI(newURL);
9696 return NS_OK;
9697}
9698
9699nsresult nsDocShell::DoURILoad(nsDocShellLoadState* aLoadState,
9700 Maybe<uint32_t> aCacheKey,
9701 nsIRequest** aRequest) {
9702 // Double-check that we're still around to load this URI.
9703 if (mIsBeingDestroyed) {
9704 // Return NS_OK despite not doing anything to avoid throwing exceptions
9705 // from nsLocation::SetHref if the unload handler of the existing page
9706 // tears us down.
9707 return NS_OK;
9708 }
9709
9710 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"
, 9710); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "mInitialized"
") (" "Need to initialize before load" ")"); do { MOZ_CrashSequence
(__null, 9710); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
9711 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"
, 9711); return NS_ERROR_FAILURE; } } while (false)
;
9712
9713 nsCOMPtr<nsIURILoader> uriLoader = components::URILoader::Service();
9714 if (NS_WARN_IF(!uriLoader)NS_warn_if_impl(!uriLoader, "!uriLoader", "./../../../docshell/base/nsDocShell.cpp"
, 9714)
) {
9715 return NS_ERROR_UNEXPECTED;
9716 }
9717
9718 // Persist and sync layout history state before we load a new uri, as this
9719 // might be our last chance to do so, in the content process.
9720 PersistLayoutHistoryState();
9721 SynchronizeLayoutHistoryState();
9722
9723 nsresult rv;
9724 nsContentPolicyType contentPolicyType = DetermineContentType();
9725
9726 auto getSourceWindowContext = [this, &aLoadState] {
9727 const MaybeDiscardedBrowsingContext& sourceBC =
9728 aLoadState->SourceBrowsingContext();
9729 if (!sourceBC.IsNullOrDiscarded()) {
9730 if (WindowContext* wc = sourceBC.get()->GetCurrentWindowContext()) {
9731 return wc;
9732 }
9733 }
9734 return mBrowsingContext->GetParentWindowContext();
9735 };
9736
9737 if (StaticPrefs::dom_security_trusted_types_enabled() &&
9738 aLoadState->URI()->SchemeIs("javascript")) {
9739 if (WindowContext* sourceWindowContext = getSourceWindowContext()) {
9740 RefPtr<nsGlobalWindowInner> window =
9741 sourceWindowContext->GetInnerWindow();
9742 rv = PerformTrustedTypesPreNavigationCheck(aLoadState, window);
9743 // Default policy might destroy the whole docshell, so check that again.
9744 if (mIsBeingDestroyed) {
9745 return NS_OK;
9746 }
9747 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
9748 return NS_ERROR_DOM_SECURITY_ERR;
9749 }
9750 }
9751 }
9752
9753 if (IsSubframe()) {
9754 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", 9756); 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, 9756); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
9755 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", 9756); 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, 9756); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
9756 "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", 9756); 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, 9756); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9757 if (StaticPrefs::dom_block_external_protocol_in_iframes()) {
9758 // Only allow URLs able to return data in iframes.
9759 if (nsContentUtils::IsExternalProtocol(aLoadState->URI())) {
9760 // The context to check user-interaction with for the purposes of
9761 // popup-blocking.
9762 //
9763 // We generally want to check the context that initiated the navigation.
9764 WindowContext* sourceWindowContext = getSourceWindowContext();
9765 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", 9765); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "sourceWindowContext" ")"); do { MOZ_CrashSequence
(__null, 9765); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
9766
9767 // FIXME: We can't check user-interaction against an OOP window. This is
9768 // the next best thing we can really do. The load state keeps whether
9769 // the navigation had a user interaction in process
9770 // (aLoadState->HasValidUserGestureActivation()), but we can't really
9771 // consume it, which we want to prevent popup-spamming from the same
9772 // click event.
9773 WindowContext* context =
9774 sourceWindowContext->IsInProcess()
9775 ? sourceWindowContext
9776 : mBrowsingContext->GetCurrentWindowContext();
9777 const bool popupBlocked = [&] {
9778 const bool active = mBrowsingContext->IsActive();
9779
9780 // For same-origin-with-top windows, we grant a single free popup
9781 // without user activation, see bug 1680721.
9782 //
9783 // We consume the flag now even if there's no user activation.
9784 const bool hasFreePass = [&] {
9785 if (!active ||
9786 !(context->IsInProcess() && context->SameOriginWithTop())) {
9787 return false;
9788 }
9789 nsGlobalWindowInner* win =
9790 context->TopWindowContext()->GetInnerWindow();
9791 return win && win->TryOpenExternalProtocolIframe();
9792 }();
9793
9794 if (context->IsInProcess() &&
9795 context->ConsumeTransientUserGestureActivation()) {
9796 // If the user has interacted with the page, consume it.
9797 return false;
9798 }
9799
9800 // TODO(emilio): Can we remove this check? It seems like what prompted
9801 // this code (bug 1514547) should be covered by transient user
9802 // activation, see bug 1514547.
9803 if (active &&
9804 PopupBlocker::ConsumeTimerTokenForExternalProtocolIframe()) {
9805 return false;
9806 }
9807
9808 if (sourceWindowContext->CanShowPopup()) {
9809 return false;
9810 }
9811
9812 if (hasFreePass) {
9813 return false;
9814 }
9815
9816 return true;
9817 }();
9818
9819 // No error must be returned when iframes are blocked.
9820 if (popupBlocked) {
9821 nsAutoString message;
9822 nsresult rv = nsContentUtils::GetLocalizedString(
9823 PropertiesFile::DOM_PROPERTIES,
9824 "ExternalProtocolFrameBlockedNoUserActivation", message);
9825 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
9826 nsContentUtils::ReportToConsoleByWindowID(
9827 message, nsIScriptError::warningFlag, "DOM"_ns,
9828 context->InnerWindowId());
9829 }
9830 return NS_OK;
9831 }
9832 }
9833 }
9834
9835 // Only allow view-source scheme in top-level docshells. view-source is
9836 // the only scheme to which this applies at the moment due to potential
9837 // timing attacks to read data from cross-origin iframes. If this widens
9838 // we should add a protocol flag for whether the scheme is allowed in
9839 // frames and use something like nsNetUtil::NS_URIChainHasFlags.
9840 nsCOMPtr<nsIURI> tempURI = aLoadState->URI();
9841 nsCOMPtr<nsINestedURI> nestedURI = do_QueryInterface(tempURI);
9842 while (nestedURI) {
9843 // view-source should always be an nsINestedURI, loop and check the
9844 // scheme on this and all inner URIs that are also nested URIs.
9845 if (tempURI->SchemeIs("view-source")) {
9846 return NS_ERROR_UNKNOWN_PROTOCOL;
9847 }
9848 nestedURI->GetInnerURI(getter_AddRefs(tempURI));
9849 nestedURI = do_QueryInterface(tempURI);
9850 }
9851 } else {
9852 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", 9853); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "contentPolicyType == nsIContentPolicy::TYPE_DOCUMENT"
") (" "DoURILoad thinks this is a document and InternalLoad does not"
")"); do { MOZ_CrashSequence(__null, 9853); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
9853 "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", 9853); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "contentPolicyType == nsIContentPolicy::TYPE_DOCUMENT"
") (" "DoURILoad thinks this is a document and InternalLoad does not"
")"); do { MOZ_CrashSequence(__null, 9853); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9854 }
9855
9856 // We want to inherit aLoadState->PrincipalToInherit() when:
9857 // 1. ChannelShouldInheritPrincipal returns true.
9858 // 2. aLoadState->URI() is not data: URI, or data: URI is not
9859 // configured as unique opaque origin.
9860 bool inheritPrincipal = false;
9861
9862 nsCOMPtr<nsIURI> uri = aLoadState->URI();
9863 if (aLoadState->PrincipalToInherit()) {
9864 bool isSrcdoc =
9865 aLoadState->HasInternalLoadFlags(INTERNAL_LOAD_FLAGS_IS_SRCDOC);
9866 bool inheritAttrs = nsContentUtils::ChannelShouldInheritPrincipal(
9867 aLoadState->PrincipalToInherit(), uri,
9868 true, // aInheritForAboutBlank
9869 isSrcdoc);
9870
9871 inheritPrincipal = inheritAttrs && !uri->SchemeIs("data");
9872 }
9873
9874 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"
, 9876); AnnotateMozCrashReason("MOZ_ASSERT" "(" "inheritPrincipal"
")"); do { MOZ_CrashSequence(__null, 9876); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
9875 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"
, 9876); AnnotateMozCrashReason("MOZ_ASSERT" "(" "inheritPrincipal"
")"); do { MOZ_CrashSequence(__null, 9876); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
9876 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"
, 9876); AnnotateMozCrashReason("MOZ_ASSERT" "(" "inheritPrincipal"
")"); do { MOZ_CrashSequence(__null, 9876); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
9877 // See https://bugzilla.mozilla.org/show_bug.cgi?id=1736570
9878 const bool doInitialSyncLoad = ShouldDoInitialAboutBlankSyncLoad(
9879 uri, aLoadState, aLoadState->PrincipalToInherit());
9880
9881 if (!doInitialSyncLoad && mBrowsingContext->IsContent()) {
9882 // https://wicg.github.io/document-picture-in-picture/#close-on-navigate
9883 // Two exceptions.
9884 // - The initial navigation is not per-spec and must complete.
9885 // - We also set IsDocumentPiP on chrome but the spec doesn't apply to it.
9886 if (Document* doc = GetExtantDocument()) {
9887 NS_DispatchToMainThread(NS_NewRunnableFunction(
9888 "Close PIP window on navigate",
9889 [doc = RefPtr(doc)]() MOZ_CAN_RUN_SCRIPT_BOUNDARY_LAMBDA {
9890 doc->CloseAnyAssociatedDocumentPiPWindows();
9891 }));
9892 }
9893 if (mBrowsingContext->GetIsDocumentPiP()) {
9894 return NS_OK;
9895 }
9896 }
9897
9898 // FIXME We still have a ton of codepaths that don't pass through
9899 // DocumentLoadListener, so probably need to create session history info
9900 // in more places.
9901 if (aLoadState->GetLoadingSessionHistoryInfo()) {
9902 SetLoadingSessionHistoryInfo(*aLoadState->GetLoadingSessionHistoryInfo());
9903 } else if (doInitialSyncLoad) {
9904 // Materialize LoadingSessionHistoryInfo here, because DocumentChannel
9905 // loads have it, and later history behavior depends on it existing.
9906 UniquePtr<SessionHistoryInfo> entry = MakeUnique<SessionHistoryInfo>(
9907 uri, aLoadState->TriggeringPrincipal(),
9908 aLoadState->PrincipalToInherit(),
9909 aLoadState->PartitionedPrincipalToInherit(),
9910 aLoadState->PolicyContainer(), mContentTypeHint);
9911 entry->SetTransient();
9912 mozilla::dom::LoadingSessionHistoryInfo info(*entry);
9913 if (Navigation::IsAPIEnabled()) {
9914 info.mContiguousEntries.AppendElement(*entry);
9915 }
9916 SetLoadingSessionHistoryInfo(info, true);
9917 }
9918
9919 // open a channel for the url
9920
9921 // If we have a pending channel, use the channel we've already created here.
9922 // We don't need to set up load flags for our channel, as it has already been
9923 // created.
9924
9925 if (nsCOMPtr<nsIChannel> channel =
9926 aLoadState->GetPendingRedirectedChannel()) {
9927 // If we have a request outparameter, shove our channel into it.
9928 if (aRequest) {
9929 nsCOMPtr<nsIRequest> outRequest = channel;
9930 outRequest.forget(aRequest);
9931 }
9932
9933 mHasStartedLoadingOtherThanInitialBlankURI = true;
9934 return OpenRedirectedChannel(aLoadState);
9935 }
9936
9937 // There are two cases we care about:
9938 // * Top-level load: In this case, loadingNode is null, but loadingWindow
9939 // is our mScriptGlobal. We pass null for loadingPrincipal in this case.
9940 // * Subframe load: loadingWindow is null, but loadingNode is the frame
9941 // element for the load. loadingPrincipal is the NodePrincipal of the
9942 // frame element.
9943 nsCOMPtr<nsINode> loadingNode;
9944 nsCOMPtr<nsPIDOMWindowOuter> loadingWindow;
9945 nsCOMPtr<nsIPrincipal> loadingPrincipal;
9946 nsCOMPtr<nsISupports> topLevelLoadingContext;
9947
9948 if (contentPolicyType == nsIContentPolicy::TYPE_DOCUMENT) {
9949 loadingNode = nullptr;
9950 loadingPrincipal = nullptr;
9951 loadingWindow = mScriptGlobal;
9952 if (XRE_IsContentProcess()) {
9953 // In e10s the child process doesn't have access to the element that
9954 // contains the browsing context (because that element is in the chrome
9955 // process).
9956 nsCOMPtr<nsIBrowserChild> browserChild = GetBrowserChild();
9957 topLevelLoadingContext = ToSupports(browserChild);
9958 } else {
9959 // This is for loading non-e10s tabs and toplevel windows of various
9960 // sorts.
9961 // For the toplevel window cases, requestingElement will be null.
9962 nsCOMPtr<Element> requestingElement =
9963 loadingWindow->GetFrameElementInternal();
9964 topLevelLoadingContext = requestingElement;
9965 }
9966 } else {
9967 loadingWindow = nullptr;
9968 loadingNode = mScriptGlobal->GetFrameElementInternal();
9969 if (loadingNode) {
9970 // If we have a loading node, then use that as our loadingPrincipal.
9971 loadingPrincipal = loadingNode->NodePrincipal();
9972#ifdef DEBUG1
9973 // Get the docshell type for requestingElement.
9974 RefPtr<Document> requestingDoc = loadingNode->OwnerDoc();
9975 nsCOMPtr<nsIDocShell> elementDocShell = requestingDoc->GetDocShell();
9976 // requestingElement docshell type = current docshell type.
9977 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", 9979); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "mItemType == elementDocShell->ItemType()"
") (" "subframes should have the same docshell type as their parent"
")"); do { MOZ_CrashSequence(__null, 9979); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
9978 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", 9979); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "mItemType == elementDocShell->ItemType()"
") (" "subframes should have the same docshell type as their parent"
")"); do { MOZ_CrashSequence(__null, 9979); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
9979 "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", 9979); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "mItemType == elementDocShell->ItemType()"
") (" "subframes should have the same docshell type as their parent"
")"); do { MOZ_CrashSequence(__null, 9979); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9980#endif
9981 } else {
9982 if (mIsBeingDestroyed) {
9983 // If this isn't a top-level load and mScriptGlobal's frame element is
9984 // null, then the element got removed from the DOM while we were trying
9985 // to load this resource. This docshell is scheduled for destruction
9986 // already, so bail out here.
9987 return NS_OK;
9988 }
9989 // If we are not being destroyed and we do not have access to the loading
9990 // node, then we are a remote subframe. Set the loading principal
9991 // to be a null principal and then set it correctly in the parent.
9992 loadingPrincipal = NullPrincipal::Create(GetOriginAttributes(), nullptr);
9993 }
9994 }
9995
9996 if (!aLoadState->TriggeringPrincipal()) {
9997 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", 9997); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "false" ") (" "DoURILoad needs a valid triggeringPrincipal"
")"); do { MOZ_CrashSequence(__null, 9997); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9998 return NS_ERROR_FAILURE;
9999 }
10000
10001 uint32_t sandboxFlags = mBrowsingContext->GetSandboxFlags();
10002 nsSecurityFlags securityFlags =
10003 nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_SEC_CONTEXT_IS_NULL;
10004
10005 if (mLoadType == LOAD_ERROR_PAGE) {
10006 securityFlags |= nsILoadInfo::SEC_LOAD_ERROR_PAGE;
10007 }
10008
10009 if (inheritPrincipal) {
10010 securityFlags |= nsILoadInfo::SEC_FORCE_INHERIT_PRINCIPAL;
10011 }
10012
10013 // Must never have a parent for TYPE_DOCUMENT loads
10014 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", 10015); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!mBrowsingContext->GetParent()" ")"); do
{ MOZ_CrashSequence(__null, 10015); __attribute__((nomerge))
::abort(); } while (false); } } while (false); } } while (false
)
10015 !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", 10015); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!mBrowsingContext->GetParent()" ")"); do
{ MOZ_CrashSequence(__null, 10015); __attribute__((nomerge))
::abort(); } while (false); } } while (false); } } while (false
)
;
10016 // Subdocuments must have a parent
10017 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"
, 10018); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mBrowsingContext->GetParent()"
")"); do { MOZ_CrashSequence(__null, 10018); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false); } } while
(false)
10018 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"
, 10018); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mBrowsingContext->GetParent()"
")"); do { MOZ_CrashSequence(__null, 10018); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false); } } while
(false)
;
10019 mBrowsingContext->SetTriggeringAndInheritPrincipals(
10020 aLoadState->TriggeringPrincipal(), aLoadState->PrincipalToInherit(),
10021 aLoadState->GetLoadIdentifier());
10022 RefPtr<LoadInfo> loadInfo;
10023 if (contentPolicyType == nsIContentPolicy::TYPE_DOCUMENT) {
10024 loadInfo = MakeRefPtr<LoadInfo>(
10025 loadingWindow, uri, aLoadState->TriggeringPrincipal(),
10026 topLevelLoadingContext, securityFlags, sandboxFlags);
10027 } else {
10028 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(); })
10029 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(); })
10030 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(); })
10031 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(); })
;
10032 }
10033 RefPtr<WindowContext> context = mBrowsingContext->GetCurrentWindowContext();
10034
10035 if (doInitialSyncLoad) {
10036 // Stay on the eagerly created document and adjust it to match what we would
10037 // be loading.
10038 return CompleteInitialAboutBlankLoad(aLoadState, loadInfo);
10039 }
10040 mHasStartedLoadingOtherThanInitialBlankURI = true;
10041
10042 if (mLoadType != LOAD_ERROR_PAGE && context && context->IsInProcess()) {
10043 if (context->HasValidTransientUserGestureActivation()) {
10044 aLoadState->SetHasValidUserGestureActivation(true);
10045 aLoadState->SetTextDirectiveUserActivation(true);
10046 }
10047 if (!aLoadState->TriggeringWindowId()) {
10048 aLoadState->SetTriggeringWindowId(context->Id());
10049 }
10050 }
10051
10052 // in case this docshell load was triggered by a valid transient user gesture,
10053 // or also the load originates from external, then we pass that information on
10054 // to the loadinfo, which allows e.g. setting Sec-Fetch-User request headers.
10055 if (aLoadState->HasValidUserGestureActivation() ||
10056 aLoadState->HasLoadFlags(LOAD_FLAGS_FROM_EXTERNAL)) {
10057 loadInfo->SetHasValidUserGestureActivation(true);
10058 aLoadState->SetTextDirectiveUserActivation(true);
10059 }
10060
10061 loadInfo->SetTextDirectiveUserActivation(
10062 aLoadState->GetTextDirectiveUserActivation());
10063
10064 loadInfo->SetTriggeringWindowId(aLoadState->TriggeringWindowId());
10065 loadInfo->SetTriggeringSandboxFlags(aLoadState->TriggeringSandboxFlags());
10066 net::ClassificationFlags flags = aLoadState->TriggeringClassificationFlags();
10067 loadInfo->SetTriggeringFirstPartyClassificationFlags(flags.firstPartyFlags);
10068 loadInfo->SetTriggeringThirdPartyClassificationFlags(flags.thirdPartyFlags);
10069 loadInfo->SetIsMetaRefresh(aLoadState->IsMetaRefresh());
10070
10071 uint32_t cacheKey = 0;
10072 if (aCacheKey) {
10073 cacheKey = *aCacheKey;
10074 } else {
10075 if (mLoadingEntry) {
10076 cacheKey = mLoadingEntry->mInfo.GetCacheKey();
10077 } else if (mActiveEntry) { // for reload cases
10078 cacheKey = mActiveEntry->GetCacheKey();
10079 }
10080 }
10081
10082 bool uriModified;
10083 if (mLoadingEntry) {
10084 uriModified = mLoadingEntry->mInfo.GetURIWasModified();
10085 } else {
10086 uriModified = false;
10087 }
10088
10089 bool isEmbeddingBlockedError = false;
10090 if (mFailedChannel) {
10091 nsresult status;
10092 mFailedChannel->GetStatus(&status);
10093 isEmbeddingBlockedError = status == NS_ERROR_XFO_VIOLATION ||
10094 status == NS_ERROR_CSP_FRAME_ANCESTOR_VIOLATION;
10095 }
10096
10097 nsLoadFlags loadFlags = aLoadState->CalculateChannelLoadFlags(
10098 mBrowsingContext, uriModified, Some(isEmbeddingBlockedError));
10099
10100 nsCOMPtr<nsIChannel> channel;
10101 if (DocumentChannel::CanUseDocumentChannel(uri)) {
10102 channel = DocumentChannel::CreateForDocument(
10103 aLoadState, loadInfo, loadFlags, this, cacheKey, uriModified,
10104 isEmbeddingBlockedError);
10105 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"
, 10105); AnnotateMozCrashReason("MOZ_ASSERT" "(" "channel" ")"
); do { MOZ_CrashSequence(__null, 10105); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
10106
10107 // Disable keyword fixup when using DocumentChannel, since
10108 // DocumentLoadListener will handle this for us (in the parent process).
10109 mAllowKeywordFixup = false;
10110 } else if (!CreateAndConfigureRealChannelForLoadState(
10111 mBrowsingContext, aLoadState, loadInfo, this, this,
10112 GetOriginAttributes(), loadFlags, cacheKey, rv,
10113 getter_AddRefs(channel))) {
10114 return rv;
10115 }
10116
10117 // Make sure to give the caller a channel if we managed to create one
10118 // This is important for correct error page/session history interaction
10119 if (aRequest) {
10120 NS_ADDREF(*aRequest = channel)(*aRequest = channel)->AddRef();
10121 }
10122
10123 const nsACString& typeHint = aLoadState->TypeHint();
10124 if (!typeHint.IsVoid()) {
10125 mContentTypeHint = typeHint;
10126 } else {
10127 mContentTypeHint.Truncate();
10128 }
10129
10130 // Load attributes depend on load type...
10131 if (mLoadType == LOAD_RELOAD_CHARSET_CHANGE) {
10132 // Use SetAllowStaleCacheContent (not LOAD_FROM_CACHE flag) since we
10133 // only want to force cache load for this channel, not the whole
10134 // loadGroup.
10135 nsCOMPtr<nsICacheInfoChannel> cachingChannel = do_QueryInterface(channel);
10136 if (cachingChannel) {
10137 cachingChannel->SetAllowStaleCacheContent(true);
10138 }
10139 }
10140
10141 uint32_t openFlags =
10142 nsDocShell::ComputeURILoaderFlags(mBrowsingContext, mLoadType);
10143 return OpenInitializedChannel(channel, uriLoader, openFlags);
10144}
10145
10146nsresult nsDocShell::CompleteInitialAboutBlankLoad(
10147 nsDocShellLoadState* aLoadState, nsILoadInfo* aLoadInfo) {
10148 nsresult rv;
10149 // Match the DocumentChannel case where the default for third-partiness
10150 // differs from the default in LoadInfo construction here.
10151 BrowsingContext* top = mBrowsingContext->Top();
10152 if (top == mBrowsingContext) {
10153 aLoadInfo->SetIsThirdPartyContextToTopWindow(false);
10154 } else {
10155 bool thirdParty = true;
10156 if (Document* topDoc = top->GetExtantDocument();
10157 topDoc && aLoadState->PrincipalToInherit()) {
10158 (void)topDoc->GetPrincipal()->IsThirdPartyPrincipal(
10159 aLoadState->PrincipalToInherit(), &thirdParty);
10160 }
10161 aLoadInfo->SetIsThirdPartyContextToTopWindow(thirdParty);
10162 }
10163
10164 if (!mDocumentViewer) {
10165 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", 10165); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "false" ") (" "How did the viewer go away?"
")"); do { MOZ_CrashSequence(__null, 10165); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10166 return NS_ERROR_FAILURE;
10167 }
10168 RefPtr<Document> doc = mDocumentViewer->GetDocument();
10169 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)
10170 ("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)
10171 "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)
10172 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)
;
10173 if (!doc) {
10174 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", 10174); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "false" ") (" "How did the document go away?"
")"); do { MOZ_CrashSequence(__null, 10174); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10175 return NS_ERROR_FAILURE;
10176 }
10177
10178 // Get the load event fired for the initial about:blank without starting
10179 // a real load from a channel. We still need a channel object even though
10180 // we don't care about reading from the channel.
10181 nsCOMPtr<nsIChannel> aboutBlankChannel;
10182 rv = NS_NewChannelInternal(getter_AddRefs(aboutBlankChannel),
10183 aLoadState->URI(), aLoadInfo, nullptr, mLoadGroup,
10184 nullptr, nsIChannel::LOAD_DOCUMENT_URI);
10185 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
10186 return rv;
10187 }
10188 if (!aboutBlankChannel) {
10189 return NS_ERROR_FAILURE;
10190 }
10191
10192 nsCOMPtr<nsIPrincipal> expectedPrincipal = aLoadState->PrincipalToInherit();
10193 nsCOMPtr<nsIPrincipal> expectedPartitionedPrincipal = expectedPrincipal;
10194 // If we don't have a content principal, also use it as partitioned principal
10195 if (expectedPrincipal && expectedPrincipal->GetIsContentPrincipal()) {
10196 // The partitioned content principal is always isolated.
10197 StoragePrincipalHelper::Create(
10198 aboutBlankChannel, expectedPrincipal, /* aForceIsolation */ true,
10199 getter_AddRefs(expectedPartitionedPrincipal));
10200 }
10201
10202 const bool principalMismatch =
10203 expectedPrincipal && !expectedPrincipal->Equals(doc->GetPrincipal());
10204 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"
, 10204); AnnotateMozCrashReason("MOZ_ASSERT" "(" "doc->GetPrincipal()->GetIsNullPrincipal()"
")"); do { MOZ_CrashSequence(__null, 10204); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false); } } while
(false)
;
10205
10206 // The channel would sandbox aLoadState->PrincipalToInherit(). Even if
10207 // the document already has a null principal, we don't know if it's the right
10208 // sandboxed one. So be safe and clobber.
10209 const uint32_t sandboxFlags =
10210 mBrowsingContext->GetHasLoadedNonInitialDocument()
10211 ? mBrowsingContext->GetSandboxFlags()
10212 : mBrowsingContext->GetInitialSandboxFlags();
10213 const bool shouldBeSandboxed = sandboxFlags & SANDBOXED_ORIGIN;
10214 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"
, 10214); AnnotateMozCrashReason("MOZ_ASSERT" "(" "expectedPrincipal"
")"); do { MOZ_CrashSequence(__null, 10214); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false); } } while
(false)
;
10215
10216 // Clobber document before completing the synchronous load if it doesn't have
10217 // the right principal (bug 1979032)
10218 if (principalMismatch || shouldBeSandboxed) {
10219 // This will sandbox the principals as needed
10220 nsCOMPtr<nsIPolicyContainer> policyContainer =
10221 aLoadState->PolicyContainer();
10222 nsCOMPtr<nsIURI> base = doc->GetDocBaseURI();
10223 rv = CreateAboutBlankDocumentViewer(
10224 expectedPrincipal, expectedPartitionedPrincipal, policyContainer, base,
10225 /* aIsInitialDocument */ true);
10226 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"
, 10226); return rv; } } while (false)
;
10227
10228 doc = mDocumentViewer->GetDocument();
10229 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"
, 10229); AnnotateMozCrashReason("MOZ_ASSERT" "(" "doc" ")");
do { MOZ_CrashSequence(__null, 10229); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
10230 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)
10231 ("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)
10232 "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)
10233 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)
;
10234 }
10235
10236 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"
, 10237); AnnotateMozCrashReason("MOZ_ASSERT" "(" "doc->IsInitialDocument()"
") (" "How come the doc is no longer the initial one?" ")");
do { MOZ_CrashSequence(__null, 10237); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
10237 "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"
, 10237); AnnotateMozCrashReason("MOZ_ASSERT" "(" "doc->IsInitialDocument()"
") (" "How come the doc is no longer the initial one?" ")");
do { MOZ_CrashSequence(__null, 10237); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
10238
10239 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", 10239); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "doc->GetReadyStateEnum() == Document::READYSTATE_COMPLETE"
")"); do { MOZ_CrashSequence(__null, 10239); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10240 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", 10240); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!mIsLoadingDocument" ")"); do { MOZ_CrashSequence
(__null, 10240); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
10241
10242 if (nsIContentSecurityPolicy* csp =
10243 PolicyContainer::GetCSP(doc->GetPolicyContainer())) {
10244 // We do this here rather than when inheriting the CSP in
10245 // CreateAboutBlankDocumentViewer so that client source and parsed policies
10246 // use the parent's URI as self (bug 2021482, 2035423).
10247 MOZ_TRY(csp->SetRequestContextWithDocument(doc))__extension__({ auto mozTryVarTempResult = ::mozilla::ToResult
(csp->SetRequestContextWithDocument(doc)); if ((__builtin_expect
(!!(mozTryVarTempResult.isErr()), 0))) { return mozTryVarTempResult
.propagateErr(); } mozTryVarTempResult.unwrap(); })
;
10248 }
10249 doc->ApplyCspFromLoadInfo(aLoadInfo);
10250 doc->ApplySettingsFromCSP(false);
10251 doc->RecomputeResistFingerprinting();
10252
10253 rv = doc->GetWindowContext()->SetIsOriginalFrameSource(
10254 aLoadState->HasInternalLoadFlags(INTERNAL_LOAD_FLAGS_ORIGINAL_FRAME_SRC));
10255 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"
, 10255); return rv; } } while (false)
;
10256
10257 nsPIDOMWindowInner* innerWindow = doc->GetInnerWindow();
10258 if (innerWindow) {
10259 mozilla::dom::ClientSource* clientSource =
10260 nsGlobalWindowInner::Cast(innerWindow)->GetClientSource();
10261 // See if we don't have a controller but the parent has gained a
10262 // controller.
10263 if (clientSource && clientSource->GetController().isNothing()) {
10264 MaybeInheritController(
10265 clientSource,
10266 StoragePrincipalHelper::ShouldUsePartitionPrincipalForServiceWorker(
10267 this)
10268 ? doc->PartitionedPrincipal()
10269 : doc->GetPrincipal());
10270 }
10271 }
10272
10273 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", 10273); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!mIsLoadingDocument" ")"); do { MOZ_CrashSequence
(__null, 10273); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
10274 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", 10274); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!mDocumentRequest" ")"); do { MOZ_CrashSequence
(__null, 10274); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
10275
10276 // Call OnStartRequest so that nsDocLoader sets mIsLoadingDocument and fire
10277 // state start
10278 OnStartRequest(aboutBlankChannel);
10279
10280 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", 10280); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "mIsLoadingDocument" ")"); do { MOZ_CrashSequence
(__null, 10280); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
10281 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", 10281); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "mDocumentRequest == aboutBlankChannel" ")"
); do { MOZ_CrashSequence(__null, 10281); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
10282 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", 10282); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!doc->InitialAboutBlankLoadCompleting()"
")"); do { MOZ_CrashSequence(__null, 10282); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10283
10284 doc->BeginInitialAboutBlankLoadCompleting(aboutBlankChannel);
10285 auto resetLoadCompleting =
10286 MakeScopeExit([&] { doc->EndInitialAboutBlankLoadCompleting(); });
10287
10288 mCurrentURI = aLoadState->URI();
10289 doc->SetDocumentURI(aLoadState->URI());
10290
10291 // Normal documents fire the location change at content viewer creation.
10292 // The initial about:blank does not do that at content viewer creation,
10293 // so that the UI isn't bothered about the initial about:blank if there's
10294 // immediate navigation away. However, now that the initial about:blank is
10295 // going to remain in this docshell, we need to let to the UI know about it
10296 // (at least in the top-level case).
10297 FireOnLocationChange(this, aboutBlankChannel, aLoadState->URI(), 0);
10298
10299 MoveLoadingToActiveEntry(false, 0, nullptr);
10300
10301 doc->BeginLoad();
10302
10303 nsContentUtils::AddScriptRunner(
10304 MakeAndAddRef<nsDocElementCreatedNotificationRunner>(doc));
10305 // When scripts are not blocked (are they ever blocked here?), the runnable
10306 // runs immediately, so let's check if this docshell got destroyed or the
10307 // document got swapped. Unclear if this ever happens; this is a defensive
10308 // check.
10309 if (mIsBeingDestroyed || !mDocumentViewer ||
10310 doc != mDocumentViewer->GetDocument()) {
10311 return NS_OK;
10312 }
10313
10314 // Initialize the presShell here in the window.open() case.
10315 RefPtr<PresShell> presShell = doc->GetPresShell();
10316 if (presShell && !presShell->DidInitialize()) {
10317 rv = presShell->Initialize();
10318 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"
, 10318); return rv; } } while (false)
;
10319 }
10320
10321 doc->SetScrollToRef(doc->GetDocumentURI());
10322
10323 OnStopRequest(aboutBlankChannel, NS_OK);
10324
10325 // Mechanisms in Document will force a load from EndLoad()
10326 // even if there are still blockers.
10327 doc->EndLoad(/* aFireDOMContentLoadedSync = */ true);
10328 // Can't assert any postcondition, because the load event
10329 // handler may have started loading something new in this
10330 // docshell.
10331
10332 return NS_OK;
10333}
10334
10335static nsresult AppendSegmentToString(nsIInputStream* aIn, void* aClosure,
10336 const char* aFromRawSegment,
10337 uint32_t aToOffset, uint32_t aCount,
10338 uint32_t* aWriteCount) {
10339 // aFromSegment now contains aCount bytes of data.
10340
10341 nsAutoCString* buf = static_cast<nsAutoCString*>(aClosure);
10342 buf->Append(aFromRawSegment, aCount);
10343
10344 // Indicate that we have consumed all of aFromSegment
10345 *aWriteCount = aCount;
10346 return NS_OK;
10347}
10348
10349/* static */ nsresult nsDocShell::AddHeadersToChannel(
10350 nsIInputStream* aHeadersData, nsIChannel* aGenericChannel) {
10351 nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(aGenericChannel);
10352 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", 10352);
return NS_ERROR_UNEXPECTED; } } while (false)
;
10353
10354 uint32_t numRead;
10355 nsAutoCString headersString;
10356 nsresult rv = aHeadersData->ReadSegments(
10357 AppendSegmentToString, &headersString, UINT32_MAX(4294967295U), &numRead);
10358 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"
, 10358); return rv; } } while (false)
;
10359
10360 // used during the manipulation of the String from the InputStream
10361 nsAutoCString headerName;
10362 nsAutoCString headerValue;
10363 int32_t crlf;
10364 int32_t colon;
10365
10366 //
10367 // Iterate over the headersString: for each "\r\n" delimited chunk,
10368 // add the value as a header to the nsIHttpChannel
10369 //
10370
10371 static const char kWhitespace[] = "\b\t\r\n ";
10372 while (true) {
10373 crlf = headersString.Find("\r\n");
10374 if (crlf == kNotFound) {
10375 return NS_OK;
10376 }
10377
10378 const nsACString& oneHeader = StringHead(headersString, crlf);
10379
10380 colon = oneHeader.FindChar(':');
10381 if (colon == kNotFound) {
10382 return NS_ERROR_UNEXPECTED;
10383 }
10384
10385 headerName = StringHead(oneHeader, colon);
10386 headerValue = Substring(oneHeader, colon + 1);
10387
10388 headerName.Trim(kWhitespace);
10389 headerValue.Trim(kWhitespace);
10390
10391 headersString.Cut(0, crlf + 2);
10392
10393 //
10394 // FINALLY: we can set the header!
10395 //
10396
10397 rv = httpChannel->SetRequestHeader(headerName, headerValue, true);
10398 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"
, 10398); return rv; } } while (false)
;
10399 }
10400
10401 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", 10401
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") (" "MOZ_ASSERT_UNREACHABLE: "
"oops" ")"); do { MOZ_CrashSequence(__null, 10401); __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
;
10402 return NS_ERROR_UNEXPECTED;
10403}
10404
10405/* static */ uint32_t nsDocShell::ComputeURILoaderFlags(
10406 BrowsingContext* aBrowsingContext, uint32_t aLoadType,
10407 bool aIsDocumentLoad) {
10408 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", 10408); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aBrowsingContext" ")"); do { MOZ_CrashSequence
(__null, 10408); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
10409
10410 uint32_t openFlags = 0;
10411 if (aLoadType == LOAD_LINK) {
10412 openFlags |= nsIURILoader::IS_CONTENT_PREFERRED;
10413 }
10414 if (!aBrowsingContext->GetAllowContentRetargeting()) {
10415 openFlags |= nsIURILoader::DONT_RETARGET;
10416 }
10417
10418 if (!aIsDocumentLoad) {
10419 openFlags |= nsIURILoader::IS_OBJECT_EMBED;
10420
10421 // Unless the pref is set, object/embed loads always specify DONT_RETARGET.
10422 // See bug 1868001 for details.
10423 if (!StaticPrefs::dom_navigation_object_embed_allow_retargeting()) {
10424 openFlags |= nsIURILoader::DONT_RETARGET;
10425 }
10426 }
10427
10428 return openFlags;
10429}
10430
10431nsresult nsDocShell::OpenInitializedChannel(nsIChannel* aChannel,
10432 nsIURILoader* aURILoader,
10433 uint32_t aOpenFlags) {
10434 nsresult rv = NS_OK;
10435
10436 // If anything fails here, make sure to clear our initial ClientSource.
10437 auto cleanupInitialClient =
10438 MakeScopeExit([&] { mInitialClientSource.reset(); });
10439
10440 nsCOMPtr<nsPIDOMWindowOuter> win = GetWindow();
10441 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"
, 10441); return NS_ERROR_FAILURE; } } while (false)
;
10442
10443 MaybeCreateInitialClientSource();
10444
10445 // Let the client channel helper know if we are using DocumentChannel,
10446 // since redirects get handled in the parent process in that case.
10447 RefPtr<net::DocumentChannel> docChannel = do_QueryObject(aChannel);
10448 if (docChannel && XRE_IsContentProcess()) {
10449 // Tell the content process nsDocumentOpenInfo to not try to do
10450 // any sort of targeting.
10451 aOpenFlags |= nsIURILoader::DONT_RETARGET;
10452 }
10453
10454 // Since we are loading a document we need to make sure the proper reserved
10455 // and initial client data is stored on the nsILoadInfo. The
10456 // ClientChannelHelper does this and ensures that it is propagated properly
10457 // on redirects. We pass no reserved client here so that the helper will
10458 // create the reserved ClientSource if necessary.
10459 Maybe<ClientInfo> noReservedClient;
10460 if (docChannel) {
10461 // When using DocumentChannel, all redirect handling is done in the parent,
10462 // so we just need the child variant to watch for the internal redirect
10463 // to the final channel.
10464 rv = AddClientChannelHelperInChild(aChannel,
10465 GetMainThreadSerialEventTarget());
10466 docChannel->SetInitialClientInfo(GetInitialClientInfo());
10467 } else {
10468 rv = AddClientChannelHelper(aChannel, std::move(noReservedClient),
10469 GetInitialClientInfo(),
10470 GetMainThreadSerialEventTarget());
10471 }
10472 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"
, 10472); return rv; } } while (false)
;
10473
10474 rv = aURILoader->OpenURI(aChannel, aOpenFlags, this);
10475 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"
, 10475); return rv; } } while (false)
;
10476
10477 // We're about to load a new page and it may take time before necko
10478 // gives back any data, so main thread might have a chance to process a
10479 // collector slice
10480 nsJSContext::MaybeRunNextCollectorSlice(this, JS::GCReason::DOCSHELL);
10481
10482 // Success. Keep the initial ClientSource if it exists.
10483 cleanupInitialClient.release();
10484
10485 return NS_OK;
10486}
10487
10488nsresult nsDocShell::OpenRedirectedChannel(nsDocShellLoadState* aLoadState) {
10489 nsCOMPtr<nsIChannel> channel = aLoadState->GetPendingRedirectedChannel();
10490 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"
, 10490); AnnotateMozCrashReason("MOZ_ASSERT" "(" "channel" ")"
); do { MOZ_CrashSequence(__null, 10490); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
10491
10492 // If anything fails here, make sure to clear our initial ClientSource.
10493 auto cleanupInitialClient =
10494 MakeScopeExit([&] { mInitialClientSource.reset(); });
10495
10496 nsCOMPtr<nsPIDOMWindowOuter> win = GetWindow();
10497 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"
, 10497); return NS_ERROR_FAILURE; } } while (false)
;
10498
10499 MaybeCreateInitialClientSource();
10500
10501 nsCOMPtr<nsILoadInfo> loadInfo = channel->LoadInfo();
10502
10503 LoadInfo* li = static_cast<LoadInfo*>(loadInfo.get());
10504 if (loadInfo->GetExternalContentPolicyType() ==
10505 ExtContentPolicy::TYPE_DOCUMENT) {
10506 li->UpdateBrowsingContextID(mBrowsingContext->Id());
10507 } else if (loadInfo->GetExternalContentPolicyType() ==
10508 ExtContentPolicy::TYPE_SUBDOCUMENT) {
10509 li->UpdateFrameBrowsingContextID(mBrowsingContext->Id());
10510 }
10511
10512 // If we did a process switch, then we should have an existing allocated
10513 // ClientInfo, so we just need to allocate a corresponding ClientSource.
10514 CreateReservedSourceIfNeeded(channel, GetMainThreadSerialEventTarget());
10515
10516 uint32_t documentOpenInfoFlags = nsIURILoader::DONT_RETARGET;
10517 if (loadInfo->GetExternalContentPolicyType() ==
10518 ExtContentPolicy::TYPE_OBJECT) {
10519 documentOpenInfoFlags |= nsIURILoader::IS_OBJECT_EMBED;
10520 }
10521
10522 RefPtr loader =
10523 MakeRefPtr<nsDocumentOpenInfo>(this, documentOpenInfoFlags, nullptr);
10524 channel->SetLoadGroup(mLoadGroup);
10525
10526 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", 10526); AnnotateMozCrashReason
("MOZ_CRASH(" "NS_SUCCEEDED(loader->Prepare())" ")"); do {
MOZ_CrashSequence(__null, 10526); __attribute__((nomerge)) ::
abort(); } while (false); } while (false); } } while (false)
;
10527
10528 nsresult rv = NS_OK;
10529 if (XRE_IsParentProcess()) {
10530 // If we're in the parent, the we don't have an nsIChildChannel, just
10531 // the original channel, which is already open in this process.
10532
10533 // DocumentLoadListener expects to get an nsIParentChannel, so
10534 // we create a wrapper around the channel and nsIStreamListener
10535 // that forwards functionality as needed, and then we register
10536 // it under the provided identifier.
10537 RefPtr wrapper = MakeRefPtr<ParentChannelWrapper>(channel, loader);
10538 // We're in the parent process, so the redirect is owned by the parent
10539 // process (ContentParentId 0).
10540 wrapper->Register(aLoadState->GetPendingRedirectChannelRegistrarId(), 0);
10541
10542 mLoadGroup->AddRequest(channel, nullptr);
10543 } else if (nsCOMPtr<nsIChildChannel> childChannel =
10544 do_QueryInterface(channel)) {
10545 // Our channel was redirected from another process, so doesn't need to
10546 // be opened again. However, it does need its listener hooked up
10547 // correctly.
10548 rv = childChannel->CompleteRedirectSetup(loader);
10549 } else {
10550 // It's possible for the redirected channel to not implement
10551 // nsIChildChannel and be entirely local (like srcdoc). In that case we
10552 // can just open the local instance and it will work.
10553 rv = channel->AsyncOpen(loader);
10554 }
10555 if (rv == NS_ERROR_NO_CONTENT) {
10556 return NS_OK;
10557 }
10558 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"
, 10558); return rv; } } while (false)
;
10559
10560 // Success. Keep the initial ClientSource if it exists.
10561 cleanupInitialClient.release();
10562 return NS_OK;
10563}
10564
10565// https://html.spec.whatwg.org/#scrolling-to-a-fragment
10566nsresult nsDocShell::ScrollToAnchor(bool aCurHasRef, bool aNewHasRef,
10567 nsACString& aNewHash, uint32_t aLoadType) {
10568 if (!mCurrentURI) {
10569 return NS_OK;
10570 }
10571
10572 RefPtr<PresShell> presShell = GetPresShell();
10573 if (!presShell) {
10574 // If we failed to get the shell, or if there is no shell,
10575 // nothing left to do here.
10576 return NS_OK;
10577 }
10578
10579 ScrollContainerFrame* rootScroll = presShell->GetRootScrollContainerFrame();
10580 if (rootScroll) {
10581 rootScroll->ClearDidHistoryRestore();
10582 }
10583
10584 // If it's a load from history, we don't have any anchor jumping to do.
10585 // Scrollbar position will be restored by the caller based on positions stored
10586 // in session history.
10587 bool scroll = aLoadType != LOAD_HISTORY && aLoadType != LOAD_RELOAD_NORMAL;
10588 // If the load contains text directives, try to apply them. This may fail if
10589 // the load is a same-document load that was initiated before the document was
10590 // fully loaded and the target is not yet included in the DOM tree.
10591 // For this case, the `uninvokedTextDirectives` are not cleared, so that
10592 // `Document::ScrollToRef()` can re-apply the text directive.
10593 // `Document::ScrollToRef()` is (presumably) the second "async" call mentioned
10594 // in sec. 7.4.2.3.3 in the HTML spec, "Fragment navigations":
10595 // https://html.spec.whatwg.org/#scroll-to-fragid:~:text=This%20algorithm%20will%20be%20called%20twice
10596
10597 const RefPtr fragmentDirective = GetDocument()->FragmentDirective();
10598 const nsTArray<RefPtr<dom::Range>> textDirectiveRanges =
10599 fragmentDirective->FindTextFragmentsInDocument();
10600 fragmentDirective->HighlightTextDirectives(textDirectiveRanges);
10601 const bool scrollToTextDirective =
10602 !textDirectiveRanges.IsEmpty() &&
10603 fragmentDirective->IsTextDirectiveAllowedToBeScrolledTo();
10604 const RefPtr<dom::Range> textDirectiveToScroll =
10605 scrollToTextDirective ? textDirectiveRanges[0] : nullptr;
10606
10607 // If we have no new anchor, we do not want to scroll, unless there is a
10608 // current anchor and we are doing a history load. So return if we have no
10609 // new anchor, and there is no current anchor or the load is not a history
10610 // load.
10611 if ((!aCurHasRef || aLoadType != LOAD_HISTORY) && !aNewHasRef &&
10612 !scrollToTextDirective) {
10613 return NS_OK;
10614 }
10615
10616 // Both the new and current URIs refer to the same page. We can now
10617 // browse to the hash stored in the new URI.
10618
10619 if (aNewHash.IsEmpty() && !scrollToTextDirective) {
10620 // 2. If fragment is the empty string, then return the special value top of
10621 // the document.
10622 //
10623 // Tell the shell it's at an anchor without scrolling.
10624 presShell->GoToAnchor(u""_ns, nullptr, false);
10625
10626 if (scroll) {
10627 // Scroll to the top of the page. Ignore the return value; failure to
10628 // scroll here (e.g. if there is no root scrollframe) is not grounds for
10629 // canceling the load!
10630 SetCurScrollPosEx(0, 0);
10631 }
10632
10633 return NS_OK;
10634 }
10635
10636 // 3. Let potentialIndicatedElement be the result of finding a potential
10637 // indicated element given document and fragment.
10638 NS_ConvertUTF8toUTF16 uStr(aNewHash);
10639
10640 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", 10640); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!uStr.IsEmpty() || scrollToTextDirective" ")"
); do { MOZ_CrashSequence(__null, 10640); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
10641
10642 auto rv = presShell->GoToAnchor(uStr, textDirectiveToScroll, scroll,
10643 ScrollFlags::ScrollSmoothAuto);
10644
10645 // 4. If potentialIndicatedElement is not null, then return
10646 // potentialIndicatedElement.
10647 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
10648 return NS_OK;
10649 }
10650
10651 // 5. Let fragmentBytes be the result of percent-decoding fragment.
10652 nsAutoCString fragmentBytes;
10653 const bool unescaped = NS_UnescapeURL(aNewHash.Data(), aNewHash.Length(),
10654 /* aFlags = */ 0, fragmentBytes);
10655
10656 if (!unescaped) {
10657 // Another attempt is only necessary if characters were unescaped.
10658 return NS_OK;
10659 }
10660
10661 if (fragmentBytes.IsEmpty()) {
10662 // When aNewHash contains "%00", the unescaped string may be empty, and
10663 // GoToAnchor asserts if we ask it to scroll to an empty ref.
10664 presShell->GoToAnchor(u""_ns, nullptr, false);
10665 return NS_OK;
10666 }
10667
10668 // 6. Let decodedFragment be the result of running UTF-8 decode without BOM on
10669 // fragmentBytes.
10670 nsAutoString decodedFragment;
10671 rv = UTF_8_ENCODING->DecodeWithoutBOMHandling(fragmentBytes, decodedFragment);
10672 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"
, 10672); return rv; } } while (false)
;
10673
10674 // 7. Set potentialIndicatedElement to the result of finding a potential
10675 // indicated element given document and decodedFragment.
10676 //
10677 // Ignore the return value of GoToAnchor, since it will return an error if
10678 // there is no such anchor in the document, which is actually a success
10679 // condition for us (we want to update the session history with the new URI no
10680 // matter whether we actually scrolled somewhere).
10681 presShell->GoToAnchor(decodedFragment, nullptr, scroll,
10682 ScrollFlags::ScrollSmoothAuto);
10683
10684 return NS_OK;
10685}
10686
10687bool nsDocShell::OnNewURI(nsIURI* aURI, nsIChannel* aChannel,
10688 nsIPrincipal* aTriggeringPrincipal,
10689 nsIPrincipal* aPrincipalToInherit,
10690 nsIPrincipal* aPartitionedPrincipalToInherit,
10691 nsIPolicyContainer* aPolicyContainer,
10692 bool aAddToGlobalHistory, bool aCloneSHChildren) {
10693 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"
, 10693); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aURI" ") ("
"uri is null" ")"); do { MOZ_CrashSequence(__null, 10693); __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
;
10694 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", 10694); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!aChannel || !aTriggeringPrincipal" ") (" "Shouldn't have both set"
")"); do { MOZ_CrashSequence(__null, 10694); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10695
10696 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", 10697); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!aPrincipalToInherit || (aPrincipalToInherit && aTriggeringPrincipal)"
")"); do { MOZ_CrashSequence(__null, 10697); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
10697 (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", 10697); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!aPrincipalToInherit || (aPrincipalToInherit && aTriggeringPrincipal)"
")"); do { MOZ_CrashSequence(__null, 10697); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10698
10699#if defined(DEBUG1)
10700 if (MOZ_LOG_TEST(gDocShellLog, LogLevel::Debug)(__builtin_expect(!!(mozilla::detail::log_test(gDocShellLog, LogLevel
::Debug)), 0))
) {
10701 nsAutoCString chanName;
10702 if (aChannel) {
10703 aChannel->GetName(chanName);
10704 } else {
10705 chanName.AssignLiteral("<no channel>");
10706 }
10707
10708 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)
10709 ("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)
10710 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)
;
10711 }
10712#endif
10713
10714 bool equalUri = false;
10715
10716 // Get the post data and the HTTP response code from the channel.
10717 uint32_t responseStatus = 0;
10718 nsCOMPtr<nsIInputStream> inputStream;
10719 if (aChannel) {
10720 nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(aChannel));
10721
10722 // Check if the HTTPChannel is hiding under a multiPartChannel
10723 if (!httpChannel) {
10724 GetHttpChannel(aChannel, getter_AddRefs(httpChannel));
10725 }
10726
10727 if (httpChannel) {
10728 nsCOMPtr<nsIUploadChannel> uploadChannel(do_QueryInterface(httpChannel));
10729 if (uploadChannel) {
10730 uploadChannel->GetUploadStream(getter_AddRefs(inputStream));
10731 }
10732 }
10733 }
10734
10735 // Determine if this type of load should update history.
10736 bool updateGHistory = ShouldUpdateGlobalHistory(mLoadType);
10737
10738 // We don't update session history on reload unless we're loading
10739 // an iframe in shift-reload case.
10740 [[maybe_unused]] bool updateSHistory =
10741 mBrowsingContext->ShouldUpdateSessionHistory(mLoadType);
10742
10743 // Create SH Entry (mLSHE) only if there is a SessionHistory object in the
10744 // root browsing context.
10745 // FIXME If session history in the parent is enabled then we only do this if
10746 // the session history object is in process, otherwise we can't really
10747 // use the mLSHE anyway. Once session history is only stored in the
10748 // parent then this code will probably be removed anyway.
10749 RefPtr<ChildSHistory> rootSH = GetRootSessionHistory();
10750 if (!rootSH) {
10751 updateSHistory = false;
10752 updateGHistory = false; // XXX Why global history too?
10753 }
10754
10755 // Check if the url to be loaded is the same as the one already loaded.
10756 if (mCurrentURI) {
10757 aURI->Equals(mCurrentURI, &equalUri);
10758 }
10759
10760#ifdef DEBUG1
10761 bool shAvailable = (rootSH != nullptr);
10762
10763 // XXX This log message is almost useless because |updateSHistory|
10764 // and |updateGHistory| are not correct at this point.
10765
10766 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)
10767 (" 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)
10768 " 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)
10769 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)
;
10770#endif
10771
10772 /* If the url to be loaded is the same as the one already there,
10773 * and the original loadType is LOAD_NORMAL, LOAD_LINK, or
10774 * LOAD_STOP_CONTENT, set loadType to LOAD_NORMAL_REPLACE so that
10775 * AddToSessionHistory() won't mess with the current SHEntry and
10776 * if this page has any frame children, it also will be handled
10777 * properly. see bug 83684
10778 *
10779 * NB: If mOSHE is null but we have a current URI, then it probably
10780 * means that we must be at the transient about:blank content viewer;
10781 * we should let the normal load continue, since there's nothing to
10782 * replace. Sometimes this happens after a session restore (eg process
10783 * switch) and mCurrentURI is not about:blank; we assume we can let the load
10784 * continue (Bug 1301399).
10785 *
10786 * XXX Hopefully changing the loadType at this time will not hurt
10787 * anywhere. The other way to take care of sequentially repeating
10788 * frameset pages is to add new methods to nsIDocShellTreeItem.
10789 * Hopefully I don't have to do that.
10790 */
10791 if (equalUri && mActiveEntry &&
10792 (mLoadType == LOAD_NORMAL || mLoadType == LOAD_LINK ||
10793 mLoadType == LOAD_STOP_CONTENT) &&
10794 !inputStream) {
10795 mLoadType = LOAD_NORMAL_REPLACE;
10796 }
10797
10798 /* If the user pressed shift-reload, cache will create a new cache key
10799 * for the page. Save the new cacheKey in Session History.
10800 * see bug 90098
10801 */
10802 if (aChannel && IsForceReloadType(mLoadType)) {
10803 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"
, 10805); 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, 10805); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
10804 "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"
, 10805); 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, 10805); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
10805 " 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"
, 10805); 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, 10805); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10806
10807 nsCOMPtr<nsICacheInfoChannel> cacheChannel(do_QueryInterface(aChannel));
10808 uint32_t cacheKey = 0;
10809 // Get the Cache Key and store it in SH.
10810 if (cacheChannel) {
10811 cacheChannel->GetCacheKey(&cacheKey);
10812 }
10813 // If we already have a loading history entry, store the new cache key
10814 // in it. Otherwise, since we're doing a reload and won't be updating
10815 // our history entry, store the cache key in our current history entry.
10816 SetCacheKeyOnHistoryEntry(cacheKey);
10817 }
10818
10819 if (ShouldAddURIVisit(aChannel) && updateGHistory && aAddToGlobalHistory) {
10820 nsCOMPtr<nsIURI> previousURI;
10821 uint32_t previousFlags = 0;
10822
10823 if (mLoadType & LOAD_CMD_RELOAD) {
10824 // On a reload request, we don't set redirecting flags.
10825 previousURI = aURI;
10826 } else {
10827 ExtractLastVisit(aChannel, getter_AddRefs(previousURI), &previousFlags);
10828 }
10829
10830 AddURIVisit(aURI, previousURI, previousFlags, responseStatus,
10831 net::ChannelIsPost(aChannel));
10832 }
10833
10834 // aCloneSHChildren exactly means "we are not loading a new document".
10835 uint32_t locationFlags =
10836 aCloneSHChildren ? uint32_t(LOCATION_CHANGE_SAME_DOCUMENT) : 0;
10837
10838 bool onLocationChangeNeeded =
10839 SetCurrentURI(aURI, aChannel, false,
10840 /* aIsInitialAboutBlank */ false, locationFlags);
10841 // Make sure to store the referrer from the channel, if any
10842 nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(aChannel));
10843 if (httpChannel) {
10844 mReferrerInfo = httpChannel->GetReferrerInfo();
10845 }
10846 return onLocationChangeNeeded;
10847}
10848
10849Maybe<Wireframe> nsDocShell::GetWireframe() {
10850 const bool collectWireFrame =
10851 StaticPrefs::browser_history_collectWireframes() &&
10852 mBrowsingContext->IsTopContent() && mActiveEntry;
10853
10854 if (!collectWireFrame) {
10855 return Nothing();
10856 }
10857
10858 RefPtr<Document> doc = mDocumentViewer->GetDocument();
10859 Nullable<Wireframe> wireframe;
10860 doc->GetWireframeWithoutFlushing(false, wireframe);
10861 if (wireframe.IsNull()) {
10862 return Nothing();
10863 }
10864 return Some(wireframe.Value());
10865}
10866
10867bool nsDocShell::CollectWireframe() {
10868 Maybe<Wireframe> wireframe = GetWireframe();
10869 if (wireframe.isNothing()) {
10870 return false;
10871 }
10872
10873 if (XRE_IsParentProcess()) {
10874 SessionHistoryEntry* entry =
10875 mBrowsingContext->Canonical()->GetActiveSessionHistoryEntry();
10876 if (entry) {
10877 entry->SetWireframe(wireframe);
10878 }
10879 } else {
10880 (void)ContentChild::GetSingleton()->SendSessionHistoryEntryWireframe(
10881 mBrowsingContext, wireframe.ref());
10882 }
10883
10884 return true;
10885}
10886
10887//*****************************************************************************
10888// nsDocShell: Session History
10889//*****************************************************************************
10890
10891nsresult nsDocShell::AddState(JS::Handle<JS::Value> aData,
10892 const nsAString& aTitle, const nsAString& aURL,
10893 CallerType aCallerType, bool aReplace,
10894 JSContext* aCx) {
10895 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)
10896 ("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)
10897 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)
10898 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)
;
10899 // Implements History.pushState and History.replaceState
10900
10901 // Here's what we do, roughly in the order specified by HTML5. The specific
10902 // steps we are executing are at
10903 // <https://html.spec.whatwg.org/multipage/history.html#dom-history-pushstate>,
10904 // <https://html.spec.whatwg.org/#shared-history-push/replace-state-steps>,
10905 // and
10906 // <https://html.spec.whatwg.org/multipage/history.html#url-and-history-update-steps>.
10907 // This function basically implements #dom-history-pushstate and
10908 // UpdateURLAndHistory implements #url-and-history-update-steps.
10909 //
10910 // A. Serialize aData using structured clone. This is #dom-history-pushstate
10911 // step 5.
10912 // B. If the third argument is present, #dom-history-pushstate step 7.
10913 // 7.1. Resolve the url, relative to our document.
10914 // 7.2. If (a) fails, raise a SECURITY_ERR
10915 // 7.4. Compare the resulting absolute URL to the document's address. If
10916 // any part of the URLs difer other than the <path>, <query>, and
10917 // <fragment> components, raise a SECURITY_ERR and abort.
10918 // C. If !aReplace, #url-and-history-update-steps steps 2.1-2.3:
10919 // Remove from the session history all entries after the current entry,
10920 // as we would after a regular navigation, and save the current
10921 // entry's scroll position (bug 590573).
10922 // D. #url-and-history-update-steps step 2.4 or step 3. As apropriate,
10923 // either add a state object entry to the session history after the
10924 // current entry with the following properties, or modify the current
10925 // session history entry to set
10926 // a. cloned data as the state object,
10927 // b. if the third argument was present, the absolute URL found in
10928 // step 2
10929 // Also clear the new history entry's POST data (see bug 580069).
10930 // E. If aReplace is false (i.e. we're doing a pushState instead of a
10931 // replaceState), notify bfcache that we've navigated to a new page.
10932 // F. If the third argument is present, set the document's current address
10933 // to the absolute URL found in step B. This is
10934 // #url-and-history-update-steps step 4.
10935 //
10936 // It's important that this function not run arbitrary scripts after step A
10937 // and before completing step E. For example, if a script called
10938 // history.back() before we completed step E, bfcache might destroy an
10939 // active content viewer. Since EvictOutOfRangeDocumentViewers at the end of
10940 // step E might run script, we can't just put a script blocker around the
10941 // critical section.
10942 //
10943 // Note that we completely ignore the aTitle parameter.
10944
10945 nsresult rv;
10946
10947 RefPtr<Document> document = GetDocument();
10948 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", 10948); return NS_ERROR_FAILURE
; } } while (false)
;
10949
10950 // Don't clobber the load type of an existing network load.
10951 Maybe<AutoRestore<uint32_t>> loadTypeResetter;
10952 if (StaticPrefs::
10953 docshell_shistory_sameDocumentNavigationOverridesLoadType() &&
10954 !document->NodePrincipal()->IsURIInPrefList(
10955 "docshell.shistory.sameDocumentNavigationOverridesLoadType."
10956 "forceDisable")) {
10957 loadTypeResetter.emplace(mLoadType);
10958 }
10959
10960 // pushState effectively becomes replaceState when we've started a network
10961 // load but haven't adopted its document yet. This mirrors what we do with
10962 // changes to the hash at this stage of the game.
10963 if (JustStartedNetworkLoad()) {
10964 if (!loadTypeResetter.isSome()) {
10965 loadTypeResetter.emplace(mLoadType);
10966 }
10967 aReplace = true;
10968 }
10969
10970 // Step A: Serialize aData using structured clone.
10971 // https://html.spec.whatwg.org/multipage/history.html#dom-history-pushstate
10972 // step 5.
10973 nsCOMPtr<nsIStructuredCloneContainer> scContainer;
10974
10975 // scContainer->Init might cause arbitrary JS to run, and this code might
10976 // navigate the page we're on, potentially to a different origin! (bug
10977 // 634834) To protect against this, we abort if our principal changes due
10978 // to the InitFromJSVal() call.
10979 {
10980 RefPtr<Document> origDocument = GetDocument();
10981 if (!origDocument) {
10982 return NS_ERROR_DOM_SECURITY_ERR;
10983 }
10984 nsCOMPtr<nsIPrincipal> origPrincipal = origDocument->NodePrincipal();
10985
10986 scContainer = new nsStructuredCloneContainer();
10987 rv = scContainer->InitFromJSVal(aData, aCx);
10988 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"
, 10988); return rv; } } while (false)
;
10989
10990 RefPtr<Document> newDocument = GetDocument();
10991 if (!newDocument) {
10992 return NS_ERROR_DOM_SECURITY_ERR;
10993 }
10994 nsCOMPtr<nsIPrincipal> newPrincipal = newDocument->NodePrincipal();
10995
10996 bool principalsEqual = false;
10997 origPrincipal->Equals(newPrincipal, &principalsEqual);
10998 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", 10998);
return NS_ERROR_DOM_SECURITY_ERR; } } while (false)
;
10999 }
11000
11001 // Check that the state object isn't too long.
11002 int32_t maxStateObjSize = StaticPrefs::browser_history_maxStateObjectSize();
11003 if (maxStateObjSize < 0) {
11004 maxStateObjSize = 0;
11005 }
11006
11007 uint64_t scSize;
11008 rv = scContainer->GetSerializedNBytes(&scSize);
11009 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"
, 11009); return rv; } } while (false)
;
11010
11011 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"
, 11011); return NS_ERROR_ILLEGAL_VALUE; } } while (false)
;
11012
11013 // Step B: Resolve aURL.
11014 // https://html.spec.whatwg.org/multipage/history.html#dom-history-pushstate
11015 // step 7.
11016 bool equalURIs = true;
11017 nsCOMPtr<nsIURI> currentURI;
11018 if (mCurrentURI) {
11019 currentURI = nsIOService::CreateExposableURI(mCurrentURI);
11020 } else {
11021 currentURI = mCurrentURI;
11022 }
11023 nsCOMPtr<nsIURI> newURI;
11024 if (aURL.Length() == 0) {
11025 newURI = currentURI;
11026 } else {
11027 // 7.1: Resolve aURL relative to mURI
11028
11029 nsIURI* docBaseURI = document->GetDocBaseURI();
11030 if (!docBaseURI) {
11031 return NS_ERROR_FAILURE;
11032 }
11033
11034 nsAutoCString spec;
11035 docBaseURI->GetSpec(spec);
11036
11037 rv = NS_NewURI(getter_AddRefs(newURI), aURL,
11038 document->GetDocumentCharacterSet(), docBaseURI);
11039
11040 // 7.2: If 2a fails, raise a SECURITY_ERR
11041 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
11042 return NS_ERROR_DOM_SECURITY_ERR;
11043 }
11044
11045 if (!document->CanRewriteURL(newURI)) {
11046 return NS_ERROR_DOM_SECURITY_ERR;
11047 }
11048
11049 if (currentURI) {
11050 currentURI->Equals(newURI, &equalURIs);
11051 } else {
11052 equalURIs = false;
11053 }
11054
11055 } // end of same-origin check
11056
11057 if (!mBrowsingContext->CheckNavigationRateLimit(aCallerType)) {
11058 return NS_OK;
11059 }
11060
11061 // https://html.spec.whatwg.org/#shared-history-push/replace-state-steps
11062 // Step 8
11063 if (nsCOMPtr<nsPIDOMWindowInner> window = document->GetInnerWindow()) {
11064 if (RefPtr<Navigation> navigation = window->Navigation()) {
11065 bool shouldContinue = navigation->FirePushReplaceReloadNavigateEvent(
11066 aCx, aReplace ? NavigationType::Replace : NavigationType::Push,
11067 newURI,
11068 /* aIsSameDocument */ true,
11069 /* aUserInvolvement */ Nothing(),
11070 /* aSourceElement */ nullptr, /* aFormDataEntryList */ nullptr,
11071 /* aNavigationAPIState */ nullptr, scContainer);
11072
11073 // Step 9
11074 if (!shouldContinue) {
11075 return NS_OK;
11076 }
11077 }
11078 }
11079
11080 // Step 10
11081 // Run #url-and-history-update-steps
11082 rv = UpdateURLAndHistory(document, newURI, scContainer,
11083 aReplace ? NavigationHistoryBehavior::Replace
11084 : NavigationHistoryBehavior::Push,
11085 currentURI, equalURIs);
11086 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"
, 11086); return rv; } } while (false)
;
11087
11088 return NS_OK;
11089}
11090
11091nsresult nsDocShell::UpdateURLAndHistory(
11092 Document* aDocument, nsIURI* aNewURI, nsIStructuredCloneContainer* aData,
11093 NavigationHistoryBehavior aHistoryHandling, nsIURI* aCurrentURI,
11094 bool aEqualURIs, bool aFiredNavigateEvent) {
11095 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)
11096 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)
;
11097
11098 // Implements
11099 // https://html.spec.whatwg.org/multipage/history.html#url-and-history-update-steps
11100 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", 11100); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aHistoryHandling != NavigationHistoryBehavior::Auto"
")"); do { MOZ_CrashSequence(__null, 11100); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11101 bool isReplace = aHistoryHandling == NavigationHistoryBehavior::Replace;
11102
11103 // If we have a pending title change, handle it before creating a new entry.
11104 aDocument->DoNotifyPossibleTitleChange();
11105
11106 // Step 2, if aReplace is false: Create a new entry in the session
11107 // history. This will erase all SHEntries after the new entry and make this
11108 // entry the current one.
11109 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"
, 11109); return NS_ERROR_FAILURE; } } while (false)
;
11110
11111 // If this push/replaceState changed the document's current URI and the new
11112 // URI differs from the old URI in more than the hash, or if the old
11113 // SHEntry's URI was modified in this way by a push/replaceState call
11114 // set URIWasModified to true for the current SHEntry (bug 669671).
11115 bool sameExceptHashes = true;
11116 aNewURI->EqualsExceptRef(aCurrentURI, &sameExceptHashes);
11117 bool uriWasModified;
11118 if (sameExceptHashes) {
11119 uriWasModified = mActiveEntry && mActiveEntry->GetURIWasModified();
11120 } else {
11121 uriWasModified = true;
11122 }
11123
11124 mLoadType = LOAD_PUSHSTATE;
11125
11126 RefPtr<SessionHistoryEntry> newSHEntry;
11127 if (!isReplace) {
11128 // Step 2.
11129
11130 // Step 2.2, "Remove any tasks queued by the history traversal task
11131 // source that are associated with any Document objects in the
11132 // top-level browsing context's document family." This is very hard in
11133 // SessionHistoryInParent since we can't synchronously access the
11134 // pending navigations that are already sent to the parent. We can
11135 // abort any AsyncGo navigations that are waiting to be sent. If we
11136 // send a message to the parent, it would be processed after any
11137 // navigations previously sent. So long as we consider the "history
11138 // traversal task source" to be the list in this process we match the
11139 // spec. If we move the entire list to the parent, we can handle the
11140 // aborting of loads there, but we don't have a way to synchronously
11141 // remove entries as we do here for non-SHIP.
11142 RefPtr<ChildSHistory> shistory = GetRootSessionHistory();
11143 if (shistory) {
11144 shistory->RemovePendingHistoryNavigations();
11145 }
11146
11147 nsPoint scrollPos = GetCurScrollPos();
11148
11149 bool scrollRestorationIsManual;
11150 // FIXME Need to save the current scroll position on mActiveEntry.
11151 scrollRestorationIsManual = mActiveEntry->GetScrollRestorationIsManual();
11152
11153 nsCOMPtr<nsIPolicyContainer> policyContainer =
11154 aDocument->GetPolicyContainer();
11155
11156 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)
11157 ("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)
;
11158
11159 nsString title(mActiveEntry->GetTitle());
11160 nsCOMPtr<nsIReferrerInfo> referrerInfo = mActiveEntry->GetReferrerInfo();
11161
11162 UpdateActiveEntry(false,
11163 /* aPreviousScrollPos = */ Some(scrollPos), aNewURI,
11164 /* aReferrerInfo = */ referrerInfo,
11165 /* aTriggeringPrincipal = */ aDocument->NodePrincipal(),
11166 policyContainer, title, scrollRestorationIsManual, aData,
11167 uriWasModified);
11168 } else {
11169 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)
11170 ("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)
11171 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)
;
11172 // We don't use aTitle here, see bug 544535.
11173 nsString title;
11174 nsCOMPtr<nsIReferrerInfo> referrerInfo;
11175 if (mActiveEntry) {
11176 title = mActiveEntry->GetTitle();
11177 referrerInfo = mActiveEntry->GetReferrerInfo();
11178 } else {
11179 referrerInfo = nullptr;
11180 }
11181 UpdateActiveEntry(
11182 true, /* aPreviousScrollPos = */ Nothing(), aNewURI,
11183 /* aReferrerInfo = */ referrerInfo, aDocument->NodePrincipal(),
11184 aDocument->GetPolicyContainer(), title,
11185 mActiveEntry && mActiveEntry->GetScrollRestorationIsManual(), aData,
11186 uriWasModified);
11187 }
11188
11189 // Step 4: If the document's URI changed, update document's URI and update
11190 // global history.
11191 //
11192 // We need to call FireOnLocationChange so that the browser's address bar
11193 // gets updated and the back button is enabled, but we only need to
11194 // explicitly call FireOnLocationChange if we're not calling SetCurrentURI,
11195 // since SetCurrentURI will call FireOnLocationChange for us.
11196 //
11197 // Both SetCurrentURI(...) and FireDummyOnLocationChange() pass
11198 // nullptr for aRequest param to FireOnLocationChange(...). Such an update
11199 // notification is allowed only when we know docshell is not loading a new
11200 // document and it requires LOCATION_CHANGE_SAME_DOCUMENT flag. Otherwise,
11201 // FireOnLocationChange(...) breaks security UI.
11202 //
11203 // If the docshell is shutting down, don't update the document URI, as we
11204 // can't load into a docshell that is being destroyed.
11205 if (!aEqualURIs && !mIsBeingDestroyed) {
11206 aDocument->SetDocumentURI(aNewURI);
11207 SetCurrentURI(aNewURI, nullptr, /* aFireLocationChange */ true,
11208 /* aIsInitialAboutBlank */ false,
11209 GetSameDocumentNavigationFlags(aNewURI));
11210
11211 AddURIVisit(aNewURI, aCurrentURI, 0);
11212
11213 // AddURIVisit doesn't set the title for the new URI in global history,
11214 // so do that here.
11215 UpdateGlobalHistoryTitle(aNewURI);
11216
11217 // Inform the favicon service that our old favicon applies to this new
11218 // URI.
11219 CopyFavicon(aCurrentURI, aNewURI, UsePrivateBrowsing());
11220 } else {
11221 FireDummyOnLocationChange();
11222 }
11223 aDocument->SetStateObject(aData);
11224
11225 if (RefPtr navigation = aDocument->GetInnerWindow()->Navigation()) {
11226 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)
11227 ("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)
11228 "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)
11229 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)
;
11230 // Step 11: Update the navigation API entries for a same-document
11231 // navigation given document's relevant global object's navigation API,
11232 // newEntry, and historyHandling.
11233 navigation->UpdateEntriesForSameDocumentNavigation(
11234 mActiveEntry.get(),
11235 isReplace ? NavigationType::Replace : NavigationType::Push,
11236 aFiredNavigateEvent);
11237 }
11238
11239 return NS_OK;
11240}
11241
11242NS_IMETHODIMPnsresult
11243nsDocShell::GetCurrentScrollRestorationIsManual(bool* aIsManual) {
11244 *aIsManual = mActiveEntry && mActiveEntry->GetScrollRestorationIsManual();
11245 return NS_OK;
11246}
11247
11248NS_IMETHODIMPnsresult
11249nsDocShell::SetCurrentScrollRestorationIsManual(bool aIsManual) {
11250 SetScrollRestorationIsManualOnHistoryEntry(aIsManual);
11251
11252 return NS_OK;
11253}
11254
11255void nsDocShell::SetScrollRestorationIsManualOnHistoryEntry(bool aIsManual) {
11256 if (mActiveEntry && mBrowsingContext) {
11257 mActiveEntry->SetScrollRestorationIsManual(aIsManual);
11258 if (XRE_IsParentProcess()) {
11259 SessionHistoryEntry* entry =
11260 mBrowsingContext->Canonical()->GetActiveSessionHistoryEntry();
11261 if (entry) {
11262 entry->SetScrollRestorationIsManual(aIsManual);
11263 }
11264 } else {
11265 (void)ContentChild::GetSingleton()
11266 ->SendSessionHistoryEntryScrollRestorationIsManual(mBrowsingContext,
11267 aIsManual);
11268 }
11269 }
11270}
11271
11272void nsDocShell::SetCacheKeyOnHistoryEntry(uint32_t aCacheKey) {
11273 if (mActiveEntry && mBrowsingContext) {
11274 mActiveEntry->SetCacheKey(aCacheKey);
11275 if (XRE_IsParentProcess()) {
11276 SessionHistoryEntry* entry =
11277 mBrowsingContext->Canonical()->GetActiveSessionHistoryEntry();
11278 if (entry) {
11279 entry->SetCacheKey(aCacheKey);
11280 }
11281 } else {
11282 (void)ContentChild::GetSingleton()->SendSessionHistoryEntryCacheKey(
11283 mBrowsingContext, aCacheKey);
11284 }
11285 }
11286}
11287
11288void nsDocShell::UpdateActiveEntry(
11289 bool aReplace, const Maybe<nsPoint>& aPreviousScrollPos, nsIURI* aURI,
11290 nsIReferrerInfo* aReferrerInfo, nsIPrincipal* aTriggeringPrincipal,
11291 nsIPolicyContainer* aPolicyContainer, const nsAString& aTitle,
11292 bool aScrollRestorationIsManual, nsIStructuredCloneContainer* aData,
11293 bool aURIWasModified) {
11294 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"
, 11294); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aURI" ") ("
"uri is null" ")"); do { MOZ_CrashSequence(__null, 11294); __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
;
11295 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"
, 11296); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mLoadType == LOAD_PUSHSTATE"
") (" "This code only deals with pushState" ")"); do { MOZ_CrashSequence
(__null, 11296); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
11296 "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"
, 11296); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mLoadType == LOAD_PUSHSTATE"
") (" "This code only deals with pushState" ")"); do { MOZ_CrashSequence
(__null, 11296); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
11297 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", 11297
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aReplace" ")"); do
{ MOZ_CrashSequence(__null, 11297); __attribute__((nomerge))
::abort(); } while (false); } } while (false); } } while (false
)
;
11298
11299 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)
11300 ("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)
11301 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)
;
11302
11303 // Even if we're replacing an existing entry we create new a
11304 // SessionHistoryInfo. In the parent process we'll keep the existing
11305 // SessionHistoryEntry, but just replace its SessionHistoryInfo, that way the
11306 // entry keeps identity but its data is replaced.
11307 bool replace = aReplace && mActiveEntry;
11308
11309 if (!replace) {
11310 CollectWireframe();
11311 }
11312
11313 UniquePtr<SessionHistoryInfo> previousActiveEntry(mActiveEntry.release());
11314 if (previousActiveEntry) {
11315 // Link this entry to the previous active entry.
11316 mActiveEntry = MakeUnique<SessionHistoryInfo>(*previousActiveEntry, aURI);
11317 } else {
11318 Document* doc = GetDocument();
11319 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"
, 11319); AnnotateMozCrashReason("MOZ_ASSERT" "(" "doc" ")");
do { MOZ_CrashSequence(__null, 11319); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
11320 mActiveEntry = MakeUnique<SessionHistoryInfo>(
11321 aURI, aTriggeringPrincipal, doc->NodePrincipal(), nullptr,
11322 aPolicyContainer, mContentTypeHint);
11323 }
11324 mActiveEntry->SetUnstrippedURI(nullptr);
11325 mActiveEntry->SetReferrerInfo(aReferrerInfo);
11326 mActiveEntry->SetTitle(aTitle);
11327 mActiveEntry->SetStateData(static_cast<nsStructuredCloneContainer*>(aData));
11328 mActiveEntry->SetURIWasModified(aURIWasModified);
11329 mActiveEntry->SetScrollRestorationIsManual(aScrollRestorationIsManual);
11330
11331 if (replace) {
11332 mActiveEntry->NavigationKey() = previousActiveEntry->NavigationKey();
11333 mBrowsingContext->ReplaceActiveSessionHistoryEntry(mActiveEntry.get());
11334 } else {
11335 mBrowsingContext->IncrementHistoryEntryCountForBrowsingContext();
11336 // FIXME We should probably just compute mChildOffset in the parent
11337 // instead of passing it over IPC here.
11338 mBrowsingContext->SetActiveSessionHistoryEntry(
11339 aPreviousScrollPos, mActiveEntry.get(), previousActiveEntry.get(),
11340 mLoadType,
11341 /* aCacheKey = */ 0);
11342 // FIXME Do we need to update mPreviousEntryIndex and mLoadedEntryIndex?
11343 }
11344}
11345
11346nsresult nsDocShell::LoadHistoryEntry(const LoadingSessionHistoryInfo& aEntry,
11347 uint32_t aLoadType, bool aUserActivation,
11348 bool aNotifiedBeforeUnloadListeners,
11349 bool aIsResumingInterceptedNavigation) {
11350 RefPtr<nsDocShellLoadState> loadState = aEntry.CreateLoadInfo();
11351 loadState->SetHasValidUserGestureActivation(
11352 loadState->HasValidUserGestureActivation() || aUserActivation);
11353
11354 loadState->SetTextDirectiveUserActivation(
11355 loadState->GetTextDirectiveUserActivation() || aUserActivation);
11356
11357 loadState->SetNotifiedBeforeUnloadListeners(aNotifiedBeforeUnloadListeners);
11358
11359 loadState->SetIsResumingInterceptedNavigation(
11360 aIsResumingInterceptedNavigation);
11361
11362 return LoadHistoryEntry(loadState, aLoadType, aEntry.mLoadingCurrentEntry);
11363}
11364
11365void nsDocShell::MaybeFireTraverseHistory(nsDocShellLoadState* aLoadState) {
11366 if (!Navigation::IsAPIEnabled()) {
11367 return;
11368 }
11369
11370 BrowsingContext* browsingContext = GetBrowsingContext();
11371 if (!browsingContext || browsingContext->IsTop()) {
11372 return;
11373 }
11374
11375 if (!mActiveEntry || !aLoadState->GetLoadingSessionHistoryInfo() ||
11376 aLoadState->IsResumingInterceptedNavigation()) {
11377 return;
11378 }
11379 if (mActiveEntry->NavigationKey() ==
11380 aLoadState->GetLoadingSessionHistoryInfo()->mInfo.NavigationKey()) {
11381 return;
11382 }
11383
11384 nsCOMPtr activeURI = mActiveEntry->GetURIOrInheritedForAboutBlank();
11385 nsCOMPtr<nsIURI> loadingURI = aLoadState->GetLoadingSessionHistoryInfo()
11386 ->mInfo.GetURIOrInheritedForAboutBlank();
11387 if (NS_FAILED(nsContentUtils::GetSecurityManager()->CheckSameOriginURI(((bool)(__builtin_expect(!!(NS_FAILED_impl(nsContentUtils::GetSecurityManager
()->CheckSameOriginURI( activeURI, loadingURI, false, false
))), 0)))
11388 activeURI, loadingURI,((bool)(__builtin_expect(!!(NS_FAILED_impl(nsContentUtils::GetSecurityManager
()->CheckSameOriginURI( activeURI, loadingURI, false, false
))), 0)))
11389 /*reportError=*/false,((bool)(__builtin_expect(!!(NS_FAILED_impl(nsContentUtils::GetSecurityManager
()->CheckSameOriginURI( activeURI, loadingURI, false, false
))), 0)))
11390 /*fromPrivateWindow=*/false))((bool)(__builtin_expect(!!(NS_FAILED_impl(nsContentUtils::GetSecurityManager
()->CheckSameOriginURI( activeURI, loadingURI, false, false
))), 0)))
) {
11391 return;
11392 }
11393
11394 if (RefPtr window = GetActiveWindow()) {
11395 if (RefPtr navigation = window->Navigation()) {
11396 if (AutoJSAPI jsapi; jsapi.Init(window)) {
11397 // This should send the correct user involvment. See bug 1903552.
11398 navigation->FireTraverseNavigateEvent(jsapi.cx(), aLoadState,
11399 Nothing());
11400 }
11401 }
11402 }
11403}
11404
11405nsIDocumentViewer::PermitUnloadResult
11406nsDocShell::MaybeFireTraversableTraverseHistory(
11407 nsDocShellLoadState* aLoadState,
11408 Maybe<UserNavigationInvolvement> aUserInvolvement) {
11409 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", 11409); AnnotateMozCrashReason
("MOZ_DIAGNOSTIC_ASSERT" "(" "GetBrowsingContext()" ")"); do {
MOZ_CrashSequence(__null, 11409); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
11410 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"
, 11410); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "GetBrowsingContext()->IsTop()"
")"); do { MOZ_CrashSequence(__null, 11410); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11411
11412 SetOngoingNavigation(Some(OngoingNavigation::Traversal));
11413
11414 nsIDocumentViewer::PermitUnloadResult finalStatus =
11415 nsIDocumentViewer::eContinue;
11416 if (RefPtr<nsPIDOMWindowInner> activeWindow = GetActiveWindow()) {
11417 if (RefPtr navigation = activeWindow->Navigation()) {
11418 if (AutoJSAPI jsapi; jsapi.Init(activeWindow)) {
11419 bool shouldContinue = navigation->FireTraverseNavigateEvent(
11420 jsapi.cx(), aLoadState, aUserInvolvement);
11421
11422 if (!shouldContinue) {
11423 finalStatus = nsIDocumentViewer::eCanceledByNavigate;
11424 }
11425 }
11426 }
11427 }
11428
11429 return finalStatus;
11430}
11431
11432nsresult nsDocShell::LoadHistoryEntry(nsDocShellLoadState* aLoadState,
11433 uint32_t aLoadType,
11434 bool aLoadingCurrentEntry) {
11435 if (!IsNavigationAllowed()) {
11436 return NS_OK;
11437 }
11438
11439 // https://html.spec.whatwg.org/#navigate-to-a-javascript:-url
11440 // Step 13: historyEntry should store entryToReplace's URL.
11441 if (aLoadState->URI()->SchemeIs("javascript")) {
11442 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"
, 11442); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "javascript: URIs should not enter session history"
")"); do { MOZ_CrashSequence(__null, 11442); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11443 return NS_ERROR_FAILURE;
11444 }
11445
11446 // XXX FillLoadInfo doesn't copy mLoadType, so the load state arrives here
11447 // without a load type set.
11448 aLoadState->SetLoadType(aLoadType);
11449
11450 SetOngoingNavigation(Some(OngoingNavigation::Traversal));
11451
11452 /* If there is a valid postdata *and* the user pressed
11453 * reload or shift-reload, take user's permission before we
11454 * repost the data to the server.
11455 */
11456 if ((aLoadType & LOAD_CMD_RELOAD) && aLoadState->PostDataStream()) {
11457 bool repost;
11458 nsresult rv = ConfirmRepost(&repost);
11459 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
11460 return rv;
11461 }
11462
11463 // If the user pressed cancel in the dialog, return. We're done here.
11464 if (!repost) {
11465 return NS_BINDING_ABORTED;
11466 }
11467 }
11468
11469 // If there is no valid triggeringPrincipal, we deny the load
11470 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", 11471); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aLoadState->TriggeringPrincipal()" ") ("
"need a valid triggeringPrincipal to load from history" ")")
; do { MOZ_CrashSequence(__null, 11471); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
11471 "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", 11471); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aLoadState->TriggeringPrincipal()" ") ("
"need a valid triggeringPrincipal to load from history" ")")
; do { MOZ_CrashSequence(__null, 11471); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
11472 if (!aLoadState->TriggeringPrincipal()) {
11473 return NS_ERROR_FAILURE;
11474 }
11475
11476 MaybeFireTraverseHistory(aLoadState);
11477
11478 return InternalLoad(aLoadState); // No nsIRequest
11479}
11480
11481NS_IMETHODIMPnsresult
11482nsDocShell::PersistLayoutHistoryState() {
11483 nsresult rv = NS_OK;
11484
11485 if (mActiveEntry) {
11486 bool scrollRestorationIsManual =
11487 mActiveEntry->GetScrollRestorationIsManual();
11488 nsCOMPtr<nsILayoutHistoryState> layoutState;
11489 if (RefPtr<PresShell> presShell = GetPresShell()) {
11490 rv = presShell->CaptureHistoryState(getter_AddRefs(layoutState));
11491 } else if (scrollRestorationIsManual) {
11492 // Even if we don't have layout anymore, we may want to reset the
11493 // current scroll state in layout history.
11494 GetLayoutHistoryState(getter_AddRefs(layoutState));
11495 }
11496
11497 if (scrollRestorationIsManual && layoutState) {
11498 layoutState->ResetScrollState();
11499 }
11500 }
11501
11502 return rv;
11503}
11504
11505already_AddRefed<ChildSHistory> nsDocShell::GetRootSessionHistory() {
11506 RefPtr<ChildSHistory> childSHistory =
11507 mBrowsingContext->Top()->GetChildSessionHistory();
11508 return childSHistory.forget();
11509}
11510
11511nsresult nsDocShell::GetHttpChannel(nsIChannel* aChannel,
11512 nsIHttpChannel** aReturn) {
11513 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", 11513); return NS_ERROR_INVALID_POINTER
; } } while (false)
;
11514 if (!aChannel) {
11515 return NS_ERROR_FAILURE;
11516 }
11517
11518 nsCOMPtr<nsIMultiPartChannel> multiPartChannel(do_QueryInterface(aChannel));
11519 if (multiPartChannel) {
11520 nsCOMPtr<nsIChannel> baseChannel;
11521 multiPartChannel->GetBaseChannel(getter_AddRefs(baseChannel));
11522 nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(baseChannel));
11523 *aReturn = httpChannel;
11524 NS_IF_ADDREF(*aReturn)ns_if_addref(*aReturn);
11525 }
11526 return NS_OK;
11527}
11528
11529bool nsDocShell::ShouldDiscardLayoutState(nsIHttpChannel* aChannel) {
11530 // By default layout State will be saved.
11531 if (!aChannel) {
11532 return false;
11533 }
11534
11535 // figure out if SH should be saving layout state
11536 bool noStore = false;
11537 (void)aChannel->IsNoStoreResponse(&noStore);
11538 return noStore;
11539}
11540
11541NS_IMETHODIMPnsresult
11542nsDocShell::GetEditor(nsIEditor** aEditor) {
11543 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", 11543); return NS_ERROR_INVALID_POINTER
; } } while (false)
;
11544 RefPtr<HTMLEditor> htmlEditor = GetHTMLEditorInternal();
11545 htmlEditor.forget(aEditor);
11546 return NS_OK;
11547}
11548
11549NS_IMETHODIMPnsresult
11550nsDocShell::SetEditor(nsIEditor* aEditor) {
11551 HTMLEditor* htmlEditor = aEditor ? aEditor->GetAsHTMLEditor() : nullptr;
11552 // If TextEditor comes, throw an error.
11553 if (aEditor && !htmlEditor) {
11554 return NS_ERROR_INVALID_ARG;
11555 }
11556 return SetHTMLEditorInternal(htmlEditor);
11557}
11558
11559HTMLEditor* nsDocShell::GetHTMLEditorInternal() {
11560 return mEditorData ? mEditorData->GetHTMLEditor() : nullptr;
11561}
11562
11563nsresult nsDocShell::SetHTMLEditorInternal(HTMLEditor* aHTMLEditor) {
11564 if (!aHTMLEditor && !mEditorData) {
11565 return NS_OK;
11566 }
11567
11568 nsresult rv = EnsureEditorData();
11569 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
11570 return rv;
11571 }
11572
11573 return mEditorData->SetHTMLEditor(aHTMLEditor);
11574}
11575
11576NS_IMETHODIMPnsresult
11577nsDocShell::GetEditable(bool* aEditable) {
11578 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", 11578); return NS_ERROR_INVALID_POINTER
; } } while (false)
;
11579 *aEditable = mEditorData && mEditorData->GetEditable();
11580 return NS_OK;
11581}
11582
11583NS_IMETHODIMPnsresult
11584nsDocShell::GetHasEditingSession(bool* aHasEditingSession) {
11585 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", 11585);
return NS_ERROR_INVALID_POINTER; } } while (false)
;
11586
11587 if (mEditorData) {
11588 *aHasEditingSession = !!mEditorData->GetEditingSession();
11589 } else {
11590 *aHasEditingSession = false;
11591 }
11592
11593 return NS_OK;
11594}
11595
11596NS_IMETHODIMPnsresult
11597nsDocShell::MakeEditable(bool aInWaitForUriLoad) {
11598 nsresult rv = EnsureEditorData();
11599 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
11600 return rv;
11601 }
11602
11603 return mEditorData->MakeEditable(aInWaitForUriLoad);
11604}
11605
11606/* static */ bool nsDocShell::ShouldAddURIVisit(nsIChannel* aChannel) {
11607 bool needToAddURIVisit = true;
11608 nsCOMPtr<nsIPropertyBag2> props(do_QueryInterface(aChannel));
11609 if (props) {
11610 (void)props->GetPropertyAsBool(u"docshell.needToAddURIVisit"_ns,
11611 &needToAddURIVisit);
11612 }
11613
11614 return needToAddURIVisit;
11615}
11616
11617/* static */ void nsDocShell::ExtractLastVisit(
11618 nsIChannel* aChannel, nsIURI** aURI, uint32_t* aChannelRedirectFlags) {
11619 nsCOMPtr<nsIPropertyBag2> props(do_QueryInterface(aChannel));
11620 if (!props) {
11621 return;
11622 }
11623
11624 nsresult rv;
11625 nsCOMPtr<nsIURI> uri(do_GetProperty(props, u"docshell.previousURI"_ns, &rv));
11626 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
11627 uri.forget(aURI);
11628
11629 rv = props->GetPropertyAsUint32(u"docshell.previousFlags"_ns,
11630 aChannelRedirectFlags);
11631
11632 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"
, 11634); } } while (false)
11633 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"
, 11634); } } while (false)
11634 "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"
, 11634); } } while (false)
;
11635
11636 } else {
11637 // There is no last visit for this channel, so this must be the first
11638 // link. Link the visit to the referrer of this request, if any.
11639 // Treat referrer as null if there is an error getting it.
11640 NS_GetReferrerFromChannel(aChannel, aURI);
11641 }
11642}
11643
11644void nsDocShell::SaveLastVisit(nsIChannel* aChannel, nsIURI* aURI,
11645 uint32_t aChannelRedirectFlags) {
11646 nsCOMPtr<nsIWritablePropertyBag2> props(do_QueryInterface(aChannel));
11647 if (!props || !aURI) {
11648 return;
11649 }
11650
11651 props->SetPropertyAsInterface(u"docshell.previousURI"_ns, aURI);
11652 props->SetPropertyAsUint32(u"docshell.previousFlags"_ns,
11653 aChannelRedirectFlags);
11654}
11655
11656/* static */ void nsDocShell::InternalAddURIVisit(
11657 nsIURI* aURI, nsIURI* aPreviousURI, uint32_t aChannelRedirectFlags,
11658 uint32_t aResponseStatus, BrowsingContext* aBrowsingContext,
11659 nsIWidget* aWidget, uint32_t aLoadType, bool aWasUpgraded, bool aIsPost) {
11660 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", 11660); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aURI" ") (" "Visited URI is null!" ")"); do
{ MOZ_CrashSequence(__null, 11660); __attribute__((nomerge))
::abort(); } while (false); } } while (false)
;
11661 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", 11662); 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, 11662); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
11662 "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", 11662); 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, 11662); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
11663
11664 bool usePrivateBrowsing = false;
11665 aBrowsingContext->GetUsePrivateBrowsing(&usePrivateBrowsing);
11666
11667 // Only content-type docshells save URI visits. Also don't do
11668 // anything here if we're not supposed to use global history.
11669 if (!aBrowsingContext->IsContent() ||
11670 !aBrowsingContext->GetUseGlobalHistory() || usePrivateBrowsing) {
11671 return;
11672 }
11673
11674 nsCOMPtr<IHistory> history = components::History::Service();
11675
11676 if (history) {
11677 uint32_t visitURIFlags = 0;
11678
11679 if (aBrowsingContext->IsTop()) {
11680 visitURIFlags |= IHistory::TOP_LEVEL;
11681 }
11682
11683 if (aChannelRedirectFlags & nsIChannelEventSink::REDIRECT_TEMPORARY) {
11684 visitURIFlags |= IHistory::REDIRECT_TEMPORARY;
11685 } else if (aChannelRedirectFlags &
11686 nsIChannelEventSink::REDIRECT_PERMANENT) {
11687 visitURIFlags |= IHistory::REDIRECT_PERMANENT;
11688 } else {
11689 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"
, 11691); 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, 11691); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
11690 "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"
, 11691); 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, 11691); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
11691 "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"
, 11691); 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, 11691); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
11692 }
11693
11694 if (aResponseStatus >= 300 && aResponseStatus < 400) {
11695 visitURIFlags |= IHistory::REDIRECT_SOURCE;
11696 if (aResponseStatus == 301 || aResponseStatus == 308) {
11697 visitURIFlags |= IHistory::REDIRECT_SOURCE_PERMANENT;
11698 }
11699 }
11700 // Errors 400-501 and 505 are considered unrecoverable, in the sense a
11701 // simple retry attempt by the user is unlikely to solve them.
11702 // 408 is special cased, since may actually indicate a temporary
11703 // connection problem.
11704 else if (aResponseStatus != 408 &&
11705 ((aResponseStatus >= 400 && aResponseStatus <= 501) ||
11706 aResponseStatus == 505)) {
11707 visitURIFlags |= IHistory::UNRECOVERABLE_ERROR;
11708 }
11709
11710 if (aWasUpgraded) {
11711 visitURIFlags |=
11712 IHistory::REDIRECT_SOURCE | IHistory::REDIRECT_SOURCE_UPGRADED;
11713 }
11714
11715 if (aIsPost) {
11716 visitURIFlags |= IHistory::SOURCE_IS_POST_RESPONSE;
11717 }
11718
11719 (void)history->VisitURI(aWidget, aURI, aPreviousURI, visitURIFlags,
11720 aBrowsingContext->BrowserId());
11721 }
11722}
11723
11724void nsDocShell::AddURIVisit(nsIURI* aURI, nsIURI* aPreviousURI,
11725 uint32_t aChannelRedirectFlags,
11726 uint32_t aResponseStatus, bool aIsPost) {
11727 nsPIDOMWindowOuter* outer = GetWindow();
11728 nsCOMPtr<nsIWidget> widget = widget::WidgetUtils::DOMWindowToWidget(outer);
11729
11730 InternalAddURIVisit(aURI, aPreviousURI, aChannelRedirectFlags,
11731 aResponseStatus, mBrowsingContext, widget, mLoadType,
11732 false, aIsPost);
11733}
11734
11735//*****************************************************************************
11736// nsDocShell: Helper Routines
11737//*****************************************************************************
11738
11739NS_IMETHODIMPnsresult
11740nsDocShell::SetLoadType(uint32_t aLoadType) {
11741 mLoadType = aLoadType;
11742 return NS_OK;
11743}
11744
11745NS_IMETHODIMPnsresult
11746nsDocShell::GetLoadType(uint32_t* aLoadType) {
11747 *aLoadType = mLoadType;
11748 return NS_OK;
11749}
11750
11751nsresult nsDocShell::ConfirmRepost(bool* aRepost) {
11752 if (StaticPrefs::dom_confirm_repost_testing_always_accept()) {
11753 *aRepost = true;
11754 return NS_OK;
11755 }
11756
11757 nsCOMPtr<nsIPromptCollection> prompter =
11758 do_GetService("@mozilla.org/embedcomp/prompt-collection;1");
11759 if (!prompter) {
11760 return NS_ERROR_NOT_AVAILABLE;
11761 }
11762
11763 return prompter->ConfirmRepost(mBrowsingContext, aRepost);
11764}
11765
11766nsresult nsDocShell::GetPromptAndStringBundle(nsIPrompt** aPrompt,
11767 nsIStringBundle** aStringBundle) {
11768 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"
, 11769); return NS_ERROR_FAILURE; } } while (false)
11769 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"
, 11769); return NS_ERROR_FAILURE; } } while (false)
;
11770
11771 nsCOMPtr<nsIStringBundleService> stringBundleService =
11772 mozilla::components::StringBundle::Service();
11773 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"
, 11773); return NS_ERROR_FAILURE; } } while (false)
;
11774
11775 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"
, 11777); return NS_ERROR_FAILURE; } } while (false)
11776 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"
, 11777); return NS_ERROR_FAILURE; } } while (false)
11777 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"
, 11777); return NS_ERROR_FAILURE; } } while (false)
;
11778
11779 return NS_OK;
11780}
11781
11782ScrollContainerFrame* nsDocShell::GetRootScrollContainerFrame() {
11783 PresShell* presShell = GetPresShell();
11784 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", 11784); return nullptr
; } } while (false)
;
11785
11786 return presShell->GetRootScrollContainerFrame();
11787}
11788
11789nsresult nsDocShell::EnsureScriptEnvironment() {
11790 if (mScriptGlobal) {
11791 return NS_OK;
11792 }
11793
11794 if (mIsBeingDestroyed) {
11795 return NS_ERROR_NOT_AVAILABLE;
11796 }
11797
11798#ifdef DEBUG1
11799 NS_ASSERTION(!mInEnsureScriptEnv,do { if (!(!mInEnsureScriptEnv)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "Infinite loop! Calling EnsureScriptEnvironment() from " "within EnsureScriptEnvironment()!"
, "!mInEnsureScriptEnv", "./../../../docshell/base/nsDocShell.cpp"
, 11801); MOZ_PretendNoReturn(); } } while (0)
11800 "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"
, 11801); MOZ_PretendNoReturn(); } } while (0)
11801 "within EnsureScriptEnvironment()!")do { if (!(!mInEnsureScriptEnv)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "Infinite loop! Calling EnsureScriptEnvironment() from " "within EnsureScriptEnvironment()!"
, "!mInEnsureScriptEnv", "./../../../docshell/base/nsDocShell.cpp"
, 11801); MOZ_PretendNoReturn(); } } while (0)
;
11802
11803 // Yeah, this isn't re-entrant safe, but that's ok since if we
11804 // re-enter this method, we'll infinitely loop...
11805 AutoRestore<bool> boolSetter(mInEnsureScriptEnv);
11806 mInEnsureScriptEnv = true;
11807#endif
11808
11809 nsCOMPtr<nsIWebBrowserChrome> browserChrome(do_GetInterface(mTreeOwner));
11810 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", 11810);
return NS_ERROR_NOT_AVAILABLE; } } while (false)
;
11811
11812 uint32_t chromeFlags;
11813 browserChrome->GetChromeFlags(&chromeFlags);
11814
11815 // If our window is modal and we're not opened as chrome, make
11816 // this window a modal content window.
11817 mScriptGlobal = nsGlobalWindowOuter::Create(this, mItemType == typeChrome);
11818 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", 11818); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "mScriptGlobal" ")"); do { MOZ_CrashSequence
(__null, 11818); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
11819
11820 // Ensure the script object is set up to run script.
11821 return mScriptGlobal->EnsureScriptEnvironment();
11822}
11823
11824nsresult nsDocShell::EnsureEditorData() {
11825 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", 11825); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!mIsBeingDestroyed" ")"); do { MOZ_CrashSequence
(__null, 11825); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
11826
11827 bool openDocHasDetachedEditor = false;
11828 if (!mEditorData && !mIsBeingDestroyed && !openDocHasDetachedEditor) {
11829 // We shouldn't recreate the editor data if it already exists, or
11830 // we're shutting down, or we already have a detached editor data
11831 // stored in the session history. We should only have one editordata
11832 // per docshell.
11833 mEditorData = MakeUnique<nsDocShellEditorData>(this);
11834 }
11835
11836 return mEditorData ? NS_OK : NS_ERROR_NOT_AVAILABLE;
11837}
11838
11839nsresult nsDocShell::EnsureFind() {
11840 if (!mFind) {
11841 mFind = MakeRefPtr<nsWebBrowserFind>();
11842 }
11843
11844 // we promise that the nsIWebBrowserFind that we return has been set
11845 // up to point to the focused, or content window, so we have to
11846 // set that up each time.
11847
11848 nsIScriptGlobalObject* scriptGO = GetScriptGlobalObject();
11849 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", 11849); return NS_ERROR_UNEXPECTED
; } } while (false)
;
11850
11851 // default to our window
11852 nsCOMPtr<nsPIDOMWindowOuter> ourWindow = do_QueryInterface(scriptGO);
11853 nsCOMPtr<nsPIDOMWindowOuter> windowToSearch;
11854 nsFocusManager::GetFocusedDescendant(ourWindow,
11855 nsFocusManager::eIncludeAllDescendants,
11856 getter_AddRefs(windowToSearch));
11857
11858 nsCOMPtr<nsIWebBrowserFindInFrames> findInFrames = do_QueryInterface(mFind);
11859 if (!findInFrames) {
11860 return NS_ERROR_NO_INTERFACE;
11861 }
11862
11863 nsresult rv = findInFrames->SetRootSearchFrame(ourWindow);
11864 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
11865 return rv;
11866 }
11867 rv = findInFrames->SetCurrentSearchFrame(windowToSearch);
11868 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
11869 return rv;
11870 }
11871
11872 return NS_OK;
11873}
11874
11875NS_IMETHODIMPnsresult
11876nsDocShell::IsBeingDestroyed(bool* aDoomed) {
11877 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", 11877); return NS_ERROR_INVALID_ARG
; } } while (false)
;
11878 *aDoomed = mIsBeingDestroyed;
11879 return NS_OK;
11880}
11881
11882NS_IMETHODIMPnsresult
11883nsDocShell::GetIsExecutingOnLoadHandler(bool* aResult) {
11884 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", 11884); return NS_ERROR_INVALID_ARG
; } } while (false)
;
11885 *aResult = mIsExecutingOnLoadHandler;
11886 return NS_OK;
11887}
11888
11889NS_IMETHODIMPnsresult
11890nsDocShell::GetLayoutHistoryState(nsILayoutHistoryState** aLayoutHistoryState) {
11891 nsCOMPtr<nsILayoutHistoryState> state;
11892 if (mActiveEntry) {
11893 state = mActiveEntry->GetLayoutHistoryState();
11894 }
11895 state.forget(aLayoutHistoryState);
11896 return NS_OK;
11897}
11898
11899NS_IMETHODIMPnsresult
11900nsDocShell::SetLayoutHistoryState(nsILayoutHistoryState* aLayoutHistoryState) {
11901 if (mActiveEntry) {
11902 mActiveEntry->SetLayoutHistoryState(aLayoutHistoryState);
11903 }
11904 return NS_OK;
11905}
11906
11907nsDocShell::InterfaceRequestorProxy::InterfaceRequestorProxy(
11908 nsIInterfaceRequestor* aRequestor) {
11909 if (aRequestor) {
11910 mWeakPtr = do_GetWeakReference(aRequestor);
11911 }
11912}
11913
11914nsDocShell::InterfaceRequestorProxy::~InterfaceRequestorProxy() {
11915 mWeakPtr = nullptr;
11916}
11917
11918NS_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"
, 11918); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { MOZ_CrashSequence(__null, 11918
); __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"
, 11918); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"nsDocShell::InterfaceRequestorProxy\" != nullptr"
") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__null
, 11918); __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"
, 11918); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { MOZ_CrashSequence(__null, 11918
); __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"
, 11918); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"nsDocShell::InterfaceRequestorProxy\" != nullptr"
") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__null
, 11918); __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", 11918); 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; }
11919
11920NS_IMETHODIMPnsresult
11921nsDocShell::InterfaceRequestorProxy::GetInterface(const nsIID& aIID,
11922 void** aSink) {
11923 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", 11923); return NS_ERROR_INVALID_POINTER
; } } while (false)
;
11924 nsCOMPtr<nsIInterfaceRequestor> ifReq = do_QueryReferent(mWeakPtr);
11925 if (ifReq) {
11926 return ifReq->GetInterface(aIID, aSink);
11927 }
11928 *aSink = nullptr;
11929 return NS_NOINTERFACE;
11930}
11931
11932//*****************************************************************************
11933// nsDocShell::nsIAuthPromptProvider
11934//*****************************************************************************
11935
11936NS_IMETHODIMPnsresult
11937nsDocShell::GetAuthPrompt(uint32_t aPromptReason, const nsIID& aIID,
11938 void** aResult) {
11939 // a priority prompt request will override a false mAllowAuth setting
11940 bool priorityPrompt = (aPromptReason == PROMPT_PROXY);
11941
11942 if (!mAllowAuth && !priorityPrompt) {
11943 return NS_ERROR_NOT_AVAILABLE;
11944 }
11945
11946 // we're either allowing auth, or it's a proxy request
11947 nsresult rv;
11948 nsCOMPtr<nsIPromptFactory> wwatch =
11949 do_GetService(NS_WINDOWWATCHER_CONTRACTID"@mozilla.org/embedcomp/window-watcher;1", &rv);
11950 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"
, 11950); return rv; } } while (false)
;
11951
11952 rv = EnsureScriptEnvironment();
11953 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"
, 11953); return rv; } } while (false)
;
11954
11955 // Get the an auth prompter for our window so that the parenting
11956 // of the dialogs works as it should when using tabs.
11957
11958 return wwatch->GetPrompt(mScriptGlobal, aIID,
11959 reinterpret_cast<void**>(aResult));
11960}
11961
11962//*****************************************************************************
11963// nsDocShell::nsILoadContext
11964//*****************************************************************************
11965
11966NS_IMETHODIMPnsresult
11967nsDocShell::GetAssociatedWindow(mozIDOMWindowProxy** aWindow) {
11968 CallGetInterface(this, aWindow);
11969 return NS_OK;
11970}
11971
11972NS_IMETHODIMPnsresult
11973nsDocShell::GetTopWindow(mozIDOMWindowProxy** aWindow) {
11974 return mBrowsingContext->GetTopWindow(aWindow);
11975}
11976
11977NS_IMETHODIMPnsresult
11978nsDocShell::GetTopFrameElement(Element** aElement) {
11979 return mBrowsingContext->GetTopFrameElement(aElement);
11980}
11981
11982NS_IMETHODIMPnsresult
11983nsDocShell::GetUseTrackingProtection(bool* aUseTrackingProtection) {
11984 return mBrowsingContext->GetUseTrackingProtection(aUseTrackingProtection);
11985}
11986
11987NS_IMETHODIMPnsresult
11988nsDocShell::SetUseTrackingProtection(bool aUseTrackingProtection) {
11989 return mBrowsingContext->SetUseTrackingProtection(aUseTrackingProtection);
11990}
11991
11992NS_IMETHODIMPnsresult
11993nsDocShell::GetIsContent(bool* aIsContent) {
11994 *aIsContent = (mItemType == typeContent);
11995 return NS_OK;
11996}
11997
11998bool nsDocShell::IsOKToLoadURI(nsIURI* aURI) {
11999 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", 11999); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aURI" ") (" "Must have a URI!" ")"); do { MOZ_CrashSequence
(__null, 11999); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
12000
12001 if (!mFiredUnloadEvent) {
12002 return true;
12003 }
12004
12005 if (!mLoadingURI) {
12006 return false;
12007 }
12008
12009 bool isPrivateWin = false;
12010 Document* doc = GetDocument();
12011 if (doc) {
12012 isPrivateWin =
12013 doc->NodePrincipal()->OriginAttributesRef().IsPrivateBrowsing();
12014 }
12015
12016 nsCOMPtr<nsIScriptSecurityManager> secMan =
12017 do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID"@mozilla.org/scriptsecuritymanager;1");
12018 return secMan && NS_SUCCEEDED(secMan->CheckSameOriginURI(((bool)(__builtin_expect(!!(!NS_FAILED_impl(secMan->CheckSameOriginURI
( aURI, mLoadingURI, false, isPrivateWin))), 1)))
12019 aURI, mLoadingURI, false, isPrivateWin))((bool)(__builtin_expect(!!(!NS_FAILED_impl(secMan->CheckSameOriginURI
( aURI, mLoadingURI, false, isPrivateWin))), 1)))
;
12020}
12021
12022//
12023// Routines for selection and clipboard
12024//
12025nsresult nsDocShell::GetControllerForCommand(const char* aCommand,
12026 nsIController** aResult) {
12027 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", 12027); return NS_ERROR_INVALID_POINTER
; } } while (false)
;
12028 *aResult = nullptr;
12029
12030 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", 12030);
return NS_ERROR_FAILURE; } } while (false)
;
12031
12032 nsCOMPtr<nsPIWindowRoot> root = mScriptGlobal->GetTopWindowRoot();
12033 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", 12033); return NS_ERROR_FAILURE
; } } while (false)
;
12034
12035 return root->GetControllerForCommand(aCommand, false /* for any window */,
12036 aResult);
12037}
12038
12039NS_IMETHODIMPnsresult
12040nsDocShell::IsCommandEnabled(const char* aCommand, bool* aResult) {
12041 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", 12041); return NS_ERROR_INVALID_POINTER
; } } while (false)
;
12042 *aResult = false;
12043
12044 nsresult rv = NS_ERROR_FAILURE;
12045
12046 nsCOMPtr<nsIController> controller;
12047 rv = GetControllerForCommand(aCommand, getter_AddRefs(controller));
12048 if (controller) {
12049 rv = controller->IsCommandEnabled(aCommand, aResult);
12050 }
12051
12052 return rv;
12053}
12054
12055NS_IMETHODIMPnsresult
12056nsDocShell::DoCommand(const char* aCommand) {
12057 nsresult rv = NS_ERROR_FAILURE;
12058
12059 nsCOMPtr<nsIController> controller;
12060 rv = GetControllerForCommand(aCommand, getter_AddRefs(controller));
12061 if (controller) {
12062 rv = controller->DoCommand(aCommand);
12063 }
12064
12065 return rv;
12066}
12067
12068NS_IMETHODIMPnsresult
12069nsDocShell::DoCommandWithParams(const char* aCommand,
12070 nsICommandParams* aParams) {
12071 nsCOMPtr<nsIController> controller;
12072 nsresult rv = GetControllerForCommand(aCommand, getter_AddRefs(controller));
12073 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"
, 12073)
) {
12074 return rv;
12075 }
12076
12077 nsCOMPtr<nsICommandController> commandController =
12078 do_QueryInterface(controller, &rv);
12079 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"
, 12079)
) {
12080 return rv;
12081 }
12082
12083 return commandController->DoCommandWithParams(aCommand, aParams);
12084}
12085
12086nsresult nsDocShell::EnsureCommandHandler() {
12087 if (!mCommandManager) {
12088 if (nsCOMPtr<nsPIDOMWindowOuter> domWindow = GetWindow()) {
12089 mCommandManager = MakeRefPtr<nsCommandManager>(domWindow);
12090 }
12091 }
12092 return mCommandManager ? NS_OK : NS_ERROR_FAILURE;
12093}
12094
12095// link handling
12096
12097class OnLinkClickEvent : public CancelableRunnable, public SupportsWeakPtr {
12098 public:
12099 OnLinkClickEvent(nsDocShell* aHandler, nsIContent* aContent,
12100 nsDocShellLoadState* aLoadState, bool aNoOpenerImplied,
12101 nsIPrincipal* aTriggeringPrincipal);
12102
12103 NS_IMETHODvirtual nsresult Run() override {
12104 if (mCancelled) {
12105 return NS_OK;
12106 }
12107
12108 // We need to set up an AutoJSAPI here for the following reason: When we
12109 // do OnLinkClickSync we'll eventually end up in
12110 // nsGlobalWindow::OpenInternal which only does popup blocking if
12111 // !LegacyIsCallerChromeOrNativeCode(). So we need to fake things so that
12112 // we don't look like native code as far as LegacyIsCallerNativeCode() is
12113 // concerned. (Bug 1930445)
12114 AutoJSAPI jsapi;
12115 if (jsapi.Init(mContent->OwnerDoc()->GetScopeObject())) {
12116 // For form submissions, the source element is set to the submitter,
12117 // and we don't want to overwrite it with the <form> element here.
12118 if (!mLoadState->HasSourceElement()) {
12119 mLoadState->SetSourceElement(mContent->AsElement());
12120 }
12121 mHandler->OnLinkClickSync(mContent, mLoadState, mNoOpenerImplied,
12122 mTriggeringPrincipal);
12123 }
12124 return NS_OK;
12125 }
12126
12127 nsresult Cancel() override final {
12128 mCancelled = true;
12129 // Don't clear mLoadState, etc. here since this can be called
12130 // from the OnLinkClickSync() above, and we might be holding
12131 // the last references to them.
12132 return NS_OK;
12133 }
12134
12135 private:
12136 RefPtr<nsDocShell> mHandler;
12137 nsCOMPtr<nsIContent> mContent;
12138 RefPtr<nsDocShellLoadState> mLoadState;
12139 nsCOMPtr<nsIPrincipal> mTriggeringPrincipal;
12140 bool mNoOpenerImplied;
12141 bool mCancelled = false;
12142};
12143
12144OnLinkClickEvent::OnLinkClickEvent(nsDocShell* aHandler, nsIContent* aContent,
12145 nsDocShellLoadState* aLoadState,
12146 bool aNoOpenerImplied,
12147 nsIPrincipal* aTriggeringPrincipal)
12148 : mozilla::CancelableRunnable("OnLinkClickEvent"),
12149 mHandler(aHandler),
12150 mContent(aContent),
12151 mLoadState(aLoadState),
12152 mTriggeringPrincipal(aTriggeringPrincipal),
12153 mNoOpenerImplied(aNoOpenerImplied) {}
12154
12155nsresult nsDocShell::OnFormSubmit(HTMLFormElement* aForm,
12156 nsDocShellLoadState* aLoadState) {
12157 // Need to do this here, since it's ordinarily done in OnLinkClick.
12158 if (ShouldBlockLoadingForBackButton()) {
12159 return NS_OK;
12160 }
12161 if (!StaticPrefs::dom_forms_submit_async_navigation()) {
12162 return OnLinkClickSync(aForm, aLoadState, false, aForm->NodePrincipal());
12163 }
12164
12165 // Determine BC to target synchronously, for consistency with other browsers
12166 ComputeNamedTargetBrowsingContext(aLoadState);
12167
12168 // https://html.spec.whatwg.org/#form-submission-algorithm
12169 // 25. If form document equals targetNavigable's active document, and form
12170 // document has not yet completely loaded, then set historyHandling to
12171 // "replace".
12172 const MaybeDiscarded<BrowsingContext>& targetBC =
12173 aLoadState->TargetBrowsingContext();
12174 Document* formDocument = aForm->OwnerDoc();
12175 if ((targetBC.IsNull() || targetBC == formDocument->GetBrowsingContext()) &&
12176 !formDocument->IsCompletelyLoaded()) {
12177 aLoadState->SetHistoryBehavior(NavigationHistoryBehavior::Replace);
12178 }
12179
12180 RefPtr ev = MakeRefPtr<OnLinkClickEvent>(this, aForm, aLoadState, false,
12181 aForm->NodePrincipal());
12182 RefPtr<nsIRunnable> runnable = ev;
12183 nsresult rv = Dispatch(runnable.forget());
12184 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"
, 12184); return rv; } } while (false)
;
12185
12186 nsDocShell* targetDocShell = this;
12187 if (!aLoadState->Target().IsEmpty()) {
12188 targetDocShell =
12189 targetBC.IsNullOrDiscarded()
12190 ? nullptr
12191 : static_cast<nsDocShell*>(targetBC.get()->GetDocShell());
12192 }
12193 if (targetDocShell) {
12194 targetDocShell->CancelPlannedFormNavigation();
12195 // Chrome stops pending javascript: navigations here.
12196 // https://github.com/whatwg/html/issues/12607
12197 targetDocShell->StopPendingJavascriptURLNavigations();
12198 targetDocShell->mPlannedFormNavigation = ev.get();
12199 }
12200 return NS_OK;
12201}
12202
12203nsresult nsDocShell::CancelPlannedFormNavigation() {
12204 if (mPlannedFormNavigation) {
12205 mPlannedFormNavigation->Cancel();
12206 mPlannedFormNavigation = nullptr;
12207 }
12208 return NS_OK;
12209}
12210
12211nsresult nsDocShell::OnLinkClick(
12212 nsIContent* aContent, nsIURI* aURI, const nsAString& aTargetSpec,
12213 const nsAString& aFileName, nsIInputStream* aPostDataStream,
12214 nsIInputStream* aHeadersDataStream, bool aIsUserTriggered,
12215 UserNavigationInvolvement aUserInvolvement,
12216 nsIPrincipal* aTriggeringPrincipal, nsIPolicyContainer* aPolicyContainer) {
12217#ifndef ANDROID
12218 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"
, 12218); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aTriggeringPrincipal"
") (" "Need a valid triggeringPrincipal" ")"); do { MOZ_CrashSequence
(__null, 12218); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
12219#endif
12220 NS_ASSERTION(NS_IsMainThread(), "wrong thread")do { if (!(NS_IsMainThread())) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "wrong thread", "NS_IsMainThread()", "./../../../docshell/base/nsDocShell.cpp"
, 12220); MOZ_PretendNoReturn(); } } while (0)
;
12221
12222 if (!IsNavigationAllowed() || !IsOKToLoadURI(aURI)) {
12223 return NS_OK;
12224 }
12225
12226 // On history navigation through Back/Forward buttons, don't execute
12227 // automatic JavaScript redirection such as |anchorElement.click()| or
12228 // |formElement.submit()|.
12229 //
12230 // XXX |formElement.submit()| bypasses this checkpoint because it calls
12231 // nsDocShell::OnLinkClickSync(...) instead.
12232 if (ShouldBlockLoadingForBackButton()) {
12233 return NS_OK;
12234 }
12235
12236 if (aContent->IsEditable()) {
12237 return NS_OK;
12238 }
12239
12240 RefPtr<Document> ownerDoc = aContent->OwnerDoc();
12241 if (nsContentUtils::IsExternalProtocol(aURI)) {
12242 ownerDoc->EnsureNotEnteringAndExitFullscreen();
12243 }
12244
12245 bool noOpenerImplied = false;
12246 nsAutoString target(aTargetSpec);
12247 if (aFileName.IsVoid() &&
12248 ShouldOpenInBlankTarget(aTargetSpec, aURI, aContent, aIsUserTriggered)) {
12249 target = u"_blank";
12250 if (!aTargetSpec.Equals(target)) {
12251 noOpenerImplied = true;
12252 }
12253 }
12254
12255 // https://html.spec.whatwg.org/#downloading-hyperlinks
12256 // Step 6, step 6.1, step 6.2
12257 // aFileName not being void implies a download attribute, since we've already
12258 // checked if the attribute is present in `nsContentUtils::TriggerLinkClick`
12259 // and made it void otherwise.
12260 if (!aFileName.IsVoid() &&
12261 aUserInvolvement != UserNavigationInvolvement::BrowserUI) {
12262 if (nsCOMPtr<nsPIDOMWindowInner> window = ownerDoc->GetInnerWindow()) {
12263 if (RefPtr<Navigation> navigation = window->Navigation()) {
12264 AutoJSAPI jsapi;
12265 if (jsapi.Init(window)) {
12266 RefPtr element = aContent->AsElement();
12267 // Step 6.4
12268 bool shouldContinue = navigation->FireDownloadRequestNavigateEvent(
12269 jsapi.cx(), aURI, aUserInvolvement, element, aFileName);
12270
12271 // Step 6.5
12272 if (!shouldContinue) {
12273 return NS_OK;
12274 }
12275 }
12276 }
12277 }
12278 }
12279
12280 RefPtr loadState = MakeRefPtr<nsDocShellLoadState>(aURI);
12281 loadState->SetTarget(target);
12282 loadState->SetFileName(aFileName);
12283 loadState->SetPostDataStream(aPostDataStream);
12284 loadState->SetHeadersStream(aHeadersDataStream);
12285 loadState->SetFirstParty(true);
12286 loadState->SetTriggeringPrincipal(
12287 aTriggeringPrincipal ? aTriggeringPrincipal : aContent->NodePrincipal());
12288 loadState->SetPrincipalToInherit(aContent->NodePrincipal());
12289 loadState->SetPolicyContainer(
12290 aPolicyContainer ? aPolicyContainer : aContent->GetPolicyContainer());
12291 loadState->SetAllowFocusMove(UserActivation::IsHandlingUserInput());
12292
12293 const bool hasValidUserGestureActivation =
12294 ownerDoc->HasValidTransientUserGestureActivation();
12295 loadState->SetHasValidUserGestureActivation(hasValidUserGestureActivation);
12296
12297 // For protocols that would launch without a prompt (e.g. mailto), consume the
12298 // transient user gesture activation so a single gesture can't chain multiple
12299 // launches. Do this here, at the same point the activation value is captured
12300 // on the load state, rather than later in OnLinkClickSync: that runs
12301 // asynchronously, and consuming there would be inconsistent with the scripted
12302 // navigation path (see BrowsingContext::Navigate). The pre-consume value is
12303 // already recorded on the load state above. See bug 299116.
12304 if (nsAutoCString scheme; NS_SUCCEEDED(aURI->GetScheme(scheme))((bool)(__builtin_expect(!!(!NS_FAILED_impl(aURI->GetScheme
(scheme))), 1)))
) {
12305 nsExternalHelperAppService::MaybeConsumeUserActivationForExternalScheme(
12306 ownerDoc->GetWindowContext(), loadState->TriggeringPrincipal(), scheme);
12307 }
12308
12309 loadState->SetTextDirectiveUserActivation(
12310 ownerDoc->ConsumeTextDirectiveUserActivation() ||
12311 hasValidUserGestureActivation);
12312 loadState->SetUserNavigationInvolvement(aUserInvolvement);
12313 loadState->SetTriggeringClassificationFlags(
12314 ownerDoc->GetScriptTrackingFlags());
12315 loadState->SetHistoryBehavior(NavigationHistoryBehavior::Auto);
12316
12317 ComputeNamedTargetBrowsingContext(loadState);
12318
12319 RefPtr ev = MakeRefPtr<OnLinkClickEvent>(
12320 this, aContent, loadState, noOpenerImplied, aTriggeringPrincipal);
12321
12322 // https://html.spec.whatwg.org/#navigate step 8 only queues a task when the
12323 // navigation crosses agents.
12324 if (StaticPrefs::dom_links_sync_fragment_navigation()) {
12325 SameDocumentNavigationState state;
12326 if ((loadState->Target().IsEmpty() ||
12327 loadState->TargetBrowsingContext() == GetBrowsingContext()) &&
12328 IsSameDocumentNavigation(loadState, state)) {
12329 ev->Run();
12330 return NS_OK;
12331 }
12332 }
12333
12334 RefPtr<nsIRunnable> runnable = ev;
12335 return Dispatch(runnable.forget());
12336}
12337
12338bool nsDocShell::ShouldOpenInBlankTarget(const nsAString& aOriginalTarget,
12339 nsIURI* aLinkURI, nsIContent* aContent,
12340 bool aIsUserTriggered) {
12341 if (aLinkURI->SchemeIs("javascript")) {
12342 return false;
12343 }
12344
12345 // External links from within app tabs should always open in new tabs
12346 // instead of replacing the app tab's page (Bug 575561)
12347 // nsIURI.host can throw for non-nsStandardURL nsIURIs. If we fail to
12348 // get either host, just return false to use the original target.
12349 nsAutoCString linkHost;
12350 if (NS_FAILED(aLinkURI->GetHost(linkHost))((bool)(__builtin_expect(!!(NS_FAILED_impl(aLinkURI->GetHost
(linkHost))), 0)))
) {
12351 return false;
12352 }
12353
12354 // The targetTopLevelLinkClicksToBlank property on BrowsingContext allows
12355 // privileged code to change the default targeting behaviour. In particular,
12356 // if a user-initiated link click for the (or targetting the) top-level frame
12357 // is detected, we default the target to "_blank" to give it a new
12358 // top-level BrowsingContext.
12359 if (mBrowsingContext->TargetTopLevelLinkClicksToBlank() && aIsUserTriggered &&
12360 ((aOriginalTarget.IsEmpty() && mBrowsingContext->IsTop()) ||
12361 aOriginalTarget == u"_top"_ns)) {
12362 return true;
12363 }
12364
12365 // Don't modify non-default targets.
12366 if (!aOriginalTarget.IsEmpty()) {
12367 return false;
12368 }
12369
12370 // Only check targets that are in extension panels or app tabs.
12371 // (isAppTab will be false for app tab subframes).
12372 nsString mmGroup = mBrowsingContext->Top()->GetMessageManagerGroup();
12373 if (!mmGroup.EqualsLiteral("webext-browsers") &&
12374 !mBrowsingContext->IsAppTab()) {
12375 return false;
12376 }
12377
12378 nsCOMPtr<nsIURI> docURI = aContent->OwnerDoc()->GetDocumentURIObject();
12379 if (!docURI) {
12380 return false;
12381 }
12382
12383 nsAutoCString docHost;
12384 if (NS_FAILED(docURI->GetHost(docHost))((bool)(__builtin_expect(!!(NS_FAILED_impl(docURI->GetHost
(docHost))), 0)))
) {
12385 return false;
12386 }
12387
12388 if (linkHost.Equals(docHost)) {
12389 return false;
12390 }
12391
12392 // Special case: ignore "www" prefix if it is part of host string
12393 return linkHost.Length() < docHost.Length()
12394 ? !docHost.Equals("www."_ns + linkHost)
12395 : !linkHost.Equals("www."_ns + docHost);
12396}
12397
12398static bool ElementCanHaveNoopener(nsIContent* aContent) {
12399 return aContent->IsAnyOfHTMLElements(nsGkAtoms::a, nsGkAtoms::area,
12400 nsGkAtoms::form) ||
12401 aContent->IsSVGElement(nsGkAtoms::a) ||
12402 (aContent->IsMathMLElement(nsGkAtoms::a) &&
12403 StaticPrefs::mathml_a_element_enabled());
12404}
12405
12406nsresult nsDocShell::OnLinkClickSync(nsIContent* aContent,
12407 nsDocShellLoadState* aLoadState,
12408 bool aNoOpenerImplied,
12409 nsIPrincipal* aTriggeringPrincipal) {
12410 if (!IsNavigationAllowed() || !IsOKToLoadURI(aLoadState->URI())) {
12411 return NS_OK;
12412 }
12413
12414 if (aContent->IsEditable()) {
12415 return NS_OK;
12416 }
12417
12418 // if the triggeringPrincipal is not passed explicitly, then we
12419 // fall back to using doc->NodePrincipal() as the triggeringPrincipal.
12420 nsCOMPtr<nsIPrincipal> triggeringPrincipal =
12421 aTriggeringPrincipal ? aTriggeringPrincipal : aContent->NodePrincipal();
12422
12423 {
12424 // defer to an external protocol handler if necessary...
12425 nsCOMPtr<nsIExternalProtocolService> extProtService =
12426 do_GetService(NS_EXTERNALPROTOCOLSERVICE_CONTRACTID"@mozilla.org/uriloader/external-protocol-service;1");
12427 if (extProtService) {
12428 nsAutoCString scheme;
12429 aLoadState->URI()->GetScheme(scheme);
12430 if (!scheme.IsEmpty()) {
12431 // if the URL scheme does not correspond to an exposed protocol, then
12432 // we need to hand this link click over to the external protocol
12433 // handler.
12434 bool isExposed;
12435 nsresult rv =
12436 extProtService->IsExposedProtocol(scheme.get(), &isExposed);
12437 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && !isExposed) {
12438 // Use the activation captured on the load state at click/submit time
12439 // (OnLinkClick, HTMLFormElement::SubmitSubmission), rather than
12440 // re-reading from the document here: this runs asynchronously, by
12441 // which point the transient activation may have expired. Consumption
12442 // of the activation (for gated schemes like mailto) also happens at
12443 // that capture point. See bug 299116.
12444 bool hasValidUserGestureActivation =
12445 aLoadState->HasValidUserGestureActivation();
12446 return extProtService->LoadURI(aLoadState->URI(), triggeringPrincipal,
12447 nullptr, mBrowsingContext,
12448 /* aTriggeredExternally */
12449 false, hasValidUserGestureActivation,
12450 /* aNewWindowTarget */ false);
12451 }
12452 }
12453 }
12454 }
12455 uint32_t triggeringSandboxFlags = 0;
12456 uint64_t triggeringWindowId = 0;
12457 if (mBrowsingContext) {
12458 triggeringSandboxFlags = aContent->OwnerDoc()->GetSandboxFlags();
12459 triggeringWindowId = aContent->OwnerDoc()->InnerWindowID();
12460 }
12461
12462 uint32_t flags = INTERNAL_LOAD_FLAGS_NONE;
12463 bool elementCanHaveNoopener = ElementCanHaveNoopener(aContent);
12464 bool triggeringPrincipalIsSystemPrincipal =
12465 aLoadState->TriggeringPrincipal()->IsSystemPrincipal();
12466 if (elementCanHaveNoopener) {
12467 nsAutoString relString;
12468 aContent->AsElement()->GetAttr(nsGkAtoms::rel, relString);
12469 nsWhitespaceTokenizerTemplate<nsContentUtils::IsHTMLWhitespace> tok(
12470 relString);
12471
12472 bool targetBlank = aLoadState->Target().LowerCaseEqualsLiteral("_blank");
12473 bool explicitOpenerSet = false;
12474
12475 // The opener behaviour follows a hierarchy, such that if a higher
12476 // priority behaviour is specified, it always takes priority. That
12477 // priority is currently: norefrerer > noopener > opener > default
12478
12479 while (tok.hasMoreTokens()) {
12480 const nsAString& token = tok.nextToken();
12481 if (token.LowerCaseEqualsLiteral("noreferrer")) {
12482 flags |= INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER |
12483 INTERNAL_LOAD_FLAGS_NO_OPENER;
12484 // noreferrer cannot be overwritten by a 'rel=opener'.
12485 explicitOpenerSet = true;
12486 break;
12487 }
12488
12489 if (token.LowerCaseEqualsLiteral("noopener")) {
12490 flags |= INTERNAL_LOAD_FLAGS_NO_OPENER;
12491 explicitOpenerSet = true;
12492 }
12493
12494 if (targetBlank && StaticPrefs::dom_targetBlankNoOpener_enabled() &&
12495 token.LowerCaseEqualsLiteral("opener") && !explicitOpenerSet) {
12496 explicitOpenerSet = true;
12497 }
12498 }
12499
12500 if (targetBlank && StaticPrefs::dom_targetBlankNoOpener_enabled() &&
12501 !explicitOpenerSet && !triggeringPrincipalIsSystemPrincipal) {
12502 flags |= INTERNAL_LOAD_FLAGS_NO_OPENER;
12503 }
12504
12505 if (aNoOpenerImplied) {
12506 flags |= INTERNAL_LOAD_FLAGS_NO_OPENER;
12507 }
12508 }
12509
12510 // Get the owner document of the link that was clicked, this will be
12511 // the document that the link is in, or the last document that the
12512 // link was in. From that document, we'll get the URI to use as the
12513 // referrer, since the current URI in this docshell may be a
12514 // new document that we're in the process of loading.
12515 RefPtr<Document> referrerDoc = aContent->OwnerDoc();
12516
12517 // Now check that the referrerDoc's inner window is the current inner
12518 // window for mScriptGlobal. If it's not, then we don't want to
12519 // follow this link.
12520 nsPIDOMWindowInner* referrerInner = referrerDoc->GetInnerWindow();
12521 if (!mScriptGlobal || !referrerInner ||
12522 mScriptGlobal->GetCurrentInnerWindow() != referrerInner) {
12523 // We're no longer the current inner window
12524 return NS_OK;
12525 }
12526
12527 // referrer could be null here in some odd cases, but that's ok,
12528 // we'll just load the link w/o sending a referrer in those cases.
12529
12530 uint32_t loadType = LOAD_LINK;
12531 if (aLoadState->IsFormSubmission()) {
12532 if (aLoadState->Target().IsEmpty()) {
12533 // We set the right load type here for form submissions with an empty
12534 // target. Form submission with a non-empty target are handled in
12535 // nsDocShell::PerformRetargeting after we've selected the correct target
12536 // BC.
12537 loadType = GetLoadTypeForFormSubmission(GetBrowsingContext(), aLoadState);
12538 }
12539 }
12540
12541 RefPtr referrerInfo = elementCanHaveNoopener
12542 ? MakeRefPtr<ReferrerInfo>(*aContent->AsElement())
12543 : MakeRefPtr<ReferrerInfo>(*referrerDoc);
12544
12545 aLoadState->SetTriggeringSandboxFlags(triggeringSandboxFlags);
12546 aLoadState->SetTriggeringWindowId(triggeringWindowId);
12547 aLoadState->SetReferrerInfo(referrerInfo);
12548 aLoadState->SetInternalLoadFlags(flags);
12549 aLoadState->SetLoadType(loadType);
12550 aLoadState->SetSourceBrowsingContext(mBrowsingContext);
12551
12552 nsresult rv = InternalLoad(aLoadState);
12553
12554 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
12555 nsPingListener::DispatchPings(this, aContent, aLoadState->URI(),
12556 referrerInfo);
12557 }
12558
12559 return rv;
12560}
12561
12562nsresult nsDocShell::OnOverLink(nsIContent* aContent, nsIURI* aURI,
12563 const nsAString& aTargetSpec) {
12564 if (aContent->IsEditable()) {
12565 return NS_OK;
12566 }
12567
12568 nsresult rv = NS_ERROR_FAILURE;
12569
12570 nsCOMPtr<nsIWebBrowserChrome> browserChrome = do_GetInterface(mTreeOwner);
12571 if (!browserChrome) {
12572 return rv;
12573 }
12574
12575 nsCOMPtr<nsIURI> exposableURI = nsIOService::CreateExposableURI(aURI);
12576 nsAutoCString spec;
12577 rv = exposableURI->GetDisplaySpec(spec);
12578 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"
, 12578); return rv; } } while (false)
;
12579
12580 NS_ConvertUTF8toUTF16 uStr(spec);
12581
12582 // The speculative connect used to go through the predictor, but we don't
12583 // need all that just to initiate a speculative connect.
12584 if ((StaticPrefs::network_predictor_enable_hover_on_ssl() &&
12585 mCurrentURI->SchemeIs("https")) ||
12586 mCurrentURI->SchemeIs("http")) {
12587 if (nsCOMPtr<nsISpeculativeConnect> specService =
12588 mozilla::components::IO::Service()) {
12589 // This would be a navigation, so if this is cross origin the speculative
12590 // connection needs to have the origin of the URL not the current page.
12591 nsCOMPtr<nsIPrincipal> principal = BasePrincipal::CreateContentPrincipal(
12592 aURI, aContent->NodePrincipal()->OriginAttributesRef());
12593
12594 specService->SpeculativeConnect(aURI, principal, this, false);
12595 }
12596 }
12597
12598 rv = browserChrome->SetLinkStatus(uStr);
12599 return rv;
12600}
12601
12602nsresult nsDocShell::OnLeaveLink() {
12603 nsCOMPtr<nsIWebBrowserChrome> browserChrome(do_GetInterface(mTreeOwner));
12604 nsresult rv = NS_ERROR_FAILURE;
12605
12606 if (browserChrome) {
12607 rv = browserChrome->SetLinkStatus(u""_ns);
12608 }
12609 return rv;
12610}
12611
12612bool nsDocShell::ShouldBlockLoadingForBackButton() {
12613 if (!(mLoadType & LOAD_CMD_HISTORY) ||
12614 UserActivation::IsHandlingUserInput() ||
12615 !Preferences::GetBool("accessibility.blockjsredirection")) {
12616 return false;
12617 }
12618
12619 bool canGoForward = false;
12620 GetCanGoForward(&canGoForward);
12621 return canGoForward;
12622}
12623
12624//----------------------------------------------------------------------
12625// Web Shell Services API
12626
12627// This functions is only called when a new charset is detected in loading a
12628// document.
12629nsresult nsDocShell::CharsetChangeReloadDocument(
12630 mozilla::NotNull<const mozilla::Encoding*> aEncoding, int32_t aSource) {
12631 // XXX hack. keep the aCharset and aSource wait to pick it up
12632 nsCOMPtr<nsIDocumentViewer> viewer;
12633 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"
, 12633); return NS_ERROR_FAILURE; } } while (false)
;
12634 if (viewer) {
12635 int32_t source;
12636 (void)viewer->GetReloadEncodingAndSource(&source);
12637 if (aSource > source) {
12638 viewer->SetReloadEncodingAndSource(aEncoding, aSource);
12639 if (eCharsetReloadRequested != mCharsetReloadState) {
12640 mCharsetReloadState = eCharsetReloadRequested;
12641 switch (mLoadType) {
12642 case LOAD_RELOAD_BYPASS_PROXY_AND_CACHE:
12643 return Reload(LOAD_FLAGS_CHARSET_CHANGE | LOAD_FLAGS_BYPASS_CACHE |
12644 LOAD_FLAGS_BYPASS_PROXY);
12645 case LOAD_RELOAD_BYPASS_CACHE:
12646 return Reload(LOAD_FLAGS_CHARSET_CHANGE | LOAD_FLAGS_BYPASS_CACHE);
12647 default:
12648 return Reload(LOAD_FLAGS_CHARSET_CHANGE);
12649 }
12650 }
12651 }
12652 }
12653 // return failure if this request is not accepted due to mCharsetReloadState
12654 return NS_ERROR_DOCSHELL_REQUEST_REJECTED;
12655}
12656
12657nsresult nsDocShell::CharsetChangeStopDocumentLoad() {
12658 if (eCharsetReloadRequested != mCharsetReloadState) {
12659 Stop(nsIWebNavigation::STOP_ALL);
12660 return NS_OK;
12661 }
12662 // return failer if this request is not accepted due to mCharsetReloadState
12663 return NS_ERROR_DOCSHELL_REQUEST_REJECTED;
12664}
12665
12666NS_IMETHODIMPnsresult nsDocShell::ExitPrintPreview() {
12667 nsCOMPtr<nsIWebBrowserPrint> viewer = do_QueryInterface(mDocumentViewer);
12668 MOZ_TRY(viewer->ExitPrintPreview())__extension__({ auto mozTryVarTempResult = ::mozilla::ToResult
(viewer->ExitPrintPreview()); if ((__builtin_expect(!!(mozTryVarTempResult
.isErr()), 0))) { return mozTryVarTempResult.propagateErr(); }
mozTryVarTempResult.unwrap(); })
;
12669 return NS_OK;
12670}
12671
12672/* [infallible] */
12673NS_IMETHODIMPnsresult nsDocShell::GetIsTopLevelContentDocShell(
12674 bool* aIsTopLevelContentDocShell) {
12675 *aIsTopLevelContentDocShell = false;
12676
12677 if (mItemType == typeContent) {
12678 *aIsTopLevelContentDocShell = mBrowsingContext->IsTopContent();
12679 }
12680
12681 return NS_OK;
12682}
12683
12684// Implements nsILoadContext.originAttributes
12685NS_IMETHODIMPnsresult
12686nsDocShell::GetScriptableOriginAttributes(JSContext* aCx,
12687 JS::MutableHandle<JS::Value> aVal) {
12688 return mBrowsingContext->GetScriptableOriginAttributes(aCx, aVal);
12689}
12690
12691// Implements nsIDocShell.GetOriginAttributes()
12692NS_IMETHODIMPnsresult
12693nsDocShell::GetOriginAttributes(JSContext* aCx,
12694 JS::MutableHandle<JS::Value> aVal) {
12695 return mBrowsingContext->GetScriptableOriginAttributes(aCx, aVal);
12696}
12697
12698bool nsDocShell::ServiceWorkerAllowedToControlWindow(nsIPrincipal* aPrincipal,
12699 nsIURI* aURI) {
12700 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"
, 12700); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPrincipal"
")"); do { MOZ_CrashSequence(__null, 12700); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12701 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"
, 12701); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aURI" ")")
; do { MOZ_CrashSequence(__null, 12701); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
12702
12703 if (UsePrivateBrowsing() || mBrowsingContext->GetSandboxFlags()) {
12704 return false;
12705 }
12706
12707 nsCOMPtr<nsIDocShellTreeItem> parent;
12708 GetInProcessSameTypeParent(getter_AddRefs(parent));
12709 nsPIDOMWindowOuter* parentOuter = parent ? parent->GetWindow() : nullptr;
12710 nsPIDOMWindowInner* parentInner =
12711 parentOuter ? parentOuter->GetCurrentInnerWindow() : nullptr;
12712
12713 StorageAccess storage =
12714 StorageAllowedForNewWindow(aPrincipal, aURI, parentInner);
12715
12716 // A service worker is allowed to control the window if partition is enabled.
12717 if (parentInner) {
12718 RefPtr<Document> doc = parentInner->GetExtantDoc();
12719
12720 if (doc && StoragePartitioningEnabled(storage, doc->CookieJarSettings())) {
12721 return true;
12722 }
12723 }
12724
12725 return storage == StorageAccess::eAllow;
12726}
12727
12728nsresult nsDocShell::SetOriginAttributes(const OriginAttributes& aAttrs) {
12729 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", 12729); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!mIsBeingDestroyed" ")"); do { MOZ_CrashSequence
(__null, 12729); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
12730 return mBrowsingContext->SetOriginAttributes(aAttrs);
12731}
12732
12733NS_IMETHODIMPnsresult
12734nsDocShell::ResumeRedirectedLoad(uint64_t aIdentifier) {
12735 RefPtr<nsDocShell> self = this;
12736 RefPtr<ChildProcessChannelListener> cpcl =
12737 ChildProcessChannelListener::GetSingleton();
12738
12739 // Call into InternalLoad with the pending channel when it is received.
12740 cpcl->RegisterCallback(
12741 aIdentifier, [self](nsDocShellLoadState* aLoadState,
12742 nsTArray<Endpoint<extensions::PStreamFilterParent>>&&
12743 aStreamFilterEndpoints,
12744 nsDOMNavigationTiming* aTiming) {
12745 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", 12745); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aLoadState->GetPendingRedirectedChannel()"
")"); do { MOZ_CrashSequence(__null, 12745); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12746 if (NS_WARN_IF(self->mIsBeingDestroyed)NS_warn_if_impl(self->mIsBeingDestroyed, "self->mIsBeingDestroyed"
, "./../../../docshell/base/nsDocShell.cpp", 12746)
) {
12747 aLoadState->GetPendingRedirectedChannel()->CancelWithReason(
12748 NS_BINDING_ABORTED, "nsDocShell::mIsBeingDestroyed"_ns);
12749 return NS_BINDING_ABORTED;
12750 }
12751
12752 self->mLoadType = aLoadState->LoadType();
12753 nsCOMPtr<nsIURI> previousURI;
12754 uint32_t previousFlags = 0;
12755 ExtractLastVisit(aLoadState->GetPendingRedirectedChannel(),
12756 getter_AddRefs(previousURI), &previousFlags);
12757 self->SaveLastVisit(aLoadState->GetPendingRedirectedChannel(),
12758 previousURI, previousFlags);
12759
12760 if (aTiming) {
12761 self->mTiming = new nsDOMNavigationTiming(self, aTiming);
12762 self->mBlankTiming = false;
12763 }
12764
12765 // Prohibit initial about:blank handling e.g. for when a cross-process
12766 // iframe loads about:blank and becomes same-process. Conceptually, the
12767 // browsing context isn't new despite the docshell being newly created.
12768 aLoadState->ProhibitInitialAboutBlankHandling();
12769
12770 self->InternalLoad(aLoadState);
12771
12772 if (aLoadState->GetOriginalURIString().isSome()) {
12773 // Save URI string in case it's needed later when
12774 // sending to search engine service in EndPageLoad()
12775 self->mOriginalUriString = *aLoadState->GetOriginalURIString();
12776 }
12777
12778 for (auto& endpoint : aStreamFilterEndpoints) {
12779 extensions::StreamFilterParent::Attach(
12780 aLoadState->GetPendingRedirectedChannel(), std::move(endpoint));
12781 }
12782
12783 // If the channel isn't pending, then it means that InternalLoad
12784 // never connected it, and we shouldn't try to continue. This
12785 // can happen even if InternalLoad returned NS_OK.
12786 bool pending = false;
12787 aLoadState->GetPendingRedirectedChannel()->IsPending(&pending);
12788 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", 12788
); MOZ_PretendNoReturn(); } } while (0)
;
12789 if (!pending) {
12790 return NS_BINDING_ABORTED;
12791 }
12792 return NS_OK;
12793 });
12794 return NS_OK;
12795}
12796
12797NS_IMETHODIMPnsresult
12798nsDocShell::SetOriginAttributes(JS::Handle<JS::Value> aOriginAttributes,
12799 JSContext* aCx) {
12800 OriginAttributes attrs;
12801 if (!aOriginAttributes.isObject() || !attrs.Init(aCx, aOriginAttributes)) {
12802 return NS_ERROR_INVALID_ARG;
12803 }
12804
12805 return SetOriginAttributes(attrs);
12806}
12807
12808NS_IMETHODIMPnsresult
12809nsDocShell::GetAsyncPanZoomEnabled(bool* aOut) {
12810 if (PresShell* presShell = GetPresShell()) {
12811 *aOut = presShell->AsyncPanZoomEnabled();
12812 return NS_OK;
12813 }
12814
12815 // If we don't have a presShell, fall back to the default platform value of
12816 // whether or not APZ is enabled.
12817 *aOut = gfxPlatform::AsyncPanZoomEnabled();
12818 return NS_OK;
12819}
12820
12821bool nsDocShell::HasUnloadedParent() {
12822 for (WindowContext* wc = GetBrowsingContext()->GetParentWindowContext(); wc;
12823 wc = wc->GetParentWindowContext()) {
12824 if (!wc->IsCurrent() || wc->IsDiscarded() ||
12825 wc->GetBrowsingContext()->IsDiscarded()) {
12826 // If a parent is OOP and the parent WindowContext is no
12827 // longer current, we can assume the parent was unloaded.
12828 return true;
12829 }
12830
12831 if (wc->GetBrowsingContext()->IsInProcess() &&
12832 (!wc->GetBrowsingContext()->GetDocShell() ||
12833 wc->GetBrowsingContext()->GetDocShell()->GetIsInUnload())) {
12834 return true;
12835 }
12836 }
12837 return false;
12838}
12839
12840/* static */
12841bool nsDocShell::ShouldUpdateGlobalHistory(uint32_t aLoadType) {
12842 return !(aLoadType == LOAD_BYPASS_HISTORY || aLoadType == LOAD_ERROR_PAGE ||
12843 aLoadType & LOAD_CMD_HISTORY);
12844}
12845
12846void nsDocShell::UpdateGlobalHistoryTitle(nsIURI* aURI) {
12847 if (!mBrowsingContext->GetUseGlobalHistory() || UsePrivateBrowsing()) {
12848 return;
12849 }
12850
12851 // Global history is interested into sub-frame visits only for link-coloring
12852 // purposes, thus title updates are skipped for those.
12853 //
12854 // Moreover, some iframe documents (such as the ones created via
12855 // document.open()) inherit the document uri of the caller, which would cause
12856 // us to override a previously set page title with one from the subframe.
12857 if (IsSubframe()) {
12858 return;
12859 }
12860
12861 if (nsCOMPtr<IHistory> history = components::History::Service()) {
12862 history->SetURITitle(aURI, mTitle);
12863 }
12864}
12865
12866bool nsDocShell::IsInvisible() { return mInvisible; }
12867
12868void nsDocShell::SetInvisible(bool aInvisible) { mInvisible = aInvisible; }
12869
12870/* static */
12871void nsDocShell::MaybeNotifyKeywordSearchLoading(const nsString& aProviderId,
12872 const nsString& aKeyword) {
12873 if (aProviderId.IsEmpty()) {
12874 return;
12875 }
12876 nsresult rv;
12877 nsCOMPtr<nsISupportsString> isupportsString =
12878 do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID"@mozilla.org/supports-string;1", &rv);
12879 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"
, 12879); return; } } while (false)
;
12880
12881 rv = isupportsString->SetData(aProviderId);
12882 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"
, 12882); return; } } while (false)
;
12883
12884 nsCOMPtr<nsIObserverService> obsSvc = services::GetObserverService();
12885 if (obsSvc) {
12886 // Note that "keyword-search" refers to a search via the url
12887 // bar, not a bookmarks keyword search.
12888 obsSvc->NotifyObservers(isupportsString, "keyword-search", aKeyword.get());
12889 }
12890}
12891
12892NS_IMETHODIMPnsresult
12893nsDocShell::ShouldPrepareForIntercept(nsIURI* aURI, nsIChannel* aChannel,
12894 bool* aShouldIntercept) {
12895 return mInterceptController->ShouldPrepareForIntercept(aURI, aChannel,
12896 aShouldIntercept);
12897}
12898
12899NS_IMETHODIMPnsresult
12900nsDocShell::ChannelIntercepted(nsIInterceptedChannel* aChannel) {
12901 return mInterceptController->ChannelIntercepted(aChannel);
12902}
12903
12904bool nsDocShell::InFrameSwap() {
12905 RefPtr<nsDocShell> shell = this;
12906 do {
12907 if (shell->mInFrameSwap) {
12908 return true;
12909 }
12910 shell = shell->GetInProcessParentDocshell();
12911 } while (shell);
12912 return false;
12913}
12914
12915UniquePtr<ClientSource> nsDocShell::TakeInitialClientSource() {
12916 return std::move(mInitialClientSource);
12917}
12918
12919NS_IMETHODIMPnsresult
12920nsDocShell::GetEditingSession(nsIEditingSession** aEditSession) {
12921 if (!NS_SUCCEEDED(EnsureEditorData())((bool)(__builtin_expect(!!(!NS_FAILED_impl(EnsureEditorData(
))), 1)))
) {
12922 return NS_ERROR_FAILURE;
12923 }
12924
12925 *aEditSession = do_AddRef(mEditorData->GetEditingSession()).take();
12926 return *aEditSession ? NS_OK : NS_ERROR_FAILURE;
12927}
12928
12929NS_IMETHODIMPnsresult
12930nsDocShell::GetScriptableBrowserChild(nsIBrowserChild** aBrowserChild) {
12931 *aBrowserChild = GetBrowserChild().take();
12932 return *aBrowserChild ? NS_OK : NS_ERROR_FAILURE;
12933}
12934
12935already_AddRefed<nsIBrowserChild> nsDocShell::GetBrowserChild() {
12936 nsCOMPtr<nsIBrowserChild> tc = do_QueryReferent(mBrowserChild);
12937 return tc.forget();
12938}
12939
12940nsCommandManager* nsDocShell::GetCommandManager() {
12941 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", 12941); return nullptr
; } } while (false)
;
12942 return mCommandManager;
12943}
12944
12945NS_IMETHODIMP_(void)void
12946nsDocShell::GetOriginAttributes(mozilla::OriginAttributes& aAttrs) {
12947 mBrowsingContext->GetOriginAttributes(aAttrs);
12948}
12949
12950HTMLEditor* nsIDocShell::GetHTMLEditor() {
12951 nsDocShell* docShell = static_cast<nsDocShell*>(this);
12952 return docShell->GetHTMLEditorInternal();
12953}
12954
12955nsresult nsIDocShell::SetHTMLEditor(HTMLEditor* aHTMLEditor) {
12956 nsDocShell* docShell = static_cast<nsDocShell*>(this);
12957 return docShell->SetHTMLEditorInternal(aHTMLEditor);
12958}
12959
12960#define MATRIX_LENGTH 20
12961
12962NS_IMETHODIMPnsresult
12963nsDocShell::SetColorMatrix(const nsTArray<float>& aMatrix) {
12964 if (aMatrix.Length() == MATRIX_LENGTH) {
12965 mColorMatrix = MakeUnique<gfx::Matrix5x4>();
12966 static_assert(
12967 MATRIX_LENGTH * sizeof(float) == sizeof(mColorMatrix->components),
12968 "Size mismatch for our memcpy");
12969 memcpy(mColorMatrix->components, aMatrix.Elements(),
12970 sizeof(mColorMatrix->components));
12971 } else if (aMatrix.Length() == 0) {
12972 mColorMatrix.reset();
12973 } else {
12974 return NS_ERROR_INVALID_ARG;
12975 }
12976
12977 PresShell* presShell = GetPresShell();
12978 if (!presShell) {
12979 return NS_ERROR_FAILURE;
12980 }
12981
12982 nsIFrame* frame = presShell->GetRootFrame();
12983 if (!frame) {
12984 return NS_ERROR_FAILURE;
12985 }
12986
12987 frame->SchedulePaint();
12988
12989 return NS_OK;
12990}
12991
12992NS_IMETHODIMPnsresult
12993nsDocShell::GetColorMatrix(nsTArray<float>& aMatrix) {
12994 if (mColorMatrix) {
12995 aMatrix.SetLength(MATRIX_LENGTH);
12996 static_assert(
12997 MATRIX_LENGTH * sizeof(float) == sizeof(mColorMatrix->components),
12998 "Size mismatch for our memcpy");
12999 memcpy(aMatrix.Elements(), mColorMatrix->components,
13000 MATRIX_LENGTH * sizeof(float));
13001 }
13002
13003 return NS_OK;
13004}
13005
13006#undef MATRIX_LENGTH
13007
13008NS_IMETHODIMPnsresult
13009nsDocShell::GetIsForceReloading(bool* aForceReload) {
13010 *aForceReload = IsForceReloading();
13011 return NS_OK;
13012}
13013
13014bool nsDocShell::IsForceReloading() { return IsForceReloadType(mLoadType); }
13015
13016NS_IMETHODIMPnsresult
13017nsDocShell::GetBrowsingContextXPCOM(BrowsingContext** aBrowsingContext) {
13018 *aBrowsingContext = do_AddRef(mBrowsingContext).take();
13019 return NS_OK;
13020}
13021
13022BrowsingContext* nsDocShell::GetBrowsingContext() { return mBrowsingContext; }
13023
13024bool nsDocShell::GetIsAttemptingToNavigate() {
13025 // XXXbz the document.open spec says to abort even if there's just a
13026 // queued navigation task, sort of. It's not clear whether browsers
13027 // actually do that, and we didn't use to do it, so for now let's
13028 // not do that.
13029 // https://github.com/whatwg/html/issues/3447 tracks the spec side of this.
13030 if (mDocumentRequest) {
13031 // There's definitely a navigation in progress.
13032 return true;
13033 }
13034
13035 // javascript: channels have slightly weird behavior: they're LOAD_BACKGROUND
13036 // until the script runs, which means they're not sending loadgroup
13037 // notifications and hence not getting set as mDocumentRequest. Look through
13038 // our loadgroup for document-level javascript: loads.
13039 if (!mLoadGroup) {
13040 return false;
13041 }
13042
13043 nsCOMPtr<nsISimpleEnumerator> requests;
13044 mLoadGroup->GetRequests(getter_AddRefs(requests));
13045 bool hasMore = false;
13046 while (NS_SUCCEEDED(requests->HasMoreElements(&hasMore))((bool)(__builtin_expect(!!(!NS_FAILED_impl(requests->HasMoreElements
(&hasMore))), 1)))
&& hasMore) {
13047 nsCOMPtr<nsISupports> elem;
13048 requests->GetNext(getter_AddRefs(elem));
13049 nsCOMPtr<nsIScriptChannel> scriptChannel(do_QueryInterface(elem));
13050 if (!scriptChannel) {
13051 continue;
13052 }
13053
13054 if (scriptChannel->GetIsDocumentLoad()) {
13055 // This is a javascript: load that might lead to a new document,
13056 // hence a navigation.
13057 return true;
13058 }
13059 }
13060
13061 if (mOngoingNavigation == Some(OngoingNavigation::NavigationID)) {
13062 return true;
13063 }
13064
13065 return mCheckingSessionHistory;
13066}
13067
13068mozilla::dom::SessionHistoryInfo* nsDocShell::GetActiveSessionHistoryInfo()
13069 const {
13070 return mActiveEntry.get();
13071}
13072
13073void nsDocShell::SetLoadingSessionHistoryInfo(
13074 const mozilla::dom::LoadingSessionHistoryInfo& aLoadingInfo,
13075 bool aNeedToReportActiveAfterLoadingBecomesActive) {
13076 // FIXME Would like to assert this, but can't yet.
13077 // MOZ_ASSERT(!mLoadingEntry);
13078 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)
13079 ("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)
13080 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)
;
13081 mLoadingEntry = MakeUnique<LoadingSessionHistoryInfo>(aLoadingInfo);
13082 mNeedToReportActiveAfterLoadingBecomesActive =
13083 aNeedToReportActiveAfterLoadingBecomesActive;
13084}
13085
13086void nsDocShell::MoveLoadingToActiveEntry(bool aExpired, uint32_t aCacheKey,
13087 nsIURI* aPreviousURI) {
13088 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)
13089 ("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)
;
13090
13091 UniquePtr<SessionHistoryInfo> previousActiveEntry(mActiveEntry.release());
13092 mozilla::UniquePtr<mozilla::dom::LoadingSessionHistoryInfo> loadingEntry;
13093 mActiveEntryIsLoadingFromSessionHistory =
13094 mLoadingEntry && mLoadingEntry->mLoadIsFromSessionHistory;
13095 if (mLoadingEntry) {
13096 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)
13097 ("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)
13098 "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)
13099 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)
;
13100 mActiveEntry = MakeUnique<SessionHistoryInfo>(mLoadingEntry->mInfo);
13101 mLoadingEntry.swap(loadingEntry);
13102 if (!mActiveEntryIsLoadingFromSessionHistory) {
13103 if (mNeedToReportActiveAfterLoadingBecomesActive) {
13104 // Needed to pass various history length WPTs.
13105 mBrowsingContext->SetActiveSessionHistoryEntry(
13106 mozilla::Nothing(), mActiveEntry.get(), previousActiveEntry.get(),
13107 mLoadType,
13108 /* aUpdatedCacheKey = */ 0, false);
13109 }
13110 if (!(previousActiveEntry && previousActiveEntry->IsTransient())) {
13111 mBrowsingContext->IncrementHistoryEntryCountForBrowsingContext();
13112 }
13113 }
13114 }
13115 mNeedToReportActiveAfterLoadingBecomesActive = false;
13116
13117 if (mActiveEntry) {
13118 if (aCacheKey != 0) {
13119 mActiveEntry->SetCacheKey(aCacheKey);
13120 }
13121
13122 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"
, 13122); AnnotateMozCrashReason("MOZ_ASSERT" "(" "loadingEntry"
")"); do { MOZ_CrashSequence(__null, 13122); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
13123 uint32_t loadType =
13124 mLoadType == LOAD_ERROR_PAGE ? mFailedLoadType : mLoadType;
13125
13126 if (loadingEntry->mLoadId != UINT64_MAX(18446744073709551615UL)) {
13127 // We're passing in mCurrentURI, which could be null. SessionHistoryCommit
13128 // does require a non-null uri if this is for a refresh load of the same
13129 // URI, but in that case mCurrentURI won't be null here.
13130 mBrowsingContext->SessionHistoryCommit(
13131 *loadingEntry, loadType, aPreviousURI, previousActiveEntry.get(),
13132 false, aExpired, aCacheKey);
13133 }
13134
13135 // Only update navigation if the new entry will be persisted (i.e., is not
13136 // an about: page).
13137 if (!loadingEntry->mInfo.IsTransient() && GetWindow() &&
13138 GetWindow()->GetCurrentInnerWindow()) {
13139 if (RefPtr navigation =
13140 GetWindow()->GetCurrentInnerWindow()->Navigation()) {
13141 navigation->InitializeHistoryEntries(loadingEntry->mContiguousEntries,
13142 mActiveEntry.get());
13143
13144 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)
13145 "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)
13146 "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)
13147 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)
13148 .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)
13149 .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)
13150 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)
13151 .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)
13152 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)
13153 })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)
13154 .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)
;
13155 navigation->CreateNavigationActivationFrom(
13156 loadingEntry->mPreviousEntry,
13157 loadingEntry->mTriggeringNavigationType);
13158 }
13159 }
13160 }
13161}
13162
13163static bool IsFaviconLoad(nsIRequest* aRequest) {
13164 nsCOMPtr<nsIChannel> channel = do_QueryInterface(aRequest);
13165 if (!channel) {
13166 return false;
13167 }
13168
13169 nsCOMPtr<nsILoadInfo> li = channel->LoadInfo();
13170 return li && li->InternalContentPolicyType() ==
13171 nsIContentPolicy::TYPE_INTERNAL_IMAGE_FAVICON;
13172}
13173
13174void nsDocShell::RecordSingleChannelId(bool aStartRequest,
13175 nsIRequest* aRequest) {
13176 // Ignore favicon loads, they don't need to block caching.
13177 if (IsFaviconLoad(aRequest)) {
13178 return;
13179 }
13180
13181 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", 13181); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "mRequestForBlockingFromBFCacheCount > 0"
")"); do { MOZ_CrashSequence(__null, 13181); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false); } } while
(false)
;
13182
13183 mRequestForBlockingFromBFCacheCount += aStartRequest ? 1 : -1;
13184
13185 if (mBrowsingContext->GetCurrentWindowContext()) {
13186 // We have three states: no request, one request with an id and
13187 // eiher one request without an id or multiple requests. Nothing() is no
13188 // request, Some(non-zero) is one request with an id and Some(0) is one
13189 // request without an id or multiple requests.
13190 Maybe<uint64_t> singleChannelId;
13191 if (mRequestForBlockingFromBFCacheCount > 1) {
13192 singleChannelId = Some(0);
13193 } else if (mRequestForBlockingFromBFCacheCount == 1) {
13194 nsCOMPtr<nsIIdentChannel> identChannel;
13195 if (aStartRequest) {
13196 identChannel = do_QueryInterface(aRequest);
13197 } else {
13198 // aChannel is the channel that's being removed, but we need to check if
13199 // the remaining channel in the loadgroup has an id.
13200 nsCOMPtr<nsISimpleEnumerator> requests;
13201 mLoadGroup->GetRequests(getter_AddRefs(requests));
13202 for (const auto& request : SimpleEnumerator<nsIRequest>(requests)) {
13203 if (!IsFaviconLoad(request) &&
13204 !!(identChannel = do_QueryInterface(request))) {
13205 break;
13206 }
13207 }
13208 }
13209
13210 if (identChannel) {
13211 singleChannelId = Some(identChannel->ChannelId());
13212 } else {
13213 singleChannelId = Some(0);
13214 }
13215 } else {
13216 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", 13216); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "mRequestForBlockingFromBFCacheCount == 0" ")"
); do { MOZ_CrashSequence(__null, 13216); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
13217 singleChannelId = Nothing();
13218 }
13219
13220 if (MOZ_UNLIKELY(MOZ_LOG_TEST(gSHIPBFCacheLog, LogLevel::Verbose))(__builtin_expect(!!((__builtin_expect(!!(mozilla::detail::log_test
(gSHIPBFCacheLog, LogLevel::Verbose)), 0))), 0))
) {
13221 nsAutoCString uri("[no uri]");
13222 if (mCurrentURI) {
13223 uri = mCurrentURI->GetSpecOrDefault();
13224 }
13225 if (singleChannelId.isNothing()) {
13226 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)
13227 ("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)
13228 "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)
13229 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)
;
13230 } else if (singleChannelId.value() == 0) {
13231 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)
13232 ("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)
13233 "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)
13234 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)
;
13235 } else {
13236 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)
13237 ("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)
13238 " 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)
13239 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)
;
13240 }
13241 }
13242
13243 if (mSingleChannelId != singleChannelId) {
13244 mSingleChannelId = singleChannelId;
13245 WindowGlobalChild* wgc =
13246 mBrowsingContext->GetCurrentWindowContext()->GetWindowGlobalChild();
13247 if (wgc) {
13248 wgc->SendSetSingleChannelId(singleChannelId);
13249 }
13250 }
13251 }
13252}
13253
13254NS_IMETHODIMPnsresult
13255nsDocShell::OnStartRequest(nsIRequest* aRequest) {
13256 if (MOZ_UNLIKELY(MOZ_LOG_TEST(gSHIPBFCacheLog, LogLevel::Verbose))(__builtin_expect(!!((__builtin_expect(!!(mozilla::detail::log_test
(gSHIPBFCacheLog, LogLevel::Verbose)), 0))), 0))
) {
13257 nsAutoCString uri("[no uri]");
13258 if (mCurrentURI) {
13259 uri = mCurrentURI->GetSpecOrDefault();
13260 }
13261 nsAutoCString name;
13262 aRequest->GetName(name);
13263 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)
13264 ("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)
;
13265 }
13266 RecordSingleChannelId(true, aRequest);
13267 return nsDocLoader::OnStartRequest(aRequest);
13268}
13269
13270NS_IMETHODIMPnsresult
13271nsDocShell::OnStopRequest(nsIRequest* aRequest, nsresult aStatusCode) {
13272 if (MOZ_UNLIKELY(MOZ_LOG_TEST(gSHIPBFCacheLog, LogLevel::Verbose))(__builtin_expect(!!((__builtin_expect(!!(mozilla::detail::log_test
(gSHIPBFCacheLog, LogLevel::Verbose)), 0))), 0))
) {
13273 nsAutoCString uri("[no uri]");
13274 if (mCurrentURI) {
13275 uri = mCurrentURI->GetSpecOrDefault();
13276 }
13277 nsAutoCString name;
13278 aRequest->GetName(name);
13279 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)
13280 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)
13281 ("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)
;
13282 }
13283 RecordSingleChannelId(false, aRequest);
13284 return nsDocLoader::OnStopRequest(aRequest, aStatusCode);
13285}
13286
13287void nsDocShell::MaybeDisconnectChildListenersOnPageHide() {
13288 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", 13288); AnnotateMozCrashReason
("MOZ_RELEASE_ASSERT" "(" "XRE_IsContentProcess()" ")"); do {
MOZ_CrashSequence(__null, 13288); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
13289
13290 if (mChannelToDisconnectOnPageHide != 0 && mLoadGroup) {
13291 nsCOMPtr<nsISimpleEnumerator> requests;
13292 mLoadGroup->GetRequests(getter_AddRefs(requests));
13293 for (const auto& request : SimpleEnumerator<nsIRequest>(requests)) {
13294 RefPtr<DocumentChannel> channel = do_QueryObject(request);
13295 if (channel && channel->ChannelId() == mChannelToDisconnectOnPageHide) {
13296 static_cast<DocumentChannelChild*>(channel.get())
13297 ->DisconnectChildListeners(NS_BINDING_ABORTED, NS_BINDING_ABORTED);
13298 }
13299 }
13300 mChannelToDisconnectOnPageHide = 0;
13301 }
13302}
13303
13304bool nsDocShell::IsSameDocumentAsActiveEntry(
13305 const mozilla::dom::SessionHistoryInfo& aSHInfo) {
13306 return mActiveEntry ? mActiveEntry->SharesDocumentWith(aSHInfo) : false;
13307}
13308
13309// https://html.spec.whatwg.org/#nav-window
13310nsPIDOMWindowInner* nsDocShell::GetActiveWindow() {
13311 nsPIDOMWindowOuter* outer = GetWindow();
13312 return outer ? outer->GetCurrentInnerWindow() : nullptr;
13313}
13314
13315// https://html.spec.whatwg.org/#inform-the-navigation-api-about-aborting-navigation
13316void nsDocShell::InformNavigationAPIAboutAbortingNavigation() {
13317 // Step 1
13318 // We really have no idea what this means.
13319
13320 // No ongoing navigations if we don't have a window.
13321 RefPtr<nsPIDOMWindowInner> window = GetActiveWindow();
13322 if (!window) {
13323 return;
13324 }
13325
13326 // Step 2
13327 RefPtr<Navigation> navigation = window->Navigation();
13328 if (!navigation) {
13329 return;
13330 }
13331
13332 AutoJSAPI jsapi;
13333 if (!jsapi.Init(navigation->GetRelevantGlobal())) {
13334 return;
13335 }
13336
13337 // Steps 3 & 4
13338 // See https://github.com/whatwg/html/issues/11579
13339 navigation->InnerInformAboutAbortingNavigation(jsapi.cx());
13340}
13341
13342// https://html.spec.whatwg.org/#inform-the-navigation-api-about-child-navigable-destruction
13343void nsDocShell::InformNavigationAPIAboutChildNavigableDestruction() {
13344 // Step 1
13345 InformNavigationAPIAboutAbortingNavigation();
13346
13347 // No ongoing navigations if we don't have a window.
13348 RefPtr<nsPIDOMWindowInner> window = GetActiveWindow();
13349 if (!window) {
13350 return;
13351 }
13352
13353 // Step 2
13354 RefPtr<Navigation> navigation = window->Navigation();
13355 if (!navigation) {
13356 return;
13357 }
13358
13359 AutoJSAPI jsapi;
13360 if (!jsapi.Init(navigation->GetRelevantGlobal())) {
13361 return;
13362 }
13363
13364 navigation->InformAboutChildNavigableDestruction(jsapi.cx());
13365}
13366
13367// https://html.spec.whatwg.org/#set-the-ongoing-navigation
13368void nsDocShell::SetOngoingNavigation(
13369 const Maybe<OngoingNavigation>& aOngoingNavigation) {
13370 // We currently only use #set-the-ongoing-navigation to call,
13371 // #inform-the-navigation-api-about-aborting-navigation, but really it should
13372 // be used for more. The spec keeps a piece of state on the navigable:
13373 // https://html.spec.whatwg.org/#ongoing-navigation. Spec uses it for several
13374 // things, for example right here in #set-the-ongoing-navigation to make sure
13375 // that we don't call #inform-the-navigation-api-about-aborting-navigation if
13376 // we're setting it to the same value. We currently only care about aborting
13377 // the currently firing navigate event. Also, in reality, this is very much
13378 // related to nsDocShell::GetIsAttemptingToNavigate() which is what we
13379 // currently use to determine if we need to stop an ongoing navigation in
13380 // Document::Open, whereas the spec checks if the ongoing navigation is a
13381 // NavigationID.
13382
13383 // Step 1, with the exception that we assume setting the ongoing navigation to
13384 // an id always means a fresh id.
13385 if (aOngoingNavigation == mOngoingNavigation &&
13386 aOngoingNavigation != Some(OngoingNavigation::NavigationID)) {
13387 return;
13388 }
13389
13390 // Step 2
13391 InformNavigationAPIAboutAbortingNavigation();
13392
13393 // Step 3
13394 mOngoingNavigation = aOngoingNavigation;
13395}
13396
13397void nsDocShell::StopPendingJavascriptURLNavigations() {
13398 nsCOMPtr<nsISimpleEnumerator> requests;
13399 mLoadGroup->GetRequests(getter_AddRefs(requests));
13400 bool hasMore;
13401 while (NS_SUCCEEDED(requests->HasMoreElements(&hasMore))((bool)(__builtin_expect(!!(!NS_FAILED_impl(requests->HasMoreElements
(&hasMore))), 1)))
&& hasMore) {
13402 nsCOMPtr<nsISupports> elem;
13403 requests->GetNext(getter_AddRefs(elem));
13404 nsCOMPtr<nsIScriptChannel> script = do_QueryInterface(elem);
13405 if (script) {
13406 nsCOMPtr<nsIRequest> request = do_QueryInterface(elem);
13407 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"
, 13407); AnnotateMozCrashReason("MOZ_ASSERT" "(" "request" ")"
); do { MOZ_CrashSequence(__null, 13407); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
13408 mLoadGroup->CancelRequest(
13409 request, "nsDocShell::StopPendingJavascriptNavigations"_ns,
13410 NS_BINDING_ABORTED);
13411 }
13412 }
13413}