Bug Summary

File:root/firefox-clang/docshell/base/nsDocShell.cpp
Warning:line 3440, 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-22/lib/clang/22 -include /root/firefox-clang/config/gcc_hidden.h -include /root/firefox-clang/obj-x86_64-pc-linux-gnu/mozilla-config.h -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/stl_wrappers -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/system_wrappers -U _FORTIFY_SOURCE -D _FORTIFY_SOURCE=2 -D _GLIBCXX_ASSERTIONS -D DEBUG=1 -D MOZ_HAS_MOZGLUE -D MOZILLA_INTERNAL_API -D IMPL_LIBXUL -D MOZ_SUPPORT_LEAKCHECKING -D STATIC_EXPORTABLE_JS_API -I /root/firefox-clang/docshell/base -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/docshell/base -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/ipc/ipdl/_ipdlheaders -I /root/firefox-clang/ipc/chromium/src -I /root/firefox-clang/docshell/shistory -I /root/firefox-clang/dom/base -I /root/firefox-clang/dom/bindings -I /root/firefox-clang/js/xpconnect/src -I /root/firefox-clang/layout/base -I /root/firefox-clang/layout/generic -I /root/firefox-clang/layout/style -I /root/firefox-clang/layout/xul -I /root/firefox-clang/netwerk/base -I /root/firefox-clang/netwerk/protocol/viewsource -I /root/firefox-clang/toolkit/components/browser -I /root/firefox-clang/toolkit/components/find -I /root/firefox-clang/tools/profiler -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/nspr -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/nss -D MOZILLA_CLIENT -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/15/../../../../include/c++/15 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/15/../../../../include/x86_64-linux-gnu/c++/15 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/15/../../../../include/c++/15/backward -internal-isystem /usr/lib/llvm-22/lib/clang/22/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/15/../../../../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-deprecated-this-capture -Wno-inline-new-delete -Wno-error=deprecated-declarations -Wno-error=array-bounds -Wno-error=free-nonheap-object -Wno-error=atomic-alignment -Wno-error=deprecated-builtins -Wno-psabi -Wno-error=builtin-macro-redefined -Wno-vla-cxx-extension -Wno-unknown-warning-option -Wno-character-conversion -fdeprecated-macro -ferror-limit 19 -fstrict-flex-arrays=1 -stack-protector 2 -fstack-clash-protection -ftrivial-auto-var-init=pattern -fno-rtti -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -fno-sized-deallocation -fno-aligned-allocation -vectorize-loops -vectorize-slp -analyzer-checker optin.performance.Padding -analyzer-output=html -analyzer-config stable-report-filename=true -faddrsig -fdwarf2-cfi-asm -o /tmp/scan-build-2026-01-17-100050-2808198-1 -x c++ Unified_cpp_docshell_base0.cpp
1/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2/* vim: set ts=8 sts=2 et sw=2 tw=80: */
3/* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7#include "nsDocShell.h"
8
9#include <algorithm>
10#include "mozilla/dom/HTMLFormElement.h"
11
12#ifdef XP_WIN
13# include <process.h>
14# define getpid _getpid
15#else
16# include <unistd.h> // for getpid()
17#endif
18
19#include "mozilla/ArrayUtils.h"
20#include "mozilla/Attributes.h"
21#include "mozilla/AutoRestore.h"
22#include "mozilla/BasePrincipal.h"
23#include "mozilla/Casting.h"
24#include "mozilla/CheckedInt.h"
25#include "mozilla/Components.h"
26#include "mozilla/DebugOnly.h"
27#include "mozilla/Encoding.h"
28#include "mozilla/EventStateManager.h"
29#include "mozilla/HTMLEditor.h"
30#include "mozilla/InputTaskManager.h"
31#include "mozilla/LoadInfo.h"
32#include "mozilla/Logging.h"
33#include "mozilla/MediaFeatureChange.h"
34#include "mozilla/Preferences.h"
35#include "mozilla/PresShell.h"
36#include "mozilla/ResultExtensions.h"
37#include "mozilla/SchedulerGroup.h"
38#include "mozilla/ScopeExit.h"
39#include "mozilla/ScrollContainerFrame.h"
40#include "mozilla/ScrollTypes.h"
41#include "mozilla/SimpleEnumerator.h"
42#include "mozilla/StaticPrefs_browser.h"
43#include "mozilla/StaticPrefs_docshell.h"
44#include "mozilla/StaticPrefs_dom.h"
45#include "mozilla/StaticPrefs_extensions.h"
46#include "mozilla/StaticPrefs_privacy.h"
47#include "mozilla/StaticPrefs_security.h"
48#include "mozilla/StaticPrefs_ui.h"
49#include "mozilla/StaticPrefs_fission.h"
50#include "mozilla/StartupTimeline.h"
51#include "mozilla/StorageAccess.h"
52#include "mozilla/StoragePrincipalHelper.h"
53#include "mozilla/Telemetry.h"
54
55#include "mozilla/Unused.h"
56#include "mozilla/WidgetUtils.h"
57
58#include "mozilla/dom/AutoEntryScript.h"
59#include "mozilla/dom/ChildProcessChannelListener.h"
60#include "mozilla/dom/ClientChannelHelper.h"
61#include "mozilla/dom/ClientHandle.h"
62#include "mozilla/dom/ClientInfo.h"
63#include "mozilla/dom/ClientManager.h"
64#include "mozilla/dom/ClientSource.h"
65#include "mozilla/dom/ContentChild.h"
66#include "mozilla/dom/ContentFrameMessageManager.h"
67#include "mozilla/dom/DocGroup.h"
68#include "mozilla/dom/Element.h"
69#include "mozilla/dom/FragmentDirective.h"
70#include "mozilla/dom/HTMLAnchorElement.h"
71#include "mozilla/dom/HTMLIFrameElement.h"
72#include "mozilla/dom/Navigation.h"
73#include "mozilla/dom/NavigationBinding.h"
74#include "mozilla/dom/NavigationHistoryEntry.h"
75#include "mozilla/dom/PerformanceNavigation.h"
76#include "mozilla/dom/PermissionMessageUtils.h"
77#include "mozilla/dom/PopupBlocker.h"
78#include "mozilla/dom/ScreenOrientation.h"
79#include "mozilla/dom/ScriptSettings.h"
80#include "mozilla/dom/ServiceWorkerInterceptController.h"
81#include "mozilla/dom/ServiceWorkerUtils.h"
82#include "mozilla/dom/SessionHistoryEntry.h"
83#include "mozilla/dom/SessionStorageManager.h"
84#include "mozilla/dom/SessionStoreChangeListener.h"
85#include "mozilla/dom/SessionStoreChild.h"
86#include "mozilla/dom/SessionStoreUtils.h"
87#include "mozilla/dom/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 "nsIExternalProtocolService.h"
129#include "nsIFormPOSTActionChannel.h"
130#include "nsIFrame.h"
131#include "nsIGlobalObject.h"
132#include "nsIHttpChannel.h"
133#include "nsIHttpChannelInternal.h"
134#include "nsIIDNService.h"
135#include "nsIInputStreamChannel.h"
136#include "nsIInterfaceRequestorUtils.h"
137#include "nsILayoutHistoryState.h"
138#include "nsILoadInfo.h"
139#include "nsILoadURIDelegate.h"
140#include "nsIMultiPartChannel.h"
141#include "nsINestedURI.h"
142#include "nsINetworkPredictor.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 "nsISHEntry.h"
164#include "nsISiteSecurityService.h"
165#include "nsISocketProvider.h"
166#include "nsIStringBundle.h"
167#include "nsIStructuredCloneContainer.h"
168#include "nsIBrowserChild.h"
169#include "nsITextToSubURI.h"
170#include "nsITimedChannel.h"
171#include "nsITimer.h"
172#include "nsITransportSecurityInfo.h"
173#include "nsIUploadChannel.h"
174#include "nsIURIFixup.h"
175#include "nsIURIMutator.h"
176#include "nsIURILoader.h"
177#include "nsIViewSourceChannel.h"
178#include "nsIWebBrowserChrome.h"
179#include "nsIWebBrowserFind.h"
180#include "nsIWebProgress.h"
181#include "nsIWidget.h"
182#include "nsIWindowWatcher.h"
183#include "nsIWritablePropertyBag2.h"
184#include "nsIX509Cert.h"
185#include "nsIXULRuntime.h"
186
187#include "nsCommandManager.h"
188#include "nsPIDOMWindow.h"
189#include "nsPIWindowRoot.h"
190
191#include "IHistory.h"
192#include "IUrlClassifierUITelemetry.h"
193
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 "nsDocShellCID.h"
205#include "nsDocShellEditorData.h"
206#include "nsDocShellEnumerator.h"
207#include "nsDocShellLoadState.h"
208#include "nsDocShellLoadTypes.h"
209#include "nsDOMCID.h"
210#include "nsDOMNavigationTiming.h"
211#include "nsDSURIContentListener.h"
212#include "nsEditingSession.h"
213#include "nsError.h"
214#include "nsEscape.h"
215#include "nsFocusManager.h"
216#include "nsGlobalWindowInner.h"
217#include "nsGlobalWindowOuter.h"
218#include "nsJSEnvironment.h"
219#include "nsNetCID.h"
220#include "nsNetUtil.h"
221#include "nsObjectLoadingContent.h"
222#include "nsPingListener.h"
223#include "nsPoint.h"
224#include "nsQueryObject.h"
225#include "nsQueryActor.h"
226#include "nsRect.h"
227#include "nsRefreshTimer.h"
228#include "nsSandboxFlags.h"
229#include "nsSHEntry.h"
230#include "nsSHistory.h"
231#include "nsSHEntry.h"
232#include "nsStructuredCloneContainer.h"
233#include "nsSubDocumentFrame.h"
234#include "nsURILoader.h"
235#include "nsURLHelper.h"
236#include "nsView.h"
237#include "nsViewManager.h"
238#include "nsViewSourceHandler.h"
239#include "nsWebBrowserFind.h"
240#include "nsWhitespaceTokenizer.h"
241#include "nsWidgetsCID.h"
242#include "nsXULAppAPI.h"
243
244#include "CertVerifier.h"
245#include "ThirdPartyUtil.h"
246#include "GeckoProfiler.h"
247#include "mozilla/NullPrincipal.h"
248#include "Navigator.h"
249#include "prenv.h"
250#include "mozilla/ipc/URIUtils.h"
251#include "sslerr.h"
252#include "mozpkix/pkix.h"
253#include "NSSErrorsService.h"
254
255#include "nsDocShellTelemetryUtils.h"
256
257#ifdef MOZ_PLACES1
258# include "mozilla/places/nsFaviconService.h"
259# include "mozIPlacesPendingOperation.h"
260#endif
261
262#if NS_PRINT_PREVIEW1
263# include "nsIDocumentViewerPrint.h"
264# include "nsIWebBrowserPrint.h"
265#endif
266
267using namespace mozilla;
268using namespace mozilla::dom;
269using namespace mozilla::net;
270
271using mozilla::ipc::Endpoint;
272
273// Threshold value in ms for META refresh based redirects
274#define REFRESH_REDIRECT_TIMER15000 15000
275
276static mozilla::LazyLogModule gCharsetMenuLog("CharsetMenu");
277
278#define LOGCHARSETMENU(args)do { const ::mozilla::LogModule* moz_real_module = gCharsetMenuLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, MOZ_LOG_EXPAND_ARGS
args); } } while (0)
\
279 MOZ_LOG(gCharsetMenuLog, mozilla::LogLevel::Debug, args)do { const ::mozilla::LogModule* moz_real_module = gCharsetMenuLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Debug, MOZ_LOG_EXPAND_ARGS
args); } } while (0)
280
281#ifdef DEBUG1
282unsigned long nsDocShell::gNumberOfDocShells = 0;
283static uint64_t gDocshellIDCounter = 0;
284
285static mozilla::LazyLogModule gDocShellLog("nsDocShell");
286static mozilla::LazyLogModule gDocShellAndDOMWindowLeakLogging(
287 "DocShellAndDOMWindowLeak");
288#endif
289static mozilla::LazyLogModule gDocShellLeakLog("nsDocShellLeak");
290extern mozilla::LazyLogModule gPageCacheLog;
291extern mozilla::LazyLogModule gNavigationLog;
292mozilla::LazyLogModule gSHLog("SessionHistory");
293extern mozilla::LazyLogModule gSHIPBFCacheLog;
294
295const char kAppstringsBundleURL[] =
296 "chrome://global/locale/appstrings.properties";
297
298static bool IsTopLevelDoc(BrowsingContext* aBrowsingContext,
299 nsILoadInfo* aLoadInfo) {
300 MOZ_ASSERT(aBrowsingContext)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aBrowsingContext)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aBrowsingContext))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("aBrowsingContext"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 300); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aBrowsingContext" ")"); do { MOZ_CrashSequence
(__null, 300); __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
301 MOZ_ASSERT(aLoadInfo)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aLoadInfo)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aLoadInfo))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aLoadInfo", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 301); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadInfo" ")"
); do { MOZ_CrashSequence(__null, 301); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
302
303 if (aLoadInfo->GetExternalContentPolicyType() !=
304 ExtContentPolicy::TYPE_DOCUMENT) {
305 return false;
306 }
307
308 return aBrowsingContext->IsTopContent();
309}
310
311// True if loading for top level document loading in active tab.
312static bool IsUrgentStart(BrowsingContext* aBrowsingContext,
313 nsILoadInfo* aLoadInfo, uint32_t aLoadType) {
314 MOZ_ASSERT(aBrowsingContext)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aBrowsingContext)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aBrowsingContext))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("aBrowsingContext"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 314); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aBrowsingContext" ")"); do { MOZ_CrashSequence
(__null, 314); __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
315 MOZ_ASSERT(aLoadInfo)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aLoadInfo)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aLoadInfo))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aLoadInfo", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 315); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadInfo" ")"
); do { MOZ_CrashSequence(__null, 315); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
316
317 if (!IsTopLevelDoc(aBrowsingContext, aLoadInfo)) {
318 return false;
319 }
320
321 if (aLoadType &
322 (nsIDocShell::LOAD_CMD_NORMAL | nsIDocShell::LOAD_CMD_HISTORY)) {
323 return true;
324 }
325
326 return aBrowsingContext->IsActive();
327}
328
329nsDocShell::nsDocShell(BrowsingContext* aBrowsingContext,
330 uint64_t aContentWindowID)
331 : nsDocLoader(true),
332 mContentWindowID(aContentWindowID),
333 mBrowsingContext(aBrowsingContext),
334 mParentCharset(nullptr),
335 mTreeOwner(nullptr),
336 mScrollbarPref(ScrollbarPreference::Auto),
337 mCharsetReloadState(eCharsetReloadInit),
338 mParentCharsetSource(0),
339 mFrameMargins(-1, -1),
340 mItemType(aBrowsingContext->IsContent() ? typeContent : typeChrome),
341 mPreviousEntryIndex(-1),
342 mLoadedEntryIndex(-1),
343 mBusyFlags(BUSY_FLAGS_NONE),
344 mAppType(nsIDocShell::APP_TYPE_UNKNOWN),
345 mLoadType(0),
346 mFailedLoadType(0),
347 mChannelToDisconnectOnPageHide(0),
348 mCreatingDocument(false),
349#ifdef DEBUG1
350 mInEnsureScriptEnv(false),
351#endif
352 mInitialized(false),
353 mAllowSubframes(true),
354 mAllowMetaRedirects(true),
355 mAllowImages(true),
356 mAllowMedia(true),
357 mAllowDNSPrefetch(true),
358 mAllowWindowControl(true),
359 mCSSErrorReportingEnabled(false),
360 mAllowAuth(mItemType == typeContent),
361 mAllowKeywordFixup(false),
362 mDisableMetaRefreshWhenInactive(false),
363 mWindowDraggingAllowed(false),
364 mInFrameSwap(false),
365 mFiredUnloadEvent(false),
366 mEODForCurrentDocument(false),
367 mURIResultedInDocument(false),
368 mIsBeingDestroyed(false),
369 mIsExecutingOnLoadHandler(false),
370 mSavingOldViewer(false),
371 mInvisible(false),
372 mHasLoadedNonBlankURI(false),
373 mBlankTiming(false),
374 mTitleValidForCurrentURI(false),
375 mWillChangeProcess(false),
376 mIsNavigating(false),
377 mForcedAutodetection(false),
378 mCheckingSessionHistory(false),
379 mNeedToReportActiveAfterLoadingBecomesActive(false) {
380 // If no outer window ID was provided, generate a new one.
381 if (aContentWindowID == 0) {
382 mContentWindowID = nsContentUtils::GenerateWindowId();
383 }
384
385 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)
;
386
387#ifdef DEBUG1
388 mDocShellID = gDocshellIDCounter++;
389 // We're counting the number of |nsDocShells| to help find leaks
390 ++gNumberOfDocShells;
391 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)
392 ("++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)
393 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)
;
394#endif
395}
396
397nsDocShell::~nsDocShell() {
398 // Avoid notifying observers while we're in the dtor.
399 mIsBeingDestroyed = true;
400
401 Destroy();
402
403 if (mDocumentViewer) {
404 mDocumentViewer->Close(nullptr);
405 mDocumentViewer->Destroy();
406 mDocumentViewer = nullptr;
407 }
408
409 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)
;
410
411#ifdef DEBUG1
412 if (MOZ_LOG_TEST(gDocShellAndDOMWindowLeakLogging, LogLevel::Info)(__builtin_expect(!!(mozilla::detail::log_test(gDocShellAndDOMWindowLeakLogging
, LogLevel::Info)), 0))
) {
413 nsAutoCString url;
414 if (mLastOpenedURI) {
415 url = mLastOpenedURI->GetSpecOrDefault();
416
417 // Data URLs can be very long, so truncate to avoid flooding the log.
418 const uint32_t maxURLLength = 1000;
419 if (url.Length() > maxURLLength) {
420 url.Truncate(maxURLLength);
421 }
422 }
423
424 // We're counting the number of |nsDocShells| to help find leaks
425 --gNumberOfDocShells;
426 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)
427 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)
428 ("--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)
429 (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)
;
430 }
431#endif
432}
433
434bool nsDocShell::Initialize() {
435 if (mInitialized) {
436 // We've already been initialized.
437 return true;
438 }
439
440 NS_ASSERTION(mItemType == typeContent || mItemType == typeChrome,do { if (!(mItemType == typeContent || mItemType == typeChrome
)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "Unexpected item type in docshell"
, "mItemType == typeContent || mItemType == typeChrome", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 441); MOZ_PretendNoReturn(); } } while (0)
441 "Unexpected item type in docshell")do { if (!(mItemType == typeContent || mItemType == typeChrome
)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "Unexpected item type in docshell"
, "mItemType == typeContent || mItemType == typeChrome", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 441); MOZ_PretendNoReturn(); } } while (0)
;
442
443 NS_ENSURE_TRUE(Preferences::GetRootBranch(), false)do { if ((__builtin_expect(!!(!(Preferences::GetRootBranch())
), 0))) { NS_DebugBreak(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "Preferences::GetRootBranch()"
") failed", nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 443); return false; } } while (false)
;
444 mInitialized = true;
445
446 mDisableMetaRefreshWhenInactive =
447 Preferences::GetBool("browser.meta_refresh_when_inactive.disabled",
448 mDisableMetaRefreshWhenInactive);
449
450 if (nsCOMPtr<nsIObserverService> serv = services::GetObserverService()) {
451 const char* msg = mItemType == typeContent ? NS_WEBNAVIGATION_CREATE"webnavigation-create"
452 : NS_CHROME_WEBNAVIGATION_CREATE"chrome-webnavigation-create";
453 serv->NotifyWhenScriptSafe(GetAsSupports(this), msg, nullptr);
454 }
455
456 return true;
457}
458
459/* static */
460already_AddRefed<nsDocShell> nsDocShell::Create(
461 BrowsingContext* aBrowsingContext, uint64_t aContentWindowID) {
462 MOZ_ASSERT(aBrowsingContext, "DocShell without a BrowsingContext!")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aBrowsingContext)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aBrowsingContext))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("aBrowsingContext"
" (" "DocShell without a BrowsingContext!" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 462); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aBrowsingContext"
") (" "DocShell without a BrowsingContext!" ")"); do { MOZ_CrashSequence
(__null, 462); __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
463
464 nsresult rv;
465 RefPtr<nsDocShell> ds = new nsDocShell(aBrowsingContext, aContentWindowID);
466
467 // Initialize the underlying nsDocLoader.
468 rv = ds->nsDocLoader::InitWithBrowsingContext(aBrowsingContext);
469 if (NS_WARN_IF(NS_FAILED(rv))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(rv
)), 0))), "NS_FAILED(rv)", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 469)
) {
470 return nullptr;
471 }
472
473 // Create our ContentListener
474 ds->mContentListener = new nsDSURIContentListener(ds);
475
476 // We enable if we're in the parent process in order to support non-e10s
477 // configurations.
478 // Note: This check is duplicated in SharedWorkerInterfaceRequestor's
479 // constructor.
480 if (XRE_IsParentProcess()) {
481 ds->mInterceptController = new ServiceWorkerInterceptController();
482 }
483
484 // We want to hold a strong ref to the loadgroup, so it better hold a weak
485 // ref to us... use an InterfaceRequestorProxy to do this.
486 nsCOMPtr<nsIInterfaceRequestor> proxy = new InterfaceRequestorProxy(ds);
487 ds->mLoadGroup->SetNotificationCallbacks(proxy);
488
489 // XXX(nika): We have our BrowsingContext, so we might be able to skip this.
490 // It could be nice to directly set up our DocLoader tree?
491 rv = nsDocLoader::AddDocLoaderAsChildOfRoot(ds);
492 if (NS_WARN_IF(NS_FAILED(rv))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(rv
)), 0))), "NS_FAILED(rv)", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 492)
) {
493 return nullptr;
494 }
495
496 uint32_t notifyMask =
497 nsIWebProgress::NOTIFY_STATE_ALL | nsIWebProgress::NOTIFY_LOCATION |
498 nsIWebProgress::NOTIFY_SECURITY | nsIWebProgress::NOTIFY_STATUS;
499
500 // NOTE: Only listen for NOTIFY_PROGRESS on toplevel BrowsingContexts, as
501 // listeners in the browser UI only cares about total progress on the toplevel
502 // context. Aggregation of the total progress is currently handled within
503 // `nsDocLoader`, and does not take out-of-process iframes into account.
504 if (aBrowsingContext->IsTop()) {
505 notifyMask |= nsIWebProgress::NOTIFY_PROGRESS;
506 }
507
508 // Add |ds| as a progress listener to itself. A little weird, but simpler
509 // than reproducing all the listener-notification logic in overrides of the
510 // various methods via which nsDocLoader can be notified. Note that this
511 // holds an nsWeakPtr to |ds|, so it's ok.
512 rv = ds->AddProgressListener(ds, notifyMask);
513 if (NS_WARN_IF(NS_FAILED(rv))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(rv
)), 0))), "NS_FAILED(rv)", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 513)
) {
514 return nullptr;
515 }
516
517 // If our BrowsingContext has private browsing enabled, update the number of
518 // private browsing docshells.
519 if (aBrowsingContext->UsePrivateBrowsing()) {
520 ds->NotifyPrivateBrowsingChanged();
521 }
522
523 // If our parent window is present in this process, set up our parent now.
524 RefPtr<WindowContext> parentWC = aBrowsingContext->GetParentWindowContext();
525 if (parentWC && parentWC->IsInProcess()) {
526 // If we don't have a parent element anymore, we can't finish this load!
527 // How'd we get here?
528 RefPtr<Element> parentElement = aBrowsingContext->GetEmbedderElement();
529 if (!parentElement) {
530 MOZ_ASSERT_UNREACHABLE("nsDocShell::Create() - !parentElement")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "MOZ_ASSERT_UNREACHABLE: "
"nsDocShell::Create() - !parentElement" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 530); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "nsDocShell::Create() - !parentElement"
")"); do { MOZ_CrashSequence(__null, 530); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
531 return nullptr;
532 }
533
534 // We have an in-process parent window, but don't have a parent nsDocShell?
535 // How'd we get here!
536 nsCOMPtr<nsIDocShell> parentShell =
537 parentElement->OwnerDoc()->GetDocShell();
538 if (!parentShell) {
539 MOZ_ASSERT_UNREACHABLE("nsDocShell::Create() - !parentShell")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "MOZ_ASSERT_UNREACHABLE: "
"nsDocShell::Create() - !parentShell" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 539); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "nsDocShell::Create() - !parentShell"
")"); do { MOZ_CrashSequence(__null, 539); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
540 return nullptr;
541 }
542 parentShell->AddChild(ds);
543 }
544
545 // Make |ds| the primary DocShell for the given context.
546 aBrowsingContext->SetDocShell(ds);
547
548 // Set |ds| default load flags on load group.
549 ds->SetLoadGroupDefaultLoadFlags(aBrowsingContext->GetDefaultLoadFlags());
550
551 return ds.forget();
552}
553
554void nsDocShell::DestroyChildren() {
555 for (auto* child : mChildList.ForwardRange()) {
556 nsCOMPtr<nsIDocShellTreeItem> shell = do_QueryObject(child);
557 NS_ASSERTION(shell, "docshell has null child")do { if (!(shell)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "docshell has null child"
, "shell", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 557); MOZ_PretendNoReturn(); } } while (0)
;
558
559 if (shell) {
560 shell->SetTreeOwner(nullptr);
561 }
562 }
563
564 nsDocLoader::DestroyChildren();
565}
566
567NS_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; }
568 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; }
569 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; }
570 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; }
571 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; }
572
573NS_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; }
574NS_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; }
575
576NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsDocShell)nsresult nsDocShell::QueryInterface(const nsIID& aIID, void
** aInstancePtr) { do { if (!(aInstancePtr)) { NS_DebugBreak(
NS_DEBUG_ASSERTION, "QueryInterface requires a non-NULL destination!"
, "aInstancePtr", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 576); 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
577 NS_INTERFACE_MAP_ENTRY(nsIDocShell)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIDocShell>)) foundInterface = static_cast
<nsIDocShell*>(this); else
578 NS_INTERFACE_MAP_ENTRY(nsIDocShellTreeItem)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIDocShellTreeItem>)) foundInterface
= static_cast<nsIDocShellTreeItem*>(this); else
579 NS_INTERFACE_MAP_ENTRY(nsIWebNavigation)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIWebNavigation>)) foundInterface
= static_cast<nsIWebNavigation*>(this); else
580 NS_INTERFACE_MAP_ENTRY(nsIBaseWindow)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIBaseWindow>)) foundInterface =
static_cast<nsIBaseWindow*>(this); else
581 NS_INTERFACE_MAP_ENTRY(nsIRefreshURI)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIRefreshURI>)) foundInterface =
static_cast<nsIRefreshURI*>(this); else
582 NS_INTERFACE_MAP_ENTRY(nsIWebProgressListener)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIWebProgressListener>)) foundInterface
= static_cast<nsIWebProgressListener*>(this); else
583 NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsISupportsWeakReference>)) foundInterface
= static_cast<nsISupportsWeakReference*>(this); else
584 NS_INTERFACE_MAP_ENTRY(nsIWebPageDescriptor)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIWebPageDescriptor>)) foundInterface
= static_cast<nsIWebPageDescriptor*>(this); else
585 NS_INTERFACE_MAP_ENTRY(nsIAuthPromptProvider)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIAuthPromptProvider>)) foundInterface
= static_cast<nsIAuthPromptProvider*>(this); else
586 NS_INTERFACE_MAP_ENTRY(nsILoadContext)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsILoadContext>)) foundInterface =
static_cast<nsILoadContext*>(this); else
587 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
588 mInterceptController)if ((mInterceptController) && aIID.Equals(mozilla::detail
::kImplementedIID<std::remove_reference_t<decltype(*this
)>, nsINetworkInterceptController>)) foundInterface = static_cast
<nsINetworkInterceptController*>(this); else
589NS_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; }
590
591NS_IMETHODIMPnsresult
592nsDocShell::GetInterface(const nsIID& aIID, void** aSink) {
593 MOZ_ASSERT(aSink, "null out param")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aSink)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(aSink))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("aSink" " (" "null out param"
")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 593
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aSink" ") (" "null out param"
")"); do { MOZ_CrashSequence(__null, 593); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
594
595 *aSink = nullptr;
596
597 if (aIID.Equals(NS_GET_IID(nsICommandManager)(nsICommandManager::kIID))) {
598 NS_ENSURE_SUCCESS(EnsureCommandHandler(), NS_ERROR_FAILURE)do { nsresult __rv = EnsureCommandHandler(); if (((bool)(__builtin_expect
(!!(NS_FAILED_impl(__rv)), 0)))) { const char* name = mozilla
::GetStaticErrorName(__rv); mozilla::SmprintfPointer msg = mozilla
::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%"
"X" "%s%s%s", "EnsureCommandHandler()", "NS_ERROR_FAILURE", static_cast
<uint32_t>(__rv), name ? " (" : "", name ? name : "", name
? ")" : ""); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 598); return
NS_ERROR_FAILURE; } } while (false)
;
599 *aSink = static_cast<nsICommandManager*>(mCommandManager.get());
600 } else if (aIID.Equals(NS_GET_IID(nsIURIContentListener)(nsIURIContentListener::kIID))) {
601 *aSink = mContentListener;
602 } else if ((aIID.Equals(NS_GET_IID(nsIScriptGlobalObject)(nsIScriptGlobalObject::kIID)) ||
603 aIID.Equals(NS_GET_IID(nsIGlobalObject)(nsIGlobalObject::kIID)) ||
604 aIID.Equals(NS_GET_IID(nsPIDOMWindowOuter)(nsPIDOMWindowOuter::kIID)) ||
605 aIID.Equals(NS_GET_IID(mozIDOMWindowProxy)(mozIDOMWindowProxy::kIID)) ||
606 aIID.Equals(NS_GET_IID(nsIDOMWindow)(nsIDOMWindow::kIID))) &&
607 NS_SUCCEEDED(EnsureScriptEnvironment())((bool)(__builtin_expect(!!(!NS_FAILED_impl(EnsureScriptEnvironment
())), 1)))
) {
608 return mScriptGlobal->QueryInterface(aIID, aSink);
609 } else if (aIID.Equals(NS_GET_IID(Document)(Document::kIID)) &&
610 NS_SUCCEEDED(EnsureDocumentViewer())((bool)(__builtin_expect(!!(!NS_FAILED_impl(EnsureDocumentViewer
())), 1)))
) {
611 RefPtr<Document> doc = mDocumentViewer->GetDocument();
612 doc.forget(aSink);
613 return *aSink ? NS_OK : NS_NOINTERFACE;
614 } else if (aIID.Equals(NS_GET_IID(nsIPrompt)(nsIPrompt::kIID)) &&
615 NS_SUCCEEDED(EnsureScriptEnvironment())((bool)(__builtin_expect(!!(!NS_FAILED_impl(EnsureScriptEnvironment
())), 1)))
) {
616 nsresult rv;
617 nsCOMPtr<nsIWindowWatcher> wwatch =
618 do_GetService(NS_WINDOWWATCHER_CONTRACTID"@mozilla.org/embedcomp/window-watcher;1", &rv);
619 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 619); return rv; } } while (false)
;
620
621 // Get the an auth prompter for our window so that the parenting
622 // of the dialogs works as it should when using tabs.
623 nsIPrompt* prompt;
624 rv = wwatch->GetNewPrompter(mScriptGlobal, &prompt);
625 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 625); return rv; } } while (false)
;
626
627 *aSink = prompt;
628 return NS_OK;
629 } else if (aIID.Equals(NS_GET_IID(nsIAuthPrompt)(nsIAuthPrompt::kIID)) ||
630 aIID.Equals(NS_GET_IID(nsIAuthPrompt2)(nsIAuthPrompt2::kIID))) {
631 return NS_SUCCEEDED(GetAuthPrompt(PROMPT_NORMAL, aIID, aSink))((bool)(__builtin_expect(!!(!NS_FAILED_impl(GetAuthPrompt(PROMPT_NORMAL
, aIID, aSink))), 1)))
632 ? NS_OK
633 : NS_NOINTERFACE;
634 } else if (aIID.Equals(NS_GET_IID(nsISHistory)(nsISHistory::kIID))) {
635 // This is deprecated, you should instead directly get
636 // ChildSHistory from the browsing context.
637 MOZ_DIAGNOSTIC_ASSERT(do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "Do not try to get a nsISHistory interface from nsIDocShell"
")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 638
); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "false"
") (" "Do not try to get a nsISHistory interface from nsIDocShell"
")"); do { MOZ_CrashSequence(__null, 638); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
638 false, "Do not try to get a nsISHistory interface from nsIDocShell")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "Do not try to get a nsISHistory interface from nsIDocShell"
")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 638
); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "false"
") (" "Do not try to get a nsISHistory interface from nsIDocShell"
")"); do { MOZ_CrashSequence(__null, 638); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
639 return NS_NOINTERFACE;
640 } else if (aIID.Equals(NS_GET_IID(nsIWebBrowserFind)(nsIWebBrowserFind::kIID))) {
641 nsresult rv = EnsureFind();
642 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
643 return rv;
644 }
645
646 *aSink = mFind;
647 NS_ADDREF((nsISupports*)*aSink)((nsISupports*)*aSink)->AddRef();
648 return NS_OK;
649 } else if (aIID.Equals(NS_GET_IID(nsISelectionDisplay)(nsISelectionDisplay::kIID))) {
650 if (PresShell* presShell = GetPresShell()) {
651 return presShell->QueryInterface(aIID, aSink);
652 }
653 } else if (aIID.Equals(NS_GET_IID(nsIDocShellTreeOwner)(nsIDocShellTreeOwner::kIID))) {
654 nsCOMPtr<nsIDocShellTreeOwner> treeOwner;
655 nsresult rv = GetTreeOwner(getter_AddRefs(treeOwner));
656 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && treeOwner) {
657 return treeOwner->QueryInterface(aIID, aSink);
658 }
659 } else if (aIID.Equals(NS_GET_IID(nsIBrowserChild)(nsIBrowserChild::kIID))) {
660 *aSink = GetBrowserChild().take();
661 return *aSink ? NS_OK : NS_ERROR_FAILURE;
662 } else {
663 return nsDocLoader::GetInterface(aIID, aSink);
664 }
665
666 NS_IF_ADDREF(((nsISupports*)*aSink))ns_if_addref(((nsISupports*)*aSink));
667 return *aSink ? NS_OK : NS_NOINTERFACE;
668}
669
670NS_IMETHODIMPnsresult
671nsDocShell::SetCancelContentJSEpoch(int32_t aEpoch) {
672 // Note: this gets called fairly early (before a pageload actually starts).
673 // We could probably defer this even longer.
674 nsCOMPtr<nsIBrowserChild> browserChild = GetBrowserChild();
675 static_cast<BrowserChild*>(browserChild.get())
676 ->SetCancelContentJSEpoch(aEpoch);
677 return NS_OK;
678}
679
680nsresult nsDocShell::CheckDisallowedJavascriptLoad(
681 nsDocShellLoadState* aLoadState) {
682 if (!aLoadState->URI()->SchemeIs("javascript")) {
683 return NS_OK;
684 }
685
686 if (nsCOMPtr<nsIPrincipal> targetPrincipal =
687 GetInheritedPrincipal(/* aConsiderCurrentDocument */ true)) {
688 if (!aLoadState->TriggeringPrincipal()->Subsumes(targetPrincipal)) {
689 return NS_ERROR_DOM_BAD_CROSS_ORIGIN_URI;
690 }
691 return NS_OK;
692 }
693 return NS_ERROR_DOM_BAD_CROSS_ORIGIN_URI;
694}
695
696NS_IMETHODIMPnsresult
697nsDocShell::LoadURI(nsDocShellLoadState* aLoadState, bool aSetNavigating) {
698 return LoadURI(aLoadState, aSetNavigating, false);
699}
700
701nsresult nsDocShell::LoadURI(nsDocShellLoadState* aLoadState,
702 bool aSetNavigating,
703 bool aContinueHandlingSubframeHistory) {
704 MOZ_ASSERT(aLoadState, "Must have a valid load state!")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aLoadState)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aLoadState))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("aLoadState" " (" "Must have a valid load state!"
")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 704
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState" ") ("
"Must have a valid load state!" ")"); do { MOZ_CrashSequence
(__null, 704); __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
705 // NOTE: This comparison between what appears to be internal/external load
706 // flags is intentional, as it's ensuring that the caller isn't using any of
707 // the flags reserved for implementations by the `nsIWebNavigation` interface.
708 // In the future, this check may be dropped.
709 MOZ_ASSERT(do { static_assert( mozilla::detail::AssertionConditionType<
decltype((aLoadState->LoadFlags() & INTERNAL_LOAD_FLAGS_LOADURI_SETUP_FLAGS
) == 0)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!((aLoadState->LoadFlags() & INTERNAL_LOAD_FLAGS_LOADURI_SETUP_FLAGS
) == 0))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("(aLoadState->LoadFlags() & INTERNAL_LOAD_FLAGS_LOADURI_SETUP_FLAGS) == 0"
" (" "Should not have these flags set" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 711); AnnotateMozCrashReason("MOZ_ASSERT" "(" "(aLoadState->LoadFlags() & INTERNAL_LOAD_FLAGS_LOADURI_SETUP_FLAGS) == 0"
") (" "Should not have these flags set" ")"); do { MOZ_CrashSequence
(__null, 711); __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
710 (aLoadState->LoadFlags() & INTERNAL_LOAD_FLAGS_LOADURI_SETUP_FLAGS) == 0,do { static_assert( mozilla::detail::AssertionConditionType<
decltype((aLoadState->LoadFlags() & INTERNAL_LOAD_FLAGS_LOADURI_SETUP_FLAGS
) == 0)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!((aLoadState->LoadFlags() & INTERNAL_LOAD_FLAGS_LOADURI_SETUP_FLAGS
) == 0))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("(aLoadState->LoadFlags() & INTERNAL_LOAD_FLAGS_LOADURI_SETUP_FLAGS) == 0"
" (" "Should not have these flags set" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 711); AnnotateMozCrashReason("MOZ_ASSERT" "(" "(aLoadState->LoadFlags() & INTERNAL_LOAD_FLAGS_LOADURI_SETUP_FLAGS) == 0"
") (" "Should not have these flags set" ")"); do { MOZ_CrashSequence
(__null, 711); __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
711 "Should not have these flags set")do { static_assert( mozilla::detail::AssertionConditionType<
decltype((aLoadState->LoadFlags() & INTERNAL_LOAD_FLAGS_LOADURI_SETUP_FLAGS
) == 0)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!((aLoadState->LoadFlags() & INTERNAL_LOAD_FLAGS_LOADURI_SETUP_FLAGS
) == 0))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("(aLoadState->LoadFlags() & INTERNAL_LOAD_FLAGS_LOADURI_SETUP_FLAGS) == 0"
" (" "Should not have these flags set" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 711); AnnotateMozCrashReason("MOZ_ASSERT" "(" "(aLoadState->LoadFlags() & INTERNAL_LOAD_FLAGS_LOADURI_SETUP_FLAGS) == 0"
") (" "Should not have these flags set" ")"); do { MOZ_CrashSequence
(__null, 711); __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
712 MOZ_ASSERT(aLoadState->TargetBrowsingContext().IsNull(),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aLoadState->TargetBrowsingContext().IsNull())>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(aLoadState->TargetBrowsingContext().IsNull()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("aLoadState->TargetBrowsingContext().IsNull()"
" (" "Targeting doesn't occur until InternalLoad" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 713); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->TargetBrowsingContext().IsNull()"
") (" "Targeting doesn't occur until InternalLoad" ")"); do {
MOZ_CrashSequence(__null, 713); __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
713 "Targeting doesn't occur until InternalLoad")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aLoadState->TargetBrowsingContext().IsNull())>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(aLoadState->TargetBrowsingContext().IsNull()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("aLoadState->TargetBrowsingContext().IsNull()"
" (" "Targeting doesn't occur until InternalLoad" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 713); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->TargetBrowsingContext().IsNull()"
") (" "Targeting doesn't occur until InternalLoad" ")"); do {
MOZ_CrashSequence(__null, 713); __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
;
714
715 if (!aLoadState->TriggeringPrincipal()) {
716 MOZ_ASSERT(false, "LoadURI must have a triggering principal")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "LoadURI must have a triggering principal"
")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 716
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") (" "LoadURI must have a triggering principal"
")"); do { MOZ_CrashSequence(__null, 716); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
717 return NS_ERROR_FAILURE;
718 }
719
720 MOZ_TRY(CheckDisallowedJavascriptLoad(aLoadState))__extension__({ auto mozTryVarTempResult = ::mozilla::ToResult
(CheckDisallowedJavascriptLoad(aLoadState)); if ((__builtin_expect
(!!(mozTryVarTempResult.isErr()), 0))) { return mozTryVarTempResult
.propagateErr(); } mozTryVarTempResult.unwrap(); })
;
721
722 bool oldIsNavigating = mIsNavigating;
723 auto cleanupIsNavigating =
724 MakeScopeExit([&]() { mIsNavigating = oldIsNavigating; });
725 if (aSetNavigating) {
726 mIsNavigating = true;
727 }
728
729 PopupBlocker::PopupControlState popupState = PopupBlocker::openOverridden;
730 if (aLoadState->HasLoadFlags(LOAD_FLAGS_ALLOW_POPUPS)) {
731 popupState = PopupBlocker::openAllowed;
732 // If we allow popups as part of the navigation, ensure we fake a user
733 // interaction, so that popups can, in fact, be allowed to open.
734 if (WindowContext* wc = mBrowsingContext->GetCurrentWindowContext()) {
735 wc->NotifyUserGestureActivation();
736 }
737 }
738
739 AutoPopupStatePusherAutoPopupStatePusherInternal statePusher(popupState);
740
741 if (aLoadState->GetCancelContentJSEpoch().isSome()) {
742 SetCancelContentJSEpoch(*aLoadState->GetCancelContentJSEpoch());
743 }
744
745 // Note: we allow loads to get through here even if mFiredUnloadEvent is
746 // true; that case will get handled in LoadInternal or LoadHistoryEntry,
747 // so we pass false as the second parameter to IsNavigationAllowed.
748 // However, we don't allow the page to change location *in the middle of*
749 // firing beforeunload, so we do need to check if *beforeunload* is currently
750 // firing, so we call IsNavigationAllowed rather than just IsPrintingOrPP.
751 if (!IsNavigationAllowed(true, false)) {
752 return NS_OK; // JS may not handle returning of an error code
753 }
754
755 nsLoadFlags defaultLoadFlags = mBrowsingContext->GetDefaultLoadFlags();
756 if (aLoadState->HasLoadFlags(LOAD_FLAGS_FORCE_TRR)) {
757 defaultLoadFlags |= nsIRequest::LOAD_TRR_ONLY_MODE;
758 } else if (aLoadState->HasLoadFlags(LOAD_FLAGS_DISABLE_TRR)) {
759 defaultLoadFlags |= nsIRequest::LOAD_TRR_DISABLED_MODE;
760 }
761
762 MOZ_ALWAYS_SUCCEEDS(mBrowsingContext->SetDefaultLoadFlags(defaultLoadFlags))do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(mBrowsingContext->SetDefaultLoadFlags(defaultLoadFlags)))
, 1)))), 1))) { } else { do { do { } while (false); MOZ_ReportCrash
("" "NS_SUCCEEDED(mBrowsingContext->SetDefaultLoadFlags(defaultLoadFlags))"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 762); AnnotateMozCrashReason
("MOZ_CRASH(" "NS_SUCCEEDED(mBrowsingContext->SetDefaultLoadFlags(defaultLoadFlags))"
")"); do { MOZ_CrashSequence(__null, 762); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
;
763
764 if (!StartupTimeline::HasRecord(StartupTimeline::FIRST_LOAD_URI) &&
765 mItemType == typeContent && !NS_IsAboutBlank(aLoadState->URI())) {
766 StartupTimeline::RecordOnce(StartupTimeline::FIRST_LOAD_URI);
767 }
768
769 // LoadType used to be set to a default value here, if no LoadInfo/LoadState
770 // object was passed in. That functionality has been removed as of bug
771 // 1492648. LoadType should now be set up by the caller at the time they
772 // create their nsDocShellLoadState object to pass into LoadURI.
773
774 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)
775 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)
776 ("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)
777 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)
;
778
779 if ((!aLoadState->LoadIsFromSessionHistory() &&
780 !LOAD_TYPE_HAS_FLAGS(aLoadState->LoadType(),((aLoadState->LoadType()) & ((LOAD_FLAGS_REPLACE_HISTORY
) << 16))
781 LOAD_FLAGS_REPLACE_HISTORY)((aLoadState->LoadType()) & ((LOAD_FLAGS_REPLACE_HISTORY
) << 16))
) ||
782 aContinueHandlingSubframeHistory) {
783 // This is possibly a subframe, so handle it accordingly.
784 //
785 // If history exists, it will be loaded into the aLoadState object, and the
786 // LoadType will be changed.
787 if (MaybeHandleSubframeHistory(aLoadState,
788 aContinueHandlingSubframeHistory)) {
789 // MaybeHandleSubframeHistory returns true if we need to continue loading
790 // asynchronously.
791 return NS_OK;
792 }
793 }
794
795 if (aLoadState->LoadIsFromSessionHistory()) {
796 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)
797 ("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)
;
798
799 if (!mozilla::SessionHistoryInParent()) {
800 nsCOMPtr<nsISHEntry> entry = aLoadState->SHEntry();
801 return LoadHistoryEntry(entry, aLoadState->LoadType(),
802 aLoadState->HasValidUserGestureActivation());
803 }
804
805 // FIXME Null check aLoadState->GetLoadingSessionHistoryInfo()?
806 return LoadHistoryEntry(*aLoadState->GetLoadingSessionHistoryInfo(),
807 aLoadState->LoadType(),
808 aLoadState->HasValidUserGestureActivation());
809 }
810
811 // On history navigation via Back/Forward buttons, don't execute
812 // automatic JavaScript redirection such as |location.href = ...| or
813 // |window.open()|
814 //
815 // LOAD_NORMAL: window.open(...) etc.
816 // LOAD_STOP_CONTENT: location.href = ..., location.assign(...)
817 if ((aLoadState->LoadType() == LOAD_NORMAL ||
818 aLoadState->LoadType() == LOAD_STOP_CONTENT) &&
819 ShouldBlockLoadingForBackButton()) {
820 return NS_OK;
821 }
822
823 BrowsingContext::Type bcType = mBrowsingContext->GetType();
824
825 // Set up the inheriting principal in LoadState.
826 nsresult rv = aLoadState->SetupInheritingPrincipal(
827 bcType, mBrowsingContext->OriginAttributesRef());
828 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 828); return rv; } } while (false)
;
829
830 rv = aLoadState->SetupTriggeringPrincipal(
831 mBrowsingContext->OriginAttributesRef());
832 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 832); return rv; } } while (false)
;
833
834 aLoadState->CalculateLoadURIFlags();
835
836 MOZ_ASSERT(aLoadState->TypeHint().IsVoid(),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aLoadState->TypeHint().IsVoid())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aLoadState->TypeHint().IsVoid
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("aLoadState->TypeHint().IsVoid()" " (" "Typehint should be null when calling InternalLoad from LoadURI"
")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 837
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->TypeHint().IsVoid()"
") (" "Typehint should be null when calling InternalLoad from LoadURI"
")"); do { MOZ_CrashSequence(__null, 837); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
837 "Typehint should be null when calling InternalLoad from LoadURI")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aLoadState->TypeHint().IsVoid())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aLoadState->TypeHint().IsVoid
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("aLoadState->TypeHint().IsVoid()" " (" "Typehint should be null when calling InternalLoad from LoadURI"
")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 837
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->TypeHint().IsVoid()"
") (" "Typehint should be null when calling InternalLoad from LoadURI"
")"); do { MOZ_CrashSequence(__null, 837); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
838 MOZ_ASSERT(aLoadState->FileName().IsVoid(),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aLoadState->FileName().IsVoid())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aLoadState->FileName().IsVoid
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("aLoadState->FileName().IsVoid()" " (" "FileName should be null when calling InternalLoad from LoadURI"
")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 839
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->FileName().IsVoid()"
") (" "FileName should be null when calling InternalLoad from LoadURI"
")"); do { MOZ_CrashSequence(__null, 839); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
839 "FileName should be null when calling InternalLoad from LoadURI")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aLoadState->FileName().IsVoid())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aLoadState->FileName().IsVoid
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("aLoadState->FileName().IsVoid()" " (" "FileName should be null when calling InternalLoad from LoadURI"
")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 839
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->FileName().IsVoid()"
") (" "FileName should be null when calling InternalLoad from LoadURI"
")"); do { MOZ_CrashSequence(__null, 839); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
840 MOZ_ASSERT(!aLoadState->LoadIsFromSessionHistory(),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aLoadState->LoadIsFromSessionHistory())>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(!aLoadState->LoadIsFromSessionHistory()))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("!aLoadState->LoadIsFromSessionHistory()"
" (" "Shouldn't be loading from an entry when calling InternalLoad "
"from LoadURI" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 842); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aLoadState->LoadIsFromSessionHistory()"
") (" "Shouldn't be loading from an entry when calling InternalLoad "
"from LoadURI" ")"); do { MOZ_CrashSequence(__null, 842); __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
841 "Shouldn't be loading from an entry when calling InternalLoad "do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aLoadState->LoadIsFromSessionHistory())>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(!aLoadState->LoadIsFromSessionHistory()))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("!aLoadState->LoadIsFromSessionHistory()"
" (" "Shouldn't be loading from an entry when calling InternalLoad "
"from LoadURI" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 842); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aLoadState->LoadIsFromSessionHistory()"
") (" "Shouldn't be loading from an entry when calling InternalLoad "
"from LoadURI" ")"); do { MOZ_CrashSequence(__null, 842); __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
842 "from LoadURI")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aLoadState->LoadIsFromSessionHistory())>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(!aLoadState->LoadIsFromSessionHistory()))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("!aLoadState->LoadIsFromSessionHistory()"
" (" "Shouldn't be loading from an entry when calling InternalLoad "
"from LoadURI" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 842); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aLoadState->LoadIsFromSessionHistory()"
") (" "Shouldn't be loading from an entry when calling InternalLoad "
"from LoadURI" ")"); do { MOZ_CrashSequence(__null, 842); __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
;
843
844 // If we have a system triggering principal, we can assume that this load was
845 // triggered by some UI in the browser chrome, such as the URL bar or
846 // bookmark bar. This should count as a user interaction for the current sh
847 // entry, so that the user may navigate back to the current entry, from the
848 // entry that is going to be added as part of this load.
849 nsCOMPtr<nsIPrincipal> triggeringPrincipal =
850 aLoadState->TriggeringPrincipal();
851 if (triggeringPrincipal && triggeringPrincipal->IsSystemPrincipal()) {
852 if (mozilla::SessionHistoryInParent()) {
853 WindowContext* topWc = mBrowsingContext->GetTopWindowContext();
854 if (topWc && !topWc->IsDiscarded()) {
855 MOZ_ALWAYS_SUCCEEDS(topWc->SetSHEntryHasUserInteraction(true))do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(topWc->SetSHEntryHasUserInteraction(true))), 1)))), 1))) {
} else { do { do { } while (false); MOZ_ReportCrash("" "NS_SUCCEEDED(topWc->SetSHEntryHasUserInteraction(true))"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 855); AnnotateMozCrashReason
("MOZ_CRASH(" "NS_SUCCEEDED(topWc->SetSHEntryHasUserInteraction(true))"
")"); do { MOZ_CrashSequence(__null, 855); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
;
856 }
857 } else {
858 bool oshe = false;
859 nsCOMPtr<nsISHEntry> currentSHEntry;
860 GetCurrentSHEntry(getter_AddRefs(currentSHEntry), &oshe);
861 if (currentSHEntry) {
862 currentSHEntry->SetHasUserInteraction(true);
863 }
864 }
865 }
866
867 rv = InternalLoad(aLoadState);
868 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 868); return rv; } } while (false)
;
869
870 if (aLoadState->GetOriginalURIString().isSome()) {
871 // Save URI string in case it's needed later when
872 // sending to search engine service in EndPageLoad()
873 mOriginalUriString = *aLoadState->GetOriginalURIString();
874 }
875
876 return NS_OK;
877}
878
879bool nsDocShell::IsLoadingFromSessionHistory() {
880 return mActiveEntryIsLoadingFromSessionHistory;
881}
882
883// StopDetector is modeled similarly to OnloadBlocker; it is a rather
884// dummy nsIRequest implementation which can be added to an nsILoadGroup to
885// detect Cancel calls.
886class StopDetector final : public nsIRequest {
887 public:
888 StopDetector() = default;
889
890 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:
891 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;
892
893 bool Canceled() { return mCanceled; }
894
895 private:
896 ~StopDetector() = default;
897
898 bool mCanceled = false;
899};
900
901NS_IMPL_ISUPPORTS(StopDetector, nsIRequest)MozExternalRefCountType StopDetector::AddRef(void) { static_assert
(!std::is_destructible_v<StopDetector>, "Reference-counted class "
"StopDetector" " should not have a public destructor. " "Make this class's destructor non-public"
); do { static_assert( mozilla::detail::AssertionConditionType
<decltype(int32_t(mRefCnt) >= 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) >= 0))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) >= 0"
" (" "illegal refcnt" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 901); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { MOZ_CrashSequence(__null, 901
); __attribute__((nomerge)) ::abort(); } while (false); } } while
(false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("StopDetector" != nullptr)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!("StopDetector" != nullptr)))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("\"StopDetector\" != nullptr"
" (" "Must specify a name" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 901); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"StopDetector\" != nullptr"
") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__null
, 901); __attribute__((nomerge)) ::abort(); } while (false); }
} while (false); if (!mRefCnt.isThreadSafe) _mOwningThread.AssertOwnership
("StopDetector" " not thread-safe"); nsrefcnt count = ++mRefCnt
; NS_LogAddRef((this), (count), ("StopDetector"), (uint32_t)(
sizeof(*this))); return count; } MozExternalRefCountType StopDetector
::Release(void) { do { static_assert( mozilla::detail::AssertionConditionType
<decltype(int32_t(mRefCnt) > 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) > 0))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) > 0"
" (" "dup release" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 901); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { MOZ_CrashSequence(__null, 901
); __attribute__((nomerge)) ::abort(); } while (false); } } while
(false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("StopDetector" != nullptr)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!("StopDetector" != nullptr)))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("\"StopDetector\" != nullptr"
" (" "Must specify a name" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 901); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"StopDetector\" != nullptr"
") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__null
, 901); __attribute__((nomerge)) ::abort(); } while (false); }
} while (false); if (!mRefCnt.isThreadSafe) _mOwningThread.AssertOwnership
("StopDetector" " not thread-safe"); const char* const nametmp
= "StopDetector"; nsrefcnt count = --mRefCnt; NS_LogRelease(
(this), (count), (nametmp)); if (count == 0) { mRefCnt = 1; delete
(this); return 0; } return count; } nsresult StopDetector::QueryInterface
(const nsIID& aIID, void** aInstancePtr) { do { if (!(aInstancePtr
)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "QueryInterface requires a non-NULL destination!"
, "aInstancePtr", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 901); 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; }
902
903NS_IMETHODIMPnsresult
904StopDetector::GetName(nsACString& aResult) {
905 aResult.AssignLiteral("about:stop-detector");
906 return NS_OK;
907}
908
909NS_IMETHODIMPnsresult
910StopDetector::IsPending(bool* aRetVal) {
911 *aRetVal = true;
912 return NS_OK;
913}
914
915NS_IMETHODIMPnsresult
916StopDetector::GetStatus(nsresult* aStatus) {
917 *aStatus = NS_OK;
918 return NS_OK;
919}
920
921NS_IMETHODIMPnsresult StopDetector::SetCanceledReason(const nsACString& aReason) {
922 return SetCanceledReasonImpl(aReason);
923}
924
925NS_IMETHODIMPnsresult StopDetector::GetCanceledReason(nsACString& aReason) {
926 return GetCanceledReasonImpl(aReason);
927}
928
929NS_IMETHODIMPnsresult StopDetector::CancelWithReason(nsresult aStatus,
930 const nsACString& aReason) {
931 return CancelWithReasonImpl(aStatus, aReason);
932}
933
934NS_IMETHODIMPnsresult
935StopDetector::Cancel(nsresult aStatus) {
936 mCanceled = true;
937 return NS_OK;
938}
939
940NS_IMETHODIMPnsresult
941StopDetector::Suspend(void) { return NS_OK; }
942NS_IMETHODIMPnsresult
943StopDetector::Resume(void) { return NS_OK; }
944
945NS_IMETHODIMPnsresult
946StopDetector::GetLoadGroup(nsILoadGroup** aLoadGroup) {
947 *aLoadGroup = nullptr;
948 return NS_OK;
949}
950
951NS_IMETHODIMPnsresult
952StopDetector::SetLoadGroup(nsILoadGroup* aLoadGroup) { return NS_OK; }
953
954NS_IMETHODIMPnsresult
955StopDetector::GetLoadFlags(nsLoadFlags* aLoadFlags) {
956 *aLoadFlags = nsIRequest::LOAD_NORMAL;
957 return NS_OK;
958}
959
960NS_IMETHODIMPnsresult
961StopDetector::GetTRRMode(nsIRequest::TRRMode* aTRRMode) {
962 return GetTRRModeImpl(aTRRMode);
963}
964
965NS_IMETHODIMPnsresult
966StopDetector::SetTRRMode(nsIRequest::TRRMode aTRRMode) {
967 return SetTRRModeImpl(aTRRMode);
968}
969
970NS_IMETHODIMPnsresult
971StopDetector::SetLoadFlags(nsLoadFlags aLoadFlags) { return NS_OK; }
972
973bool nsDocShell::MaybeHandleSubframeHistory(
974 nsDocShellLoadState* aLoadState, bool aContinueHandlingSubframeHistory) {
975 // First, verify if this is a subframe.
976 // Note, it is ok to rely on docshell here and not browsing context since when
977 // an iframe is created, it has first in-process docshell.
978 nsCOMPtr<nsIDocShellTreeItem> parentAsItem;
979 GetInProcessSameTypeParent(getter_AddRefs(parentAsItem));
980 nsCOMPtr<nsIDocShell> parentDS(do_QueryInterface(parentAsItem));
981
982 if (!parentDS || parentDS == static_cast<nsIDocShell*>(this)) {
983 if (mBrowsingContext && mBrowsingContext->IsTop()) {
984 // This is the root docshell. If we got here while
985 // executing an onLoad Handler,this load will not go
986 // into session history.
987 // XXX Why is this code in a method which deals with iframes!
988 if (aLoadState->IsFormSubmission()) {
989#ifdef DEBUG1
990 if (!mEODForCurrentDocument) {
991 const MaybeDiscarded<BrowsingContext>& targetBC =
992 aLoadState->TargetBrowsingContext();
993 MOZ_ASSERT_IF(GetBrowsingContext() == targetBC.get(),do { if (GetBrowsingContext() == targetBC.get()) { do { static_assert
( mozilla::detail::AssertionConditionType<decltype(aLoadState
->LoadType() == LOAD_NORMAL_REPLACE)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aLoadState->LoadType() ==
LOAD_NORMAL_REPLACE))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("aLoadState->LoadType() == LOAD_NORMAL_REPLACE", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 994); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->LoadType() == LOAD_NORMAL_REPLACE"
")"); do { MOZ_CrashSequence(__null, 994); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
994 aLoadState->LoadType() == LOAD_NORMAL_REPLACE)do { if (GetBrowsingContext() == targetBC.get()) { do { static_assert
( mozilla::detail::AssertionConditionType<decltype(aLoadState
->LoadType() == LOAD_NORMAL_REPLACE)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aLoadState->LoadType() ==
LOAD_NORMAL_REPLACE))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("aLoadState->LoadType() == LOAD_NORMAL_REPLACE", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 994); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->LoadType() == LOAD_NORMAL_REPLACE"
")"); do { MOZ_CrashSequence(__null, 994); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
995 }
996#endif
997 } else {
998 bool inOnLoadHandler = false;
999 GetIsExecutingOnLoadHandler(&inOnLoadHandler);
1000 if (inOnLoadHandler) {
1001 aLoadState->SetLoadType(LOAD_NORMAL_REPLACE);
1002 }
1003 }
1004 }
1005 return false;
1006 }
1007
1008 /* OK. It is a subframe. Checkout the parent's loadtype. If the parent was
1009 * loaded through a history mechanism, then get the SH entry for the child
1010 * from the parent. This is done to restore frameset navigation while going
1011 * back/forward. If the parent was loaded through any other loadType, set the
1012 * child's loadType too accordingly, so that session history does not get
1013 * confused.
1014 */
1015
1016 // Get the parent's load type
1017 uint32_t parentLoadType;
1018 parentDS->GetLoadType(&parentLoadType);
1019
1020 if (!aContinueHandlingSubframeHistory) {
1021 if (mozilla::SessionHistoryInParent()) {
1022 if (nsDocShell::Cast(parentDS.get())->IsLoadingFromSessionHistory() &&
1023 !GetCreatedDynamically()) {
1024 if (XRE_IsContentProcess()) {
1025 dom::ContentChild* contentChild = dom::ContentChild::GetSingleton();
1026 nsCOMPtr<nsILoadGroup> loadGroup;
1027 GetLoadGroup(getter_AddRefs(loadGroup));
1028 if (contentChild && loadGroup && !mCheckingSessionHistory) {
1029 RefPtr<Document> parentDoc = parentDS->GetDocument();
1030 parentDoc->BlockOnload();
1031 RefPtr<BrowsingContext> browsingContext = mBrowsingContext;
1032 Maybe<uint64_t> currentLoadIdentifier =
1033 mBrowsingContext->GetCurrentLoadIdentifier();
1034 RefPtr<nsDocShellLoadState> loadState = aLoadState;
1035 bool isNavigating = mIsNavigating;
1036 RefPtr<StopDetector> stopDetector = new StopDetector();
1037 loadGroup->AddRequest(stopDetector, nullptr);
1038 // Need to set mCheckingSessionHistory so that
1039 // GetIsAttemptingToNavigate() returns true.
1040 mCheckingSessionHistory = true;
1041
1042 auto resolve =
1043 [currentLoadIdentifier, browsingContext, parentDoc, loadState,
1044 isNavigating, loadGroup, stopDetector](
1045 mozilla::Maybe<LoadingSessionHistoryInfo>&& aResult) {
1046 RefPtr<nsDocShell> docShell =
1047 static_cast<nsDocShell*>(browsingContext->GetDocShell());
1048 auto unblockParent = MakeScopeExit(
1049 [loadGroup, stopDetector, parentDoc, docShell]() {
1050 if (docShell) {
1051 docShell->mCheckingSessionHistory = false;
1052 }
1053 loadGroup->RemoveRequest(stopDetector, nullptr, NS_OK);
1054 parentDoc->UnblockOnload(false);
1055 });
1056
1057 if (!docShell || !docShell->mCheckingSessionHistory) {
1058 return;
1059 }
1060
1061 if (stopDetector->Canceled()) {
1062 return;
1063 }
1064 if (currentLoadIdentifier ==
1065 browsingContext->GetCurrentLoadIdentifier() &&
1066 aResult.isSome()) {
1067 loadState->SetLoadingSessionHistoryInfo(aResult.value());
1068 // This is an initial subframe load from the session
1069 // history, index doesn't need to be updated.
1070 loadState->SetLoadIsFromSessionHistory(0, false);
1071 }
1072
1073 // We got the results back from the parent process, call
1074 // LoadURI again with the possibly updated data.
1075 docShell->LoadURI(loadState, isNavigating, true);
1076 };
1077 auto reject = [loadGroup, stopDetector, browsingContext,
1078 parentDoc](mozilla::ipc::ResponseRejectReason) {
1079 RefPtr<nsDocShell> docShell =
1080 static_cast<nsDocShell*>(browsingContext->GetDocShell());
1081 if (docShell) {
1082 docShell->mCheckingSessionHistory = false;
1083 }
1084 // In practise reject shouldn't be called ever.
1085 loadGroup->RemoveRequest(stopDetector, nullptr, NS_OK);
1086 parentDoc->UnblockOnload(false);
1087 };
1088 contentChild->SendGetLoadingSessionHistoryInfoFromParent(
1089 mBrowsingContext, std::move(resolve), std::move(reject));
1090 return true;
1091 }
1092 } else {
1093 Maybe<LoadingSessionHistoryInfo> info;
1094 mBrowsingContext->Canonical()->GetLoadingSessionHistoryInfoFromParent(
1095 info);
1096 if (info.isSome()) {
1097 aLoadState->SetLoadingSessionHistoryInfo(info.value());
1098 // This is an initial subframe load from the session
1099 // history, index doesn't need to be updated.
1100 aLoadState->SetLoadIsFromSessionHistory(0, false);
1101 }
1102 }
1103 }
1104 } else {
1105 // Get the ShEntry for the child from the parent
1106 nsCOMPtr<nsISHEntry> currentSH;
1107 bool oshe = false;
1108 parentDS->GetCurrentSHEntry(getter_AddRefs(currentSH), &oshe);
1109 bool dynamicallyAddedChild = GetCreatedDynamically();
1110
1111 if (!dynamicallyAddedChild && !oshe && currentSH) {
1112 // Only use the old SHEntry, if we're sure enough that
1113 // it wasn't originally for some other frame.
1114 nsCOMPtr<nsISHEntry> shEntry;
1115 currentSH->GetChildSHEntryIfHasNoDynamicallyAddedChild(
1116 mBrowsingContext->ChildOffset(), getter_AddRefs(shEntry));
1117 if (shEntry) {
1118 aLoadState->SetSHEntry(shEntry);
1119 }
1120 }
1121 }
1122 }
1123
1124 // Make some decisions on the child frame's loadType based on the
1125 // parent's loadType, if the subframe hasn't loaded anything into it.
1126 //
1127 // In some cases privileged scripts may try to get the DOMWindow
1128 // reference of this docshell before the loading starts, causing the
1129 // initial about:blank content viewer being created and mCurrentURI being
1130 // set. To handle this case we check if mCurrentURI is about:blank and
1131 // currentSHEntry is null.
1132 bool oshe = false;
1133 nsCOMPtr<nsISHEntry> currentChildEntry;
1134 GetCurrentSHEntry(getter_AddRefs(currentChildEntry), &oshe);
1135
1136 if (mCurrentURI && (!NS_IsAboutBlank(mCurrentURI) || currentChildEntry ||
1137 mLoadingEntry || mActiveEntry)) {
1138 // This is a pre-existing subframe. If
1139 // 1. The load of this frame was not originally initiated by session
1140 // history directly (i.e. (!shEntry) condition succeeded, but it can
1141 // still be a history load on parent which causes this frame being
1142 // loaded), which we checked with the above assert, and
1143 // 2. mCurrentURI is not null, nor the initial about:blank,
1144 // it is possible that a parent's onLoadHandler or even self's
1145 // onLoadHandler is loading a new page in this child. Check parent's and
1146 // self's busy flag and if it is set, we don't want this onLoadHandler
1147 // load to get in to session history.
1148 BusyFlags parentBusy = parentDS->GetBusyFlags();
1149 BusyFlags selfBusy = GetBusyFlags();
1150
1151 if (parentBusy & BUSY_FLAGS_BUSY || selfBusy & BUSY_FLAGS_BUSY) {
1152 aLoadState->SetLoadType(LOAD_NORMAL_REPLACE);
1153 aLoadState->ClearLoadIsFromSessionHistory();
1154 }
1155 return false;
1156 }
1157
1158 // This is a newly created frame. Check for exception cases first.
1159 // By default the subframe will inherit the parent's loadType.
1160 if (aLoadState->LoadIsFromSessionHistory() &&
1161 (parentLoadType == LOAD_NORMAL || parentLoadType == LOAD_LINK)) {
1162 // The parent was loaded normally. In this case, this *brand new*
1163 // child really shouldn't have a SHEntry. If it does, it could be
1164 // because the parent is replacing an existing frame with a new frame,
1165 // in the onLoadHandler. We don't want this url to get into session
1166 // history. Clear off shEntry, and set load type to
1167 // LOAD_BYPASS_HISTORY.
1168 bool inOnLoadHandler = false;
1169 parentDS->GetIsExecutingOnLoadHandler(&inOnLoadHandler);
1170 if (inOnLoadHandler) {
1171 aLoadState->SetLoadType(LOAD_NORMAL_REPLACE);
1172 aLoadState->ClearLoadIsFromSessionHistory();
1173 }
1174 } else if (parentLoadType == LOAD_REFRESH) {
1175 // Clear shEntry. For refresh loads, we have to load
1176 // what comes through the pipe, not what's in history.
1177 aLoadState->ClearLoadIsFromSessionHistory();
1178 } else if ((parentLoadType == LOAD_BYPASS_HISTORY) ||
1179 (aLoadState->LoadIsFromSessionHistory() &&
1180 ((parentLoadType & LOAD_CMD_HISTORY) ||
1181 (parentLoadType == LOAD_RELOAD_NORMAL) ||
1182 (parentLoadType == LOAD_RELOAD_CHARSET_CHANGE) ||
1183 (parentLoadType == LOAD_RELOAD_CHARSET_CHANGE_BYPASS_CACHE) ||
1184 (parentLoadType ==
1185 LOAD_RELOAD_CHARSET_CHANGE_BYPASS_PROXY_AND_CACHE)))) {
1186 // If the parent url, bypassed history or was loaded from
1187 // history, pass on the parent's loadType to the new child
1188 // frame too, so that the child frame will also
1189 // avoid getting into history.
1190 aLoadState->SetLoadType(parentLoadType);
1191 } else if (parentLoadType == LOAD_ERROR_PAGE) {
1192 // If the parent document is an error page, we don't
1193 // want to update global/session history. However,
1194 // this child frame is not an error page.
1195 aLoadState->SetLoadType(LOAD_BYPASS_HISTORY);
1196 } else if ((parentLoadType == LOAD_RELOAD_BYPASS_CACHE) ||
1197 (parentLoadType == LOAD_RELOAD_BYPASS_PROXY) ||
1198 (parentLoadType == LOAD_RELOAD_BYPASS_PROXY_AND_CACHE)) {
1199 // the new frame should inherit the parent's load type so that it also
1200 // bypasses the cache and/or proxy
1201 aLoadState->SetLoadType(parentLoadType);
1202 }
1203
1204 return false;
1205}
1206
1207/*
1208 * Reset state to a new content model within the current document and the
1209 * document viewer. Called by the document before initiating an out of band
1210 * document.write().
1211 */
1212NS_IMETHODIMPnsresult
1213nsDocShell::PrepareForNewContentModel() {
1214 // Clear out our form control state, because the state of controls
1215 // in the pre-open() document should not affect the state of
1216 // controls that are now going to be written.
1217 SetLayoutHistoryState(nullptr);
1218 mEODForCurrentDocument = false;
1219 return NS_OK;
1220}
1221
1222NS_IMETHODIMPnsresult
1223nsDocShell::FirePageHideNotification(bool aIsUnload) {
1224 FirePageHideNotificationInternal(aIsUnload, false);
1225 return NS_OK;
1226}
1227
1228void nsDocShell::FirePageHideNotificationInternal(
1229 bool aIsUnload, bool aSkipCheckingDynEntries) {
1230 if (mDocumentViewer && !mFiredUnloadEvent) {
1231 // Keep an explicit reference since calling PageHide could release
1232 // mDocumentViewer
1233 nsCOMPtr<nsIDocumentViewer> viewer(mDocumentViewer);
1234 mFiredUnloadEvent = true;
1235
1236 if (mTiming) {
1237 mTiming->NotifyUnloadEventStart();
1238 }
1239
1240 viewer->PageHide(aIsUnload);
1241
1242 if (mTiming) {
1243 mTiming->NotifyUnloadEventEnd();
1244 }
1245
1246 AutoTArray<nsCOMPtr<nsIDocShell>, 8> kids;
1247 uint32_t n = mChildList.Length();
1248 kids.SetCapacity(n);
1249 for (uint32_t i = 0; i < n; i++) {
1250 kids.AppendElement(do_QueryInterface(ChildAt(i)));
1251 }
1252
1253 n = kids.Length();
1254 for (uint32_t i = 0; i < n; ++i) {
1255 RefPtr<nsDocShell> child = static_cast<nsDocShell*>(kids[i].get());
1256 if (child) {
1257 // Skip checking dynamic subframe entries in our children.
1258 child->FirePageHideNotificationInternal(aIsUnload, true);
1259 }
1260 }
1261
1262 // If the document is unloading, remove all dynamic subframe entries.
1263 if (aIsUnload && !aSkipCheckingDynEntries) {
1264 RefPtr<ChildSHistory> rootSH = GetRootSessionHistory();
1265 if (rootSH) {
1266 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)
1267 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)
1268 ("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)
;
1269 if (mozilla::SessionHistoryInParent()) {
1270 if (mActiveEntry) {
1271 mBrowsingContext->RemoveDynEntriesFromActiveSessionHistoryEntry();
1272 }
1273 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)
1274 ("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)
;
1275 } else if (mOSHE) {
1276 int32_t index = rootSH->Index();
1277 rootSH->LegacySHistory()->RemoveDynEntries(index, mOSHE);
1278 }
1279 }
1280 }
1281
1282 // Now make sure our editor, if any, is detached before we go
1283 // any farther.
1284 DetachEditorFromWindow();
1285 }
1286}
1287
1288void nsDocShell::ThawFreezeNonRecursive(bool aThaw) {
1289 MOZ_ASSERT(mozilla::BFCacheInParent())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mozilla::BFCacheInParent())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mozilla::BFCacheInParent()))
), 0))) { do { } while (false); MOZ_ReportAssertionFailure("mozilla::BFCacheInParent()"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 1289); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "mozilla::BFCacheInParent()" ")"); do { MOZ_CrashSequence
(__null, 1289); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
1290
1291 if (!mScriptGlobal) {
1292 return;
1293 }
1294
1295 if (RefPtr<nsGlobalWindowInner> inner =
1296 nsGlobalWindowInner::Cast(mScriptGlobal->GetCurrentInnerWindow())) {
1297 if (aThaw) {
1298 inner->Thaw(false);
1299 } else {
1300 inner->Freeze(false);
1301 }
1302 }
1303}
1304
1305void nsDocShell::FirePageHideShowNonRecursive(bool aShow) {
1306 MOZ_ASSERT(mozilla::BFCacheInParent())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mozilla::BFCacheInParent())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mozilla::BFCacheInParent()))
), 0))) { do { } while (false); MOZ_ReportAssertionFailure("mozilla::BFCacheInParent()"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 1306); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "mozilla::BFCacheInParent()" ")"); do { MOZ_CrashSequence
(__null, 1306); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
1307
1308 if (!mDocumentViewer) {
1309 return;
1310 }
1311
1312 // Emulate what non-SHIP BFCache does too. In pageshow case
1313 // add and remove a request and before that call SetCurrentURI to get
1314 // the location change notification.
1315 // For pagehide, set mFiredUnloadEvent to true, so that unload doesn't fire.
1316 nsCOMPtr<nsIDocumentViewer> viewer(mDocumentViewer);
1317 if (aShow) {
1318 viewer->SetIsHidden(false);
1319 mRefreshURIList = std::move(mBFCachedRefreshURIList);
1320 RefreshURIFromQueue();
1321 mFiredUnloadEvent = false;
1322 RefPtr<Document> doc = viewer->GetDocument();
1323 if (doc) {
1324 doc->NotifyActivityChanged();
1325 nsCOMPtr<nsPIDOMWindowInner> inner =
1326 mScriptGlobal ? mScriptGlobal->GetCurrentInnerWindow() : nullptr;
1327 if (mBrowsingContext->IsTop()) {
1328 doc->NotifyPossibleTitleChange(false);
1329 doc->SetLoadingOrRestoredFromBFCacheTimeStampToNow();
1330 if (inner) {
1331 // Now that we have found the inner window of the page restored
1332 // from the history, we have to make sure that
1333 // performance.navigation.type is 2.
1334 // Traditionally this type change has been done to the top level page
1335 // only.
1336 Performance* performance = inner->GetPerformance();
1337 if (performance) {
1338 performance->GetDOMTiming()->NotifyRestoreStart();
1339 }
1340 }
1341 }
1342
1343 nsCOMPtr<nsIChannel> channel = doc->GetChannel();
1344 if (channel) {
1345 SetLoadType(LOAD_HISTORY);
1346 mEODForCurrentDocument = false;
1347 mIsRestoringDocument = true;
1348 mLoadGroup->AddRequest(channel, nullptr);
1349 nsCOMPtr<nsIURI> uri;
1350 if (doc->FragmentDirective()) {
1351 // If we have fragment directives, then we've mutated the document
1352 // uri. Set the current URI from session history instead.
1353 if (mozilla::SessionHistoryInParent()) {
1354 uri = mActiveEntry ? mActiveEntry->GetURI() : nullptr;
1355 } else if (mOSHE) {
1356 uri = mOSHE->GetURI();
1357 }
1358 }
1359 if (!uri) {
1360 uri = doc->GetDocumentURI();
1361 }
1362 SetCurrentURI(uri, channel,
1363 /* aFireOnLocationChange */ true,
1364 /* aIsInitialAboutBlank */ false,
1365 /* aLocationFlags */ 0);
1366 mLoadGroup->RemoveRequest(channel, nullptr, NS_OK);
1367 mIsRestoringDocument = false;
1368 }
1369 RefPtr<PresShell> presShell = GetPresShell();
1370 if (presShell) {
1371 presShell->Thaw(false);
1372 }
1373
1374 if (inner) {
1375 inner->FireDelayedDOMEvents(false);
1376 }
1377 }
1378 } else if (!mFiredUnloadEvent) {
1379 // XXXBFCache check again that the page can enter bfcache.
1380 // XXXBFCache should mTiming->NotifyUnloadEventStart()/End() be called here?
1381
1382 if (mRefreshURIList) {
1383 RefreshURIToQueue();
1384 mBFCachedRefreshURIList = std::move(mRefreshURIList);
1385 } else {
1386 // If Stop was called, the list was moved to mSavedRefreshURIList after
1387 // calling SuspendRefreshURIs, which calls RefreshURIToQueue.
1388 mBFCachedRefreshURIList = std::move(mSavedRefreshURIList);
1389 }
1390
1391 mFiredUnloadEvent = true;
1392 viewer->PageHide(false);
1393
1394 RefPtr<PresShell> presShell = GetPresShell();
1395 if (presShell) {
1396 presShell->Freeze(false);
1397 }
1398 }
1399}
1400
1401nsresult nsDocShell::Dispatch(already_AddRefed<nsIRunnable>&& aRunnable) {
1402 nsCOMPtr<nsIRunnable> runnable(aRunnable);
1403 if (NS_WARN_IF(!GetWindow())NS_warn_if_impl(!GetWindow(), "!GetWindow()", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 1403)
) {
1404 // Window should only be unavailable after destroyed.
1405 MOZ_ASSERT(mIsBeingDestroyed)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mIsBeingDestroyed)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mIsBeingDestroyed))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("mIsBeingDestroyed"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 1405); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "mIsBeingDestroyed" ")"); do { MOZ_CrashSequence
(__null, 1405); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
1406 return NS_ERROR_FAILURE;
1407 }
1408 return SchedulerGroup::Dispatch(runnable.forget());
1409}
1410
1411NS_IMETHODIMPnsresult
1412nsDocShell::DispatchLocationChangeEvent() {
1413 return Dispatch(NewRunnableMethod("nsDocShell::FireDummyOnLocationChange",
1414 this,
1415 &nsDocShell::FireDummyOnLocationChange));
1416}
1417
1418NS_IMETHODIMPnsresult
1419nsDocShell::StartDelayedAutoplayMediaComponents() {
1420 RefPtr<nsPIDOMWindowOuter> outerWindow = GetWindow();
1421 if (outerWindow) {
1422 outerWindow->ActivateMediaComponents();
1423 }
1424 return NS_OK;
1425}
1426
1427bool nsDocShell::MaybeInitTiming() {
1428 if (mTiming && !mBlankTiming) {
1429 return false;
1430 }
1431
1432 bool canBeReset = false;
1433
1434 if (mScriptGlobal && mBlankTiming) {
1435 nsPIDOMWindowInner* innerWin = mScriptGlobal->GetCurrentInnerWindow();
1436 if (innerWin && innerWin->GetPerformance()) {
1437 mTiming = innerWin->GetPerformance()->GetDOMTiming();
1438 mBlankTiming = false;
1439 }
1440 }
1441
1442 if (!mTiming) {
1443 mTiming = new nsDOMNavigationTiming(this);
1444 canBeReset = true;
1445 }
1446
1447 mTiming->NotifyNavigationStart(
1448 mBrowsingContext->IsActive()
1449 ? nsDOMNavigationTiming::DocShellState::eActive
1450 : nsDOMNavigationTiming::DocShellState::eInactive);
1451
1452 return canBeReset;
1453}
1454
1455void nsDocShell::MaybeResetInitTiming(bool aReset) {
1456 if (aReset) {
1457 mTiming = nullptr;
1458 }
1459}
1460
1461nsDOMNavigationTiming* nsDocShell::GetNavigationTiming() const {
1462 return mTiming;
1463}
1464
1465nsPresContext* nsDocShell::GetEldestPresContext() {
1466 nsIDocumentViewer* viewer = mDocumentViewer;
1467 while (viewer) {
1468 nsIDocumentViewer* prevViewer = viewer->GetPreviousViewer();
1469 if (!prevViewer) {
1470 return viewer->GetPresContext();
1471 }
1472 viewer = prevViewer;
1473 }
1474
1475 return nullptr;
1476}
1477
1478nsPresContext* nsDocShell::GetPresContext() {
1479 if (!mDocumentViewer) {
1480 return nullptr;
1481 }
1482
1483 return mDocumentViewer->GetPresContext();
1484}
1485
1486PresShell* nsDocShell::GetPresShell() {
1487 nsPresContext* presContext = GetPresContext();
1488 return presContext ? presContext->GetPresShell() : nullptr;
1489}
1490
1491PresShell* nsDocShell::GetEldestPresShell() {
1492 nsPresContext* presContext = GetEldestPresContext();
1493
1494 if (presContext) {
1495 return presContext->GetPresShell();
1496 }
1497
1498 return nullptr;
1499}
1500
1501NS_IMETHODIMPnsresult
1502nsDocShell::GetDocViewer(nsIDocumentViewer** aDocumentViewer) {
1503 NS_ENSURE_ARG_POINTER(aDocumentViewer)do { if ((__builtin_expect(!!(!(aDocumentViewer)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aDocumentViewer" ") failed"
, nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 1503); return NS_ERROR_INVALID_POINTER; } } while (false)
;
1504
1505 *aDocumentViewer = mDocumentViewer;
1506 NS_IF_ADDREF(*aDocumentViewer)ns_if_addref(*aDocumentViewer);
1507 return NS_OK;
1508}
1509
1510NS_IMETHODIMPnsresult
1511nsDocShell::GetOuterWindowID(uint64_t* aWindowID) {
1512 *aWindowID = mContentWindowID;
1513 return NS_OK;
1514}
1515
1516NS_IMETHODIMPnsresult
1517nsDocShell::SetChromeEventHandler(EventTarget* aChromeEventHandler) {
1518 mChromeEventHandler = aChromeEventHandler;
1519
1520 if (mScriptGlobal) {
1521 mScriptGlobal->SetChromeEventHandler(mChromeEventHandler);
1522 }
1523
1524 return NS_OK;
1525}
1526
1527NS_IMETHODIMPnsresult
1528nsDocShell::GetChromeEventHandler(EventTarget** aChromeEventHandler) {
1529 NS_ENSURE_ARG_POINTER(aChromeEventHandler)do { if ((__builtin_expect(!!(!(aChromeEventHandler)), 0))) {
NS_DebugBreak(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aChromeEventHandler"
") failed", nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 1529); return NS_ERROR_INVALID_POINTER; } } while (false)
;
1530 RefPtr<EventTarget> handler = mChromeEventHandler;
1531 handler.forget(aChromeEventHandler);
1532 return NS_OK;
1533}
1534
1535NS_IMETHODIMPnsresult
1536nsDocShell::SetCurrentURIForSessionStore(nsIURI* aURI) {
1537 // Note that securityUI will set STATE_IS_INSECURE, even if
1538 // the scheme of |aURI| is "https".
1539 SetCurrentURI(aURI, nullptr,
1540 /* aFireOnLocationChange */
1541 true,
1542 /* aIsInitialAboutBlank */
1543 false,
1544 /* aLocationFlags */
1545 nsIWebProgressListener::LOCATION_CHANGE_SESSION_STORE);
1546 return NS_OK;
1547}
1548
1549bool nsDocShell::SetCurrentURI(nsIURI* aURI, nsIRequest* aRequest,
1550 bool aFireOnLocationChange,
1551 bool aIsInitialAboutBlank,
1552 uint32_t aLocationFlags) {
1553 MOZ_ASSERT(!mIsBeingDestroyed)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mIsBeingDestroyed)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mIsBeingDestroyed))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("!mIsBeingDestroyed"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 1553); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!mIsBeingDestroyed" ")"); do { MOZ_CrashSequence
(__null, 1553); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
1554
1555 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)
1556 ("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)
1557 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)
;
1558
1559 // We don't want to send a location change when we're displaying an error
1560 // page, and we don't want to change our idea of "current URI" either
1561 if (mLoadType == LOAD_ERROR_PAGE) {
1562 return false;
1563 }
1564
1565 bool uriIsEqual = false;
1566 if (!mCurrentURI || !aURI ||
1567 NS_FAILED(mCurrentURI->Equals(aURI, &uriIsEqual))((bool)(__builtin_expect(!!(NS_FAILED_impl(mCurrentURI->Equals
(aURI, &uriIsEqual))), 0)))
|| !uriIsEqual) {
1568 mTitleValidForCurrentURI = false;
1569 }
1570
1571 SetCurrentURIInternal(aURI);
1572
1573#ifdef DEBUG1
1574 mLastOpenedURI = aURI;
1575#endif
1576
1577 if (!NS_IsAboutBlank(mCurrentURI)) {
1578 mHasLoadedNonBlankURI = true;
1579 }
1580
1581 // Don't fire onLocationChange when creating a subframe's initial about:blank
1582 // document, as this can happen when it's not safe for us to run script.
1583 if (aIsInitialAboutBlank && !mHasLoadedNonBlankURI &&
1584 !mBrowsingContext->IsTop()) {
1585 MOZ_ASSERT(!aRequest && aLocationFlags == 0)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aRequest && aLocationFlags == 0)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(!aRequest && aLocationFlags == 0))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("!aRequest && aLocationFlags == 0"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 1585); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!aRequest && aLocationFlags == 0" ")"
); do { MOZ_CrashSequence(__null, 1585); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1586 return false;
1587 }
1588
1589 MOZ_ASSERT(nsContentUtils::IsSafeToRunScript())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(nsContentUtils::IsSafeToRunScript())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(nsContentUtils::IsSafeToRunScript
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("nsContentUtils::IsSafeToRunScript()", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 1589); AnnotateMozCrashReason("MOZ_ASSERT" "(" "nsContentUtils::IsSafeToRunScript()"
")"); do { MOZ_CrashSequence(__null, 1589); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1590
1591 if (aFireOnLocationChange) {
1592 FireOnLocationChange(this, aRequest, aURI, aLocationFlags);
1593 }
1594 return !aFireOnLocationChange;
1595}
1596
1597void nsDocShell::SetCurrentURIInternal(nsIURI* aURI) {
1598 mCurrentURI = aURI;
1599 if (mBrowsingContext) {
1600 mBrowsingContext->ClearCachedValuesOfLocations();
1601 }
1602}
1603
1604NS_IMETHODIMPnsresult
1605nsDocShell::GetCharset(nsACString& aCharset) {
1606 aCharset.Truncate();
1607
1608 PresShell* presShell = GetPresShell();
1609 NS_ENSURE_TRUE(presShell, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(presShell)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "presShell" ") failed", nullptr
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 1609); return
NS_ERROR_FAILURE; } } while (false)
;
1610 Document* doc = presShell->GetDocument();
1611 NS_ENSURE_TRUE(doc, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(doc)), 0))) { NS_DebugBreak(NS_DEBUG_WARNING
, "NS_ENSURE_TRUE(" "doc" ") failed", nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 1611); return NS_ERROR_FAILURE; } } while (false)
;
1612 doc->GetDocumentCharacterSet()->Name(aCharset);
1613 return NS_OK;
1614}
1615
1616NS_IMETHODIMPnsresult
1617nsDocShell::ForceEncodingDetection() {
1618 nsCOMPtr<nsIDocumentViewer> viewer;
1619 GetDocViewer(getter_AddRefs(viewer));
1620 if (!viewer) {
1621 return NS_OK;
1622 }
1623
1624 Document* doc = viewer->GetDocument();
1625 if (!doc || doc->WillIgnoreCharsetOverride()) {
1626 return NS_OK;
1627 }
1628
1629 mForcedAutodetection = true;
1630
1631 nsIURI* uri = doc->GetOriginalURI();
1632 bool isFileURL = uri && uri->SchemeIs("file");
1633
1634 int32_t charsetSource = doc->GetDocumentCharacterSetSource();
1635 auto encoding = doc->GetDocumentCharacterSet();
1636 // AsHTMLDocument is valid, because we called
1637 // WillIgnoreCharsetOverride() above.
1638 if (doc->AsHTMLDocument()->IsPlainText()) {
1639 switch (charsetSource) {
1640 case kCharsetFromInitialAutoDetectionASCII:
1641 // Deliberately no final version
1642 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)
;
1643 break;
1644 case kCharsetFromInitialAutoDetectionWouldNotHaveBeenUTF8Generic:
1645 case kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8Generic:
1646 case kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8GenericInitialWasASCII:
1647 case kCharsetFromInitialAutoDetectionWouldNotHaveBeenUTF8Content:
1648 case kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8Content:
1649 case kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8ContentInitialWasASCII:
1650 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)
;
1651 break;
1652 case kCharsetFromInitialAutoDetectionWouldNotHaveBeenUTF8DependedOnTLD:
1653 case kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8DependedOnTLD:
1654 case kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8DependedOnTLDInitialWasASCII:
1655 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)
;
1656 break;
1657 case kCharsetFromInitialAutoDetectionWouldHaveBeenUTF8:
1658 case kCharsetFromFinalAutoDetectionWouldHaveBeenUTF8InitialWasASCII:
1659 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)
;
1660 break;
1661 case kCharsetFromChannel:
1662 if (encoding == UTF_8_ENCODING) {
1663 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)
;
1664 } else {
1665 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)
;
1666 }
1667 break;
1668 default:
1669 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)
;
1670 break;
1671 }
1672 } else {
1673 switch (charsetSource) {
1674 case kCharsetFromInitialAutoDetectionASCII:
1675 // Deliberately no final version
1676 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)
;
1677 break;
1678 case kCharsetFromInitialAutoDetectionWouldNotHaveBeenUTF8Generic:
1679 case kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8Generic:
1680 case kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8GenericInitialWasASCII:
1681 case kCharsetFromInitialAutoDetectionWouldNotHaveBeenUTF8Content:
1682 case kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8Content:
1683 case kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8ContentInitialWasASCII:
1684 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)
;
1685 break;
1686 case kCharsetFromInitialAutoDetectionWouldNotHaveBeenUTF8DependedOnTLD:
1687 case kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8DependedOnTLD:
1688 case kCharsetFromFinalAutoDetectionWouldNotHaveBeenUTF8DependedOnTLDInitialWasASCII:
1689 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)
;
1690 break;
1691 case kCharsetFromInitialAutoDetectionWouldHaveBeenUTF8:
1692 case kCharsetFromFinalAutoDetectionWouldHaveBeenUTF8InitialWasASCII:
1693 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)
;
1694 break;
1695 case kCharsetFromChannel:
1696 if (encoding == UTF_8_ENCODING) {
1697 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)
;
1698 } else {
1699 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)
;
1700 }
1701 break;
1702 case kCharsetFromXmlDeclaration:
1703 case kCharsetFromMetaTag:
1704 if (isFileURL) {
1705 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)
;
1706 } else if (encoding == UTF_8_ENCODING) {
1707 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)
;
1708 } else {
1709 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)
;
1710 }
1711 break;
1712 default:
1713 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)
;
1714 break;
1715 }
1716 }
1717 return NS_OK;
1718}
1719
1720void nsDocShell::SetParentCharset(const Encoding*& aCharset,
1721 int32_t aCharsetSource,
1722 nsIPrincipal* aPrincipal) {
1723 mParentCharset = aCharset;
1724 mParentCharsetSource = aCharsetSource;
1725 mParentCharsetPrincipal = aPrincipal;
1726}
1727
1728void nsDocShell::GetParentCharset(const Encoding*& aCharset,
1729 int32_t* aCharsetSource,
1730 nsIPrincipal** aPrincipal) {
1731 aCharset = mParentCharset;
1732 *aCharsetSource = mParentCharsetSource;
1733 NS_IF_ADDREF(*aPrincipal = mParentCharsetPrincipal)ns_if_addref(*aPrincipal = mParentCharsetPrincipal);
1734}
1735
1736NS_IMETHODIMPnsresult
1737nsDocShell::GetHasTrackingContentBlocked(Promise** aPromise) {
1738 MOZ_ASSERT(aPromise)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aPromise)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aPromise))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aPromise", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 1738); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPromise" ")"
); do { MOZ_CrashSequence(__null, 1738); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1739
1740 ErrorResult rv;
1741 RefPtr<Document> doc(GetDocument());
1742 RefPtr<Promise> retPromise = Promise::Create(doc->GetOwnerGlobal(), rv);
1743 if (NS_WARN_IF(rv.Failed())NS_warn_if_impl(rv.Failed(), "rv.Failed()", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 1743)
) {
1744 return rv.StealNSResult();
1745 }
1746
1747 // Retrieve the document's content blocking events from the parent process.
1748 RefPtr<Document::GetContentBlockingEventsPromise> promise =
1749 doc->GetContentBlockingEvents();
1750 if (promise) {
1751 promise->Then(
1752 GetCurrentSerialEventTarget(), __func__,
1753 [retPromise](const Document::GetContentBlockingEventsPromise::
1754 ResolveOrRejectValue& aValue) {
1755 if (aValue.IsResolve()) {
1756 bool has = aValue.ResolveValue() &
1757 nsIWebProgressListener::STATE_BLOCKED_TRACKING_CONTENT;
1758 retPromise->MaybeResolve(has);
1759 } else {
1760 retPromise->MaybeResolve(false);
1761 }
1762 });
1763 } else {
1764 retPromise->MaybeResolve(false);
1765 }
1766
1767 retPromise.forget(aPromise);
1768 return NS_OK;
1769}
1770
1771NS_IMETHODIMPnsresult
1772nsDocShell::GetCssErrorReportingEnabled(bool* aEnabled) {
1773 MOZ_ASSERT(aEnabled)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aEnabled)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aEnabled))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aEnabled", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 1773); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aEnabled" ")"
); do { MOZ_CrashSequence(__null, 1773); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1774 *aEnabled = mCSSErrorReportingEnabled;
1775 return NS_OK;
1776}
1777
1778NS_IMETHODIMPnsresult
1779nsDocShell::SetCssErrorReportingEnabled(bool aEnabled) {
1780 mCSSErrorReportingEnabled = aEnabled;
1781 return NS_OK;
1782}
1783
1784NS_IMETHODIMPnsresult
1785nsDocShell::GetUsePrivateBrowsing(bool* aUsePrivateBrowsing) {
1786 NS_ENSURE_ARG_POINTER(aUsePrivateBrowsing)do { if ((__builtin_expect(!!(!(aUsePrivateBrowsing)), 0))) {
NS_DebugBreak(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aUsePrivateBrowsing"
") failed", nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 1786); return NS_ERROR_INVALID_POINTER; } } while (false)
;
1787 return mBrowsingContext->GetUsePrivateBrowsing(aUsePrivateBrowsing);
1788}
1789
1790void nsDocShell::NotifyPrivateBrowsingChanged() {
1791 MOZ_ASSERT(!mIsBeingDestroyed)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mIsBeingDestroyed)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mIsBeingDestroyed))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("!mIsBeingDestroyed"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 1791); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!mIsBeingDestroyed" ")"); do { MOZ_CrashSequence
(__null, 1791); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
1792
1793 nsTObserverArray<nsWeakPtr>::ForwardIterator iter(mPrivacyObservers);
1794 while (iter.HasMore()) {
1795 nsWeakPtr ref = iter.GetNext();
1796 nsCOMPtr<nsIPrivacyTransitionObserver> obs = do_QueryReferent(ref);
1797 if (!obs) {
1798 iter.Remove();
1799 } else {
1800 obs->PrivateModeChanged(UsePrivateBrowsing());
1801 }
1802 }
1803}
1804
1805NS_IMETHODIMPnsresult
1806nsDocShell::SetUsePrivateBrowsing(bool aUsePrivateBrowsing) {
1807 return mBrowsingContext->SetUsePrivateBrowsing(aUsePrivateBrowsing);
1808}
1809
1810NS_IMETHODIMPnsresult
1811nsDocShell::SetPrivateBrowsing(bool aUsePrivateBrowsing) {
1812 return mBrowsingContext->SetPrivateBrowsing(aUsePrivateBrowsing);
1813}
1814
1815NS_IMETHODIMPnsresult
1816nsDocShell::GetHasLoadedNonBlankURI(bool* aResult) {
1817 NS_ENSURE_ARG_POINTER(aResult)do { if ((__builtin_expect(!!(!(aResult)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aResult" ") failed", nullptr
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 1817); return
NS_ERROR_INVALID_POINTER; } } while (false)
;
1818
1819 *aResult = mHasLoadedNonBlankURI;
1820 return NS_OK;
1821}
1822
1823NS_IMETHODIMPnsresult
1824nsDocShell::GetUseRemoteTabs(bool* aUseRemoteTabs) {
1825 NS_ENSURE_ARG_POINTER(aUseRemoteTabs)do { if ((__builtin_expect(!!(!(aUseRemoteTabs)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aUseRemoteTabs" ") failed"
, nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 1825); return NS_ERROR_INVALID_POINTER; } } while (false)
;
1826 return mBrowsingContext->GetUseRemoteTabs(aUseRemoteTabs);
1827}
1828
1829NS_IMETHODIMPnsresult
1830nsDocShell::SetRemoteTabs(bool aUseRemoteTabs) {
1831 return mBrowsingContext->SetRemoteTabs(aUseRemoteTabs);
1832}
1833
1834NS_IMETHODIMPnsresult
1835nsDocShell::GetUseRemoteSubframes(bool* aUseRemoteSubframes) {
1836 NS_ENSURE_ARG_POINTER(aUseRemoteSubframes)do { if ((__builtin_expect(!!(!(aUseRemoteSubframes)), 0))) {
NS_DebugBreak(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aUseRemoteSubframes"
") failed", nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 1836); return NS_ERROR_INVALID_POINTER; } } while (false)
;
1837 return mBrowsingContext->GetUseRemoteSubframes(aUseRemoteSubframes);
1838}
1839
1840NS_IMETHODIMPnsresult
1841nsDocShell::SetRemoteSubframes(bool aUseRemoteSubframes) {
1842 return mBrowsingContext->SetRemoteSubframes(aUseRemoteSubframes);
1843}
1844
1845NS_IMETHODIMPnsresult
1846nsDocShell::AddWeakPrivacyTransitionObserver(
1847 nsIPrivacyTransitionObserver* aObserver) {
1848 nsWeakPtr weakObs = do_GetWeakReference(aObserver);
1849 if (!weakObs) {
1850 return NS_ERROR_NOT_AVAILABLE;
1851 }
1852 mPrivacyObservers.AppendElement(weakObs);
1853 return NS_OK;
1854}
1855
1856NS_IMETHODIMPnsresult
1857nsDocShell::AddWeakReflowObserver(nsIReflowObserver* aObserver) {
1858 nsWeakPtr weakObs = do_GetWeakReference(aObserver);
1859 if (!weakObs) {
1860 return NS_ERROR_FAILURE;
1861 }
1862 mReflowObservers.AppendElement(weakObs);
1863 return NS_OK;
1864}
1865
1866NS_IMETHODIMPnsresult
1867nsDocShell::RemoveWeakReflowObserver(nsIReflowObserver* aObserver) {
1868 nsWeakPtr obs = do_GetWeakReference(aObserver);
1869 return mReflowObservers.RemoveElement(obs) ? NS_OK : NS_ERROR_FAILURE;
1870}
1871
1872NS_IMETHODIMPnsresult
1873nsDocShell::NotifyReflowObservers(bool aInterruptible,
1874 DOMHighResTimeStamp aStart,
1875 DOMHighResTimeStamp aEnd) {
1876 nsTObserverArray<nsWeakPtr>::ForwardIterator iter(mReflowObservers);
1877 while (iter.HasMore()) {
1878 nsWeakPtr ref = iter.GetNext();
1879 nsCOMPtr<nsIReflowObserver> obs = do_QueryReferent(ref);
1880 if (!obs) {
1881 iter.Remove();
1882 } else if (aInterruptible) {
1883 obs->ReflowInterruptible(aStart, aEnd);
1884 } else {
1885 obs->Reflow(aStart, aEnd);
1886 }
1887 }
1888 return NS_OK;
1889}
1890
1891NS_IMETHODIMPnsresult
1892nsDocShell::GetAllowMetaRedirects(bool* aReturn) {
1893 NS_ENSURE_ARG_POINTER(aReturn)do { if ((__builtin_expect(!!(!(aReturn)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aReturn" ") failed", nullptr
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 1893); return
NS_ERROR_INVALID_POINTER; } } while (false)
;
1894
1895 *aReturn = mAllowMetaRedirects;
1896 return NS_OK;
1897}
1898
1899NS_IMETHODIMPnsresult
1900nsDocShell::SetAllowMetaRedirects(bool aValue) {
1901 mAllowMetaRedirects = aValue;
1902 return NS_OK;
1903}
1904
1905NS_IMETHODIMPnsresult
1906nsDocShell::GetAllowSubframes(bool* aAllowSubframes) {
1907 NS_ENSURE_ARG_POINTER(aAllowSubframes)do { if ((__builtin_expect(!!(!(aAllowSubframes)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aAllowSubframes" ") failed"
, nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 1907); return NS_ERROR_INVALID_POINTER; } } while (false)
;
1908
1909 *aAllowSubframes = mAllowSubframes;
1910 return NS_OK;
1911}
1912
1913NS_IMETHODIMPnsresult
1914nsDocShell::SetAllowSubframes(bool aAllowSubframes) {
1915 mAllowSubframes = aAllowSubframes;
1916 return NS_OK;
1917}
1918
1919NS_IMETHODIMPnsresult
1920nsDocShell::GetAllowImages(bool* aAllowImages) {
1921 NS_ENSURE_ARG_POINTER(aAllowImages)do { if ((__builtin_expect(!!(!(aAllowImages)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aAllowImages" ") failed"
, nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 1921); return NS_ERROR_INVALID_POINTER; } } while (false)
;
1922
1923 *aAllowImages = mAllowImages;
1924 return NS_OK;
1925}
1926
1927NS_IMETHODIMPnsresult
1928nsDocShell::SetAllowImages(bool aAllowImages) {
1929 mAllowImages = aAllowImages;
1930 return NS_OK;
1931}
1932
1933NS_IMETHODIMPnsresult
1934nsDocShell::GetAllowMedia(bool* aAllowMedia) {
1935 *aAllowMedia = mAllowMedia;
1936 return NS_OK;
1937}
1938
1939NS_IMETHODIMPnsresult
1940nsDocShell::SetAllowMedia(bool aAllowMedia) {
1941 mAllowMedia = aAllowMedia;
1942
1943 // Mute or unmute audio contexts attached to the inner window.
1944 if (mScriptGlobal) {
1945 if (nsPIDOMWindowInner* innerWin = mScriptGlobal->GetCurrentInnerWindow()) {
1946 if (aAllowMedia) {
1947 innerWin->UnmuteAudioContexts();
1948 } else {
1949 innerWin->MuteAudioContexts();
1950 }
1951 }
1952 }
1953
1954 return NS_OK;
1955}
1956
1957NS_IMETHODIMPnsresult
1958nsDocShell::GetAllowDNSPrefetch(bool* aAllowDNSPrefetch) {
1959 *aAllowDNSPrefetch = mAllowDNSPrefetch;
1960 return NS_OK;
1961}
1962
1963NS_IMETHODIMPnsresult
1964nsDocShell::SetAllowDNSPrefetch(bool aAllowDNSPrefetch) {
1965 mAllowDNSPrefetch = aAllowDNSPrefetch;
1966 return NS_OK;
1967}
1968
1969NS_IMETHODIMPnsresult
1970nsDocShell::GetAllowWindowControl(bool* aAllowWindowControl) {
1971 *aAllowWindowControl = mAllowWindowControl;
1972 return NS_OK;
1973}
1974
1975NS_IMETHODIMPnsresult
1976nsDocShell::SetAllowWindowControl(bool aAllowWindowControl) {
1977 mAllowWindowControl = aAllowWindowControl;
1978 return NS_OK;
1979}
1980
1981NS_IMETHODIMPnsresult
1982nsDocShell::GetAllowContentRetargeting(bool* aAllowContentRetargeting) {
1983 *aAllowContentRetargeting = mBrowsingContext->GetAllowContentRetargeting();
1984 return NS_OK;
1985}
1986
1987NS_IMETHODIMPnsresult
1988nsDocShell::SetAllowContentRetargeting(bool aAllowContentRetargeting) {
1989 BrowsingContext::Transaction txn;
1990 txn.SetAllowContentRetargeting(aAllowContentRetargeting);
1991 txn.SetAllowContentRetargetingOnChildren(aAllowContentRetargeting);
1992 return txn.Commit(mBrowsingContext);
1993}
1994
1995NS_IMETHODIMPnsresult
1996nsDocShell::GetAllowContentRetargetingOnChildren(
1997 bool* aAllowContentRetargetingOnChildren) {
1998 *aAllowContentRetargetingOnChildren =
1999 mBrowsingContext->GetAllowContentRetargetingOnChildren();
2000 return NS_OK;
2001}
2002
2003NS_IMETHODIMPnsresult
2004nsDocShell::SetAllowContentRetargetingOnChildren(
2005 bool aAllowContentRetargetingOnChildren) {
2006 return mBrowsingContext->SetAllowContentRetargetingOnChildren(
2007 aAllowContentRetargetingOnChildren);
2008}
2009
2010NS_IMETHODIMPnsresult
2011nsDocShell::GetMayEnableCharacterEncodingMenu(
2012 bool* aMayEnableCharacterEncodingMenu) {
2013 *aMayEnableCharacterEncodingMenu = false;
2014 if (!mDocumentViewer) {
2015 return NS_OK;
2016 }
2017 Document* doc = mDocumentViewer->GetDocument();
2018 if (!doc) {
2019 return NS_OK;
2020 }
2021 if (doc->WillIgnoreCharsetOverride()) {
2022 return NS_OK;
2023 }
2024
2025 *aMayEnableCharacterEncodingMenu = true;
2026 return NS_OK;
2027}
2028
2029NS_IMETHODIMPnsresult
2030nsDocShell::GetAllDocShellsInSubtree(int32_t aItemType,
2031 DocShellEnumeratorDirection aDirection,
2032 nsTArray<RefPtr<nsIDocShell>>& aResult) {
2033 aResult.Clear();
2034
2035 nsDocShellEnumerator docShellEnum(
2036 (aDirection == ENUMERATE_FORWARDS)
2037 ? nsDocShellEnumerator::EnumerationDirection::Forwards
2038 : nsDocShellEnumerator::EnumerationDirection::Backwards,
2039 aItemType, *this);
2040
2041 nsresult rv = docShellEnum.BuildDocShellArray(aResult);
2042 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2043 return rv;
2044 }
2045
2046 return NS_OK;
2047}
2048
2049NS_IMETHODIMPnsresult
2050nsDocShell::GetAppType(AppType* aAppType) {
2051 *aAppType = mAppType;
2052 return NS_OK;
2053}
2054
2055NS_IMETHODIMPnsresult
2056nsDocShell::SetAppType(AppType aAppType) {
2057 mAppType = aAppType;
2058 return NS_OK;
2059}
2060
2061NS_IMETHODIMPnsresult
2062nsDocShell::GetAllowAuth(bool* aAllowAuth) {
2063 *aAllowAuth = mAllowAuth;
2064 return NS_OK;
2065}
2066
2067NS_IMETHODIMPnsresult
2068nsDocShell::SetAllowAuth(bool aAllowAuth) {
2069 mAllowAuth = aAllowAuth;
2070 return NS_OK;
2071}
2072
2073NS_IMETHODIMPnsresult
2074nsDocShell::GetZoom(float* aZoom) {
2075 NS_ENSURE_ARG_POINTER(aZoom)do { if ((__builtin_expect(!!(!(aZoom)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aZoom" ") failed", nullptr
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 2075); return
NS_ERROR_INVALID_POINTER; } } while (false)
;
2076 *aZoom = 1.0f;
2077 return NS_OK;
2078}
2079
2080NS_IMETHODIMPnsresult
2081nsDocShell::SetZoom(float aZoom) { return NS_ERROR_NOT_IMPLEMENTED; }
2082
2083NS_IMETHODIMPnsresult
2084nsDocShell::GetBusyFlags(BusyFlags* aBusyFlags) {
2085 NS_ENSURE_ARG_POINTER(aBusyFlags)do { if ((__builtin_expect(!!(!(aBusyFlags)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aBusyFlags" ") failed",
nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp",
2085); return NS_ERROR_INVALID_POINTER; } } while (false)
;
2086
2087 *aBusyFlags = mBusyFlags;
2088 return NS_OK;
2089}
2090
2091NS_IMETHODIMPnsresult
2092nsDocShell::GetLoadURIDelegate(nsILoadURIDelegate** aLoadURIDelegate) {
2093 nsCOMPtr<nsILoadURIDelegate> delegate = GetLoadURIDelegate();
2094 delegate.forget(aLoadURIDelegate);
2095 return NS_OK;
2096}
2097
2098already_AddRefed<nsILoadURIDelegate> nsDocShell::GetLoadURIDelegate() {
2099 if (nsCOMPtr<nsILoadURIDelegate> result =
2100 do_QueryActor("LoadURIDelegate", GetDocument())) {
2101 return result.forget();
2102 }
2103
2104 return nullptr;
2105}
2106
2107NS_IMETHODIMPnsresult
2108nsDocShell::GetUseErrorPages(bool* aUseErrorPages) {
2109 *aUseErrorPages = mBrowsingContext->GetUseErrorPages();
2110 return NS_OK;
2111}
2112
2113NS_IMETHODIMPnsresult
2114nsDocShell::SetUseErrorPages(bool aUseErrorPages) {
2115 return mBrowsingContext->SetUseErrorPages(aUseErrorPages);
2116}
2117
2118NS_IMETHODIMPnsresult
2119nsDocShell::GetPreviousEntryIndex(int32_t* aPreviousEntryIndex) {
2120 *aPreviousEntryIndex = mPreviousEntryIndex;
2121 return NS_OK;
2122}
2123
2124NS_IMETHODIMPnsresult
2125nsDocShell::GetLoadedEntryIndex(int32_t* aLoadedEntryIndex) {
2126 *aLoadedEntryIndex = mLoadedEntryIndex;
2127 return NS_OK;
2128}
2129
2130NS_IMETHODIMPnsresult
2131nsDocShell::HistoryPurged(int32_t aNumEntries) {
2132 // These indices are used for fastback cache eviction, to determine
2133 // which session history entries are candidates for content viewer
2134 // eviction. We need to adjust by the number of entries that we
2135 // just purged from history, so that we look at the right session history
2136 // entries during eviction.
2137 mPreviousEntryIndex = std::max(-1, mPreviousEntryIndex - aNumEntries);
2138 mLoadedEntryIndex = std::max(0, mLoadedEntryIndex - aNumEntries);
2139
2140 for (auto* child : mChildList.ForwardRange()) {
2141 nsCOMPtr<nsIDocShell> shell = do_QueryObject(child);
2142 if (shell) {
2143 shell->HistoryPurged(aNumEntries);
2144 }
2145 }
2146
2147 return NS_OK;
2148}
2149
2150nsresult nsDocShell::HistoryEntryRemoved(int32_t aIndex) {
2151 // These indices are used for fastback cache eviction, to determine
2152 // which session history entries are candidates for content viewer
2153 // eviction. We need to adjust by the number of entries that we
2154 // just purged from history, so that we look at the right session history
2155 // entries during eviction.
2156 if (aIndex == mPreviousEntryIndex) {
2157 mPreviousEntryIndex = -1;
2158 } else if (aIndex < mPreviousEntryIndex) {
2159 --mPreviousEntryIndex;
2160 }
2161 if (mLoadedEntryIndex == aIndex) {
2162 mLoadedEntryIndex = 0;
2163 } else if (aIndex < mLoadedEntryIndex) {
2164 --mLoadedEntryIndex;
2165 }
2166
2167 for (auto* child : mChildList.ForwardRange()) {
2168 nsCOMPtr<nsIDocShell> shell = do_QueryObject(child);
2169 if (shell) {
2170 static_cast<nsDocShell*>(shell.get())->HistoryEntryRemoved(aIndex);
2171 }
2172 }
2173
2174 return NS_OK;
2175}
2176
2177nsresult nsDocShell::Now(DOMHighResTimeStamp* aWhen) {
2178 *aWhen = (TimeStamp::Now() - TimeStamp::ProcessCreation()).ToMilliseconds();
2179 return NS_OK;
2180}
2181
2182NS_IMETHODIMPnsresult
2183nsDocShell::SetWindowDraggingAllowed(bool aValue) {
2184 RefPtr<nsDocShell> parent;
2185 if (!aValue && mItemType == typeChrome &&
2186 !(parent = GetInProcessParentDocshell())) {
2187 // Window dragging is always allowed for top level
2188 // chrome docshells.
2189 return NS_ERROR_FAILURE;
2190 }
2191 mWindowDraggingAllowed = aValue;
2192 return NS_OK;
2193}
2194
2195NS_IMETHODIMPnsresult
2196nsDocShell::GetWindowDraggingAllowed(bool* aValue) {
2197 // window dragging regions in CSS (-moz-window-drag:drag)
2198 // can be slow. Default behavior is to only allow it for
2199 // chrome top level windows.
2200 RefPtr<nsDocShell> parent;
2201 if (mItemType == typeChrome && !(parent = GetInProcessParentDocshell())) {
2202 // Top level chrome window
2203 *aValue = true;
2204 } else {
2205 *aValue = mWindowDraggingAllowed;
2206 }
2207 return NS_OK;
2208}
2209
2210NS_IMETHODIMPnsresult
2211nsDocShell::GetCurrentDocumentChannel(nsIChannel** aResult) {
2212 NS_IF_ADDREF(*aResult = GetCurrentDocChannel())ns_if_addref(*aResult = GetCurrentDocChannel());
2213 return NS_OK;
2214}
2215
2216nsIChannel* nsDocShell::GetCurrentDocChannel() {
2217 if (mDocumentViewer) {
2218 Document* doc = mDocumentViewer->GetDocument();
2219 if (doc) {
2220 return doc->GetChannel();
2221 }
2222 }
2223 return nullptr;
2224}
2225
2226NS_IMETHODIMPnsresult
2227nsDocShell::AddWeakScrollObserver(nsIScrollObserver* aObserver) {
2228 nsWeakPtr weakObs = do_GetWeakReference(aObserver);
2229 if (!weakObs) {
2230 return NS_ERROR_FAILURE;
2231 }
2232 mScrollObservers.AppendElement(weakObs);
2233 return NS_OK;
2234}
2235
2236NS_IMETHODIMPnsresult
2237nsDocShell::RemoveWeakScrollObserver(nsIScrollObserver* aObserver) {
2238 nsWeakPtr obs = do_GetWeakReference(aObserver);
2239 return mScrollObservers.RemoveElement(obs) ? NS_OK : NS_ERROR_FAILURE;
2240}
2241
2242void nsDocShell::NotifyAsyncPanZoomStarted() {
2243 nsTObserverArray<nsWeakPtr>::ForwardIterator iter(mScrollObservers);
2244 while (iter.HasMore()) {
2245 nsWeakPtr ref = iter.GetNext();
2246 nsCOMPtr<nsIScrollObserver> obs = do_QueryReferent(ref);
2247 if (obs) {
2248 obs->AsyncPanZoomStarted();
2249 } else {
2250 iter.Remove();
2251 }
2252 }
2253}
2254
2255void nsDocShell::NotifyAsyncPanZoomStopped() {
2256 nsTObserverArray<nsWeakPtr>::ForwardIterator iter(mScrollObservers);
2257 while (iter.HasMore()) {
2258 nsWeakPtr ref = iter.GetNext();
2259 nsCOMPtr<nsIScrollObserver> obs = do_QueryReferent(ref);
2260 if (obs) {
2261 obs->AsyncPanZoomStopped();
2262 } else {
2263 iter.Remove();
2264 }
2265 }
2266}
2267
2268NS_IMETHODIMPnsresult
2269nsDocShell::NotifyScrollObservers() {
2270 nsTObserverArray<nsWeakPtr>::ForwardIterator iter(mScrollObservers);
2271 while (iter.HasMore()) {
2272 nsWeakPtr ref = iter.GetNext();
2273 nsCOMPtr<nsIScrollObserver> obs = do_QueryReferent(ref);
2274 if (obs) {
2275 obs->ScrollPositionChanged();
2276 } else {
2277 iter.Remove();
2278 }
2279 }
2280 return NS_OK;
2281}
2282
2283//*****************************************************************************
2284// nsDocShell::nsIDocShellTreeItem
2285//*****************************************************************************
2286
2287NS_IMETHODIMPnsresult
2288nsDocShell::GetName(nsAString& aName) {
2289 aName = mBrowsingContext->Name();
2290 return NS_OK;
2291}
2292
2293NS_IMETHODIMPnsresult
2294nsDocShell::SetName(const nsAString& aName) {
2295 return mBrowsingContext->SetName(aName);
2296}
2297
2298NS_IMETHODIMPnsresult
2299nsDocShell::NameEquals(const nsAString& aName, bool* aResult) {
2300 NS_ENSURE_ARG_POINTER(aResult)do { if ((__builtin_expect(!!(!(aResult)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aResult" ") failed", nullptr
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 2300); return
NS_ERROR_INVALID_POINTER; } } while (false)
;
2301 *aResult = mBrowsingContext->NameEquals(aName);
2302 return NS_OK;
2303}
2304
2305NS_IMETHODIMPnsresult
2306nsDocShell::GetCustomUserAgent(nsAString& aCustomUserAgent) {
2307 mBrowsingContext->GetCustomUserAgent(aCustomUserAgent);
2308 return NS_OK;
2309}
2310
2311NS_IMETHODIMPnsresult
2312nsDocShell::SetCustomUserAgent(const nsAString& aCustomUserAgent) {
2313 if (mWillChangeProcess) {
2314 NS_WARNING("SetCustomUserAgent: Process is changing. Ignoring set")NS_DebugBreak(NS_DEBUG_WARNING, "SetCustomUserAgent: Process is changing. Ignoring set"
, nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 2314)
;
2315 return NS_ERROR_FAILURE;
2316 }
2317
2318 return mBrowsingContext->SetCustomUserAgent(aCustomUserAgent);
2319}
2320
2321NS_IMETHODIMPnsresult
2322nsDocShell::ClearCachedPlatform() {
2323 nsCOMPtr<nsPIDOMWindowInner> win =
2324 mScriptGlobal ? mScriptGlobal->GetCurrentInnerWindow() : nullptr;
2325 if (win) {
2326 Navigator* navigator = win->Navigator();
2327 if (navigator) {
2328 navigator->ClearPlatformCache();
2329 }
2330 }
2331
2332 return NS_OK;
2333}
2334
2335NS_IMETHODIMPnsresult
2336nsDocShell::ClearCachedUserAgent() {
2337 nsCOMPtr<nsPIDOMWindowInner> win =
2338 mScriptGlobal ? mScriptGlobal->GetCurrentInnerWindow() : nullptr;
2339 if (win) {
2340 Navigator* navigator = win->Navigator();
2341 if (navigator) {
2342 navigator->ClearUserAgentCache();
2343 }
2344 }
2345
2346 return NS_OK;
2347}
2348
2349/* virtual */
2350int32_t nsDocShell::ItemType() { return mItemType; }
2351
2352NS_IMETHODIMPnsresult
2353nsDocShell::GetItemType(int32_t* aItemType) {
2354 NS_ENSURE_ARG_POINTER(aItemType)do { if ((__builtin_expect(!!(!(aItemType)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aItemType" ") failed", nullptr
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 2354); return
NS_ERROR_INVALID_POINTER; } } while (false)
;
2355
2356 MOZ_DIAGNOSTIC_ASSERT(do { static_assert( mozilla::detail::AssertionConditionType<
decltype((mBrowsingContext->IsContent() ? typeContent : typeChrome
) == mItemType)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!((mBrowsingContext->IsContent
() ? typeContent : typeChrome) == mItemType))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("(mBrowsingContext->IsContent() ? typeContent : typeChrome) == mItemType"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 2357); AnnotateMozCrashReason
("MOZ_DIAGNOSTIC_ASSERT" "(" "(mBrowsingContext->IsContent() ? typeContent : typeChrome) == mItemType"
")"); do { MOZ_CrashSequence(__null, 2357); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2357 (mBrowsingContext->IsContent() ? typeContent : typeChrome) == mItemType)do { static_assert( mozilla::detail::AssertionConditionType<
decltype((mBrowsingContext->IsContent() ? typeContent : typeChrome
) == mItemType)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!((mBrowsingContext->IsContent
() ? typeContent : typeChrome) == mItemType))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("(mBrowsingContext->IsContent() ? typeContent : typeChrome) == mItemType"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 2357); AnnotateMozCrashReason
("MOZ_DIAGNOSTIC_ASSERT" "(" "(mBrowsingContext->IsContent() ? typeContent : typeChrome) == mItemType"
")"); do { MOZ_CrashSequence(__null, 2357); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2358 *aItemType = mItemType;
2359 return NS_OK;
2360}
2361
2362NS_IMETHODIMPnsresult
2363nsDocShell::GetInProcessParent(nsIDocShellTreeItem** aParent) {
2364 if (!mParent) {
2365 *aParent = nullptr;
2366 } else {
2367 CallQueryInterface(mParent, aParent);
2368 }
2369 // Note that in the case when the parent is not an nsIDocShellTreeItem we
2370 // don't want to throw; we just want to return null.
2371 return NS_OK;
2372}
2373
2374// With Fission, related nsDocShell objects may exist in a different process. In
2375// that case, this method will return `nullptr`, despite a parent nsDocShell
2376// object existing.
2377//
2378// Prefer using `BrowsingContext::Parent()`, which will succeed even if the
2379// parent entry is not in the current process, and handle the case where the
2380// parent nsDocShell is inaccessible.
2381already_AddRefed<nsDocShell> nsDocShell::GetInProcessParentDocshell() {
2382 nsCOMPtr<nsIDocShell> docshell = do_QueryInterface(GetAsSupports(mParent));
2383 return docshell.forget().downcast<nsDocShell>();
2384}
2385
2386void nsDocShell::MaybeCreateInitialClientSource(nsIPrincipal* aPrincipal) {
2387 MOZ_ASSERT(!mIsBeingDestroyed)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mIsBeingDestroyed)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mIsBeingDestroyed))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("!mIsBeingDestroyed"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 2387); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!mIsBeingDestroyed" ")"); do { MOZ_CrashSequence
(__null, 2387); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
2388
2389 // If there is an existing document then there is no need to create
2390 // a client for a future initial about:blank document.
2391 if (mScriptGlobal && mScriptGlobal->GetCurrentInnerWindow() &&
2392 mScriptGlobal->GetCurrentInnerWindow()->GetExtantDoc()) {
2393 MOZ_DIAGNOSTIC_ASSERT(do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mScriptGlobal->GetCurrentInnerWindow()->GetClientInfo
().isSome())>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(mScriptGlobal->GetCurrentInnerWindow
()->GetClientInfo().isSome()))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("mScriptGlobal->GetCurrentInnerWindow()->GetClientInfo().isSome()"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 2394); AnnotateMozCrashReason
("MOZ_DIAGNOSTIC_ASSERT" "(" "mScriptGlobal->GetCurrentInnerWindow()->GetClientInfo().isSome()"
")"); do { MOZ_CrashSequence(__null, 2394); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2394 mScriptGlobal->GetCurrentInnerWindow()->GetClientInfo().isSome())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mScriptGlobal->GetCurrentInnerWindow()->GetClientInfo
().isSome())>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(mScriptGlobal->GetCurrentInnerWindow
()->GetClientInfo().isSome()))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("mScriptGlobal->GetCurrentInnerWindow()->GetClientInfo().isSome()"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 2394); AnnotateMozCrashReason
("MOZ_DIAGNOSTIC_ASSERT" "(" "mScriptGlobal->GetCurrentInnerWindow()->GetClientInfo().isSome()"
")"); do { MOZ_CrashSequence(__null, 2394); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2395 MOZ_DIAGNOSTIC_ASSERT(!mInitialClientSource)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mInitialClientSource)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mInitialClientSource))), 0)
)) { do { } while (false); MOZ_ReportAssertionFailure("!mInitialClientSource"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 2395); AnnotateMozCrashReason
("MOZ_DIAGNOSTIC_ASSERT" "(" "!mInitialClientSource" ")"); do
{ MOZ_CrashSequence(__null, 2395); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
2396 return;
2397 }
2398
2399 // Don't recreate the initial client source. We call this multiple times
2400 // when DoChannelLoad() is called before CreateAboutBlankDocumentViewer.
2401 if (mInitialClientSource) {
2402 return;
2403 }
2404
2405 // Don't pre-allocate the client when we are sandboxed. The inherited
2406 // principal does not take sandboxing into account.
2407 // TODO: Refactor sandboxing principal code out so we can use it here.
2408 if (!aPrincipal && mBrowsingContext->GetSandboxFlags()) {
2409 return;
2410 }
2411
2412 // We cannot get inherited foreign partitioned principal here. Instead, we
2413 // directly check which principal we want to inherit for the service worker.
2414 nsIPrincipal* principal =
2415 aPrincipal
2416 ? aPrincipal
2417 : GetInheritedPrincipal(
2418 false, StoragePrincipalHelper::
2419 ShouldUsePartitionPrincipalForServiceWorker(this));
2420
2421 // Sometimes there is no principal available when we are called from
2422 // CreateAboutBlankDocumentViewer. For example, sometimes the principal
2423 // is only extracted from the load context after the document is created
2424 // in Document::ResetToURI(). Ideally we would do something similar
2425 // here, but for now lets just avoid the issue by not preallocating the
2426 // client.
2427 if (!principal) {
2428 return;
2429 }
2430
2431 nsCOMPtr<nsPIDOMWindowOuter> win = GetWindow();
2432 if (!win) {
2433 return;
2434 }
2435
2436 mInitialClientSource = ClientManager::CreateSource(
2437 ClientType::Window, GetMainThreadSerialEventTarget(), principal);
2438 MOZ_DIAGNOSTIC_ASSERT(mInitialClientSource)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mInitialClientSource)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mInitialClientSource))), 0))
) { do { } while (false); MOZ_ReportAssertionFailure("mInitialClientSource"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 2438); AnnotateMozCrashReason
("MOZ_DIAGNOSTIC_ASSERT" "(" "mInitialClientSource" ")"); do {
MOZ_CrashSequence(__null, 2438); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
2439
2440 // Mark the initial client as execution ready, but owned by the docshell.
2441 // If the client is actually used this will cause ClientSource to force
2442 // the creation of the initial about:blank by calling
2443 // nsDocShell::GetDocument().
2444 mInitialClientSource->DocShellExecutionReady(this);
2445
2446 // Next, check to see if the parent is controlled.
2447 nsCOMPtr<nsIDocShell> parent = GetInProcessParentDocshell();
2448 nsPIDOMWindowOuter* parentOuter = parent ? parent->GetWindow() : nullptr;
2449 nsPIDOMWindowInner* parentInner =
2450 parentOuter ? parentOuter->GetCurrentInnerWindow() : nullptr;
2451 if (!parentInner) {
2452 return;
2453 }
2454
2455 nsCOMPtr<nsIURI> uri;
2456 MOZ_ALWAYS_SUCCEEDS(NS_NewURI(getter_AddRefs(uri), "about:blank"_ns))do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(NS_NewURI(getter_AddRefs(uri), "about:blank"_ns))), 1)))), 1
))) { } else { do { do { } while (false); MOZ_ReportCrash("" "NS_SUCCEEDED(NS_NewURI(getter_AddRefs(uri), \"about:blank\"_ns))"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 2456); AnnotateMozCrashReason
("MOZ_CRASH(" "NS_SUCCEEDED(NS_NewURI(getter_AddRefs(uri), \"about:blank\"_ns))"
")"); do { MOZ_CrashSequence(__null, 2456); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
;
2457
2458 // We're done if there is no parent controller or if this docshell
2459 // is not permitted to control for some reason.
2460 Maybe<ServiceWorkerDescriptor> controller(parentInner->GetController());
2461 if (controller.isNothing() ||
2462 !ServiceWorkerAllowedToControlWindow(principal, uri)) {
2463 return;
2464 }
2465
2466 mInitialClientSource->InheritController(controller.ref());
2467}
2468
2469Maybe<ClientInfo> nsDocShell::GetInitialClientInfo() const {
2470 if (mInitialClientSource) {
2471 Maybe<ClientInfo> result;
2472 result.emplace(mInitialClientSource->Info());
2473 return result;
2474 }
2475
2476 nsPIDOMWindowInner* innerWindow =
2477 mScriptGlobal ? mScriptGlobal->GetCurrentInnerWindow() : nullptr;
2478 Document* doc = innerWindow ? innerWindow->GetExtantDoc() : nullptr;
2479
2480 if (!doc || !doc->IsInitialDocument()) {
2481 return Maybe<ClientInfo>();
2482 }
2483
2484 return innerWindow->GetClientInfo();
2485}
2486
2487nsresult nsDocShell::SetDocLoaderParent(nsDocLoader* aParent) {
2488 bool wasFrame = IsSubframe();
2489
2490 nsresult rv = nsDocLoader::SetDocLoaderParent(aParent);
2491 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 2491); return rv; } } while (false)
;
2492
2493 nsCOMPtr<nsISupportsPriority> priorityGroup = do_QueryInterface(mLoadGroup);
2494 if (wasFrame != IsSubframe() && priorityGroup) {
2495 priorityGroup->AdjustPriority(wasFrame ? -1 : 1);
2496 }
2497
2498 // Curse ambiguous nsISupports inheritance!
2499 nsISupports* parent = GetAsSupports(aParent);
2500
2501 // If parent is another docshell, we inherit all their flags for
2502 // allowing plugins, scripting etc.
2503 bool value;
2504 nsCOMPtr<nsIDocShell> parentAsDocShell(do_QueryInterface(parent));
2505
2506 if (parentAsDocShell) {
2507 if (mAllowMetaRedirects &&
2508 NS_SUCCEEDED(parentAsDocShell->GetAllowMetaRedirects(&value))((bool)(__builtin_expect(!!(!NS_FAILED_impl(parentAsDocShell->
GetAllowMetaRedirects(&value))), 1)))
) {
2509 SetAllowMetaRedirects(value);
2510 }
2511 if (mAllowSubframes &&
2512 NS_SUCCEEDED(parentAsDocShell->GetAllowSubframes(&value))((bool)(__builtin_expect(!!(!NS_FAILED_impl(parentAsDocShell->
GetAllowSubframes(&value))), 1)))
) {
2513 SetAllowSubframes(value);
2514 }
2515 if (mAllowImages &&
2516 NS_SUCCEEDED(parentAsDocShell->GetAllowImages(&value))((bool)(__builtin_expect(!!(!NS_FAILED_impl(parentAsDocShell->
GetAllowImages(&value))), 1)))
) {
2517 SetAllowImages(value);
2518 }
2519 SetAllowMedia(parentAsDocShell->GetAllowMedia() && mAllowMedia);
2520 if (mAllowWindowControl &&
2521 NS_SUCCEEDED(parentAsDocShell->GetAllowWindowControl(&value))((bool)(__builtin_expect(!!(!NS_FAILED_impl(parentAsDocShell->
GetAllowWindowControl(&value))), 1)))
) {
2522 SetAllowWindowControl(value);
2523 }
2524 if (NS_FAILED(parentAsDocShell->GetAllowDNSPrefetch(&value))((bool)(__builtin_expect(!!(NS_FAILED_impl(parentAsDocShell->
GetAllowDNSPrefetch(&value))), 0)))
) {
2525 value = false;
2526 }
2527 SetAllowDNSPrefetch(mAllowDNSPrefetch && value);
2528 }
2529
2530 nsCOMPtr<nsIURIContentListener> parentURIListener(do_GetInterface(parent));
2531 if (parentURIListener) {
2532 mContentListener->SetParentContentListener(parentURIListener);
2533 }
2534
2535 return NS_OK;
2536}
2537
2538void nsDocShell::MaybeRestoreWindowName() {
2539 if (!StaticPrefs::privacy_window_name_update_enabled()) {
2540 return;
2541 }
2542
2543 // We only restore window.name for the top-level content.
2544 if (!mBrowsingContext->IsTopContent()) {
2545 return;
2546 }
2547
2548 nsAutoString name;
2549
2550 // Following implements https://html.spec.whatwg.org/#history-traversal:
2551 // Step 4.4. Check if the loading entry has a name.
2552
2553 if (mLSHE) {
2554 mLSHE->GetName(name);
2555 }
2556
2557 if (mLoadingEntry) {
2558 name = mLoadingEntry->mInfo.GetName();
2559 }
2560
2561 if (name.IsEmpty()) {
2562 return;
2563 }
2564
2565 // Step 4.4.1. Set the name to the browsing context.
2566 Unused << mBrowsingContext->SetName(name);
2567
2568 // Step 4.4.2. Clear the name of all entries that are contiguous and
2569 // same-origin with the loading entry.
2570 if (mLSHE) {
2571 nsSHistory::WalkContiguousEntries(
2572 mLSHE, [](nsISHEntry* aEntry) { aEntry->SetName(EmptyString()); });
2573 }
2574
2575 if (mLoadingEntry) {
2576 // Clear the name of the session entry in the child side. For parent side,
2577 // the clearing will be done when we commit the history to the parent.
2578 mLoadingEntry->mInfo.SetName(EmptyString());
2579 }
2580}
2581
2582void nsDocShell::StoreWindowNameToSHEntries() {
2583 MOZ_ASSERT(mBrowsingContext->IsTopContent())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mBrowsingContext->IsTopContent())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mBrowsingContext->IsTopContent
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("mBrowsingContext->IsTopContent()", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 2583); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mBrowsingContext->IsTopContent()"
")"); do { MOZ_CrashSequence(__null, 2583); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2584
2585 nsAutoString name;
2586 mBrowsingContext->GetName(name);
2587
2588 if (mOSHE) {
2589 nsSHistory::WalkContiguousEntries(
2590 mOSHE, [&](nsISHEntry* aEntry) { aEntry->SetName(name); });
2591 }
2592
2593 if (mozilla::SessionHistoryInParent()) {
2594 if (XRE_IsParentProcess()) {
2595 SessionHistoryEntry* entry =
2596 mBrowsingContext->Canonical()->GetActiveSessionHistoryEntry();
2597 if (entry) {
2598 nsSHistory::WalkContiguousEntries(
2599 entry, [&](nsISHEntry* aEntry) { aEntry->SetName(name); });
2600 }
2601 } else {
2602 // Ask parent process to store the name in entries.
2603 mozilla::Unused
2604 << ContentChild::GetSingleton()
2605 ->SendSessionHistoryEntryStoreWindowNameInContiguousEntries(
2606 mBrowsingContext, name);
2607 }
2608 }
2609}
2610
2611NS_IMETHODIMPnsresult
2612nsDocShell::GetInProcessSameTypeParent(nsIDocShellTreeItem** aParent) {
2613 if (BrowsingContext* parentBC = mBrowsingContext->GetParent()) {
2614 *aParent = do_AddRef(parentBC->GetDocShell()).take();
2615 }
2616 return NS_OK;
2617}
2618
2619NS_IMETHODIMPnsresult
2620nsDocShell::GetInProcessRootTreeItem(nsIDocShellTreeItem** aRootTreeItem) {
2621 NS_ENSURE_ARG_POINTER(aRootTreeItem)do { if ((__builtin_expect(!!(!(aRootTreeItem)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aRootTreeItem" ") failed"
, nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 2621); return NS_ERROR_INVALID_POINTER; } } while (false)
;
2622
2623 RefPtr<nsDocShell> root = this;
2624 RefPtr<nsDocShell> parent = root->GetInProcessParentDocshell();
2625 while (parent) {
2626 root = parent;
2627 parent = root->GetInProcessParentDocshell();
2628 }
2629
2630 root.forget(aRootTreeItem);
2631 return NS_OK;
2632}
2633
2634NS_IMETHODIMPnsresult
2635nsDocShell::GetInProcessSameTypeRootTreeItem(
2636 nsIDocShellTreeItem** aRootTreeItem) {
2637 NS_ENSURE_ARG_POINTER(aRootTreeItem)do { if ((__builtin_expect(!!(!(aRootTreeItem)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aRootTreeItem" ") failed"
, nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 2637); return NS_ERROR_INVALID_POINTER; } } while (false)
;
2638 *aRootTreeItem = static_cast<nsIDocShellTreeItem*>(this);
2639
2640 nsCOMPtr<nsIDocShellTreeItem> parent;
2641 NS_ENSURE_SUCCESS(GetInProcessSameTypeParent(getter_AddRefs(parent)),do { nsresult __rv = GetInProcessSameTypeParent(getter_AddRefs
(parent)); if (((bool)(__builtin_expect(!!(NS_FAILED_impl(__rv
)), 0)))) { const char* name = mozilla::GetStaticErrorName(__rv
); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "GetInProcessSameTypeParent(getter_AddRefs(parent))"
, "NS_ERROR_FAILURE", static_cast<uint32_t>(__rv), name
? " (" : "", name ? name : "", name ? ")" : ""); NS_DebugBreak
(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 2642); return NS_ERROR_FAILURE; } } while (false)
2642 NS_ERROR_FAILURE)do { nsresult __rv = GetInProcessSameTypeParent(getter_AddRefs
(parent)); if (((bool)(__builtin_expect(!!(NS_FAILED_impl(__rv
)), 0)))) { const char* name = mozilla::GetStaticErrorName(__rv
); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "GetInProcessSameTypeParent(getter_AddRefs(parent))"
, "NS_ERROR_FAILURE", static_cast<uint32_t>(__rv), name
? " (" : "", name ? name : "", name ? ")" : ""); NS_DebugBreak
(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 2642); return NS_ERROR_FAILURE; } } while (false)
;
2643 while (parent) {
2644 *aRootTreeItem = parent;
2645 NS_ENSURE_SUCCESS(do { nsresult __rv = (*aRootTreeItem)->GetInProcessSameTypeParent
(getter_AddRefs(parent)); if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "(*aRootTreeItem)->GetInProcessSameTypeParent(getter_AddRefs(parent))"
, "NS_ERROR_FAILURE", static_cast<uint32_t>(__rv), name
? " (" : "", name ? name : "", name ? ")" : ""); NS_DebugBreak
(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 2647); return NS_ERROR_FAILURE; } } while (false)
2646 (*aRootTreeItem)->GetInProcessSameTypeParent(getter_AddRefs(parent)),do { nsresult __rv = (*aRootTreeItem)->GetInProcessSameTypeParent
(getter_AddRefs(parent)); if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "(*aRootTreeItem)->GetInProcessSameTypeParent(getter_AddRefs(parent))"
, "NS_ERROR_FAILURE", static_cast<uint32_t>(__rv), name
? " (" : "", name ? name : "", name ? ")" : ""); NS_DebugBreak
(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 2647); return NS_ERROR_FAILURE; } } while (false)
2647 NS_ERROR_FAILURE)do { nsresult __rv = (*aRootTreeItem)->GetInProcessSameTypeParent
(getter_AddRefs(parent)); if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "(*aRootTreeItem)->GetInProcessSameTypeParent(getter_AddRefs(parent))"
, "NS_ERROR_FAILURE", static_cast<uint32_t>(__rv), name
? " (" : "", name ? name : "", name ? ")" : ""); NS_DebugBreak
(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 2647); return NS_ERROR_FAILURE; } } while (false)
;
2648 }
2649 NS_ADDREF(*aRootTreeItem)(*aRootTreeItem)->AddRef();
2650 return NS_OK;
2651}
2652
2653NS_IMETHODIMPnsresult
2654nsDocShell::GetTreeOwner(nsIDocShellTreeOwner** aTreeOwner) {
2655 NS_ENSURE_ARG_POINTER(aTreeOwner)do { if ((__builtin_expect(!!(!(aTreeOwner)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aTreeOwner" ") failed",
nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp",
2655); return NS_ERROR_INVALID_POINTER; } } while (false)
;
2656
2657 *aTreeOwner = mTreeOwner;
2658 NS_IF_ADDREF(*aTreeOwner)ns_if_addref(*aTreeOwner);
2659 return NS_OK;
2660}
2661
2662NS_IMETHODIMPnsresult
2663nsDocShell::SetTreeOwner(nsIDocShellTreeOwner* aTreeOwner) {
2664 if (mIsBeingDestroyed && aTreeOwner) {
2665 return NS_ERROR_FAILURE;
2666 }
2667
2668 // Don't automatically set the progress based on the tree owner for frames
2669 if (!IsSubframe()) {
2670 nsCOMPtr<nsIWebProgress> webProgress =
2671 do_QueryInterface(GetAsSupports(this));
2672
2673 if (webProgress) {
2674 nsCOMPtr<nsIWebProgressListener> oldListener =
2675 do_QueryInterface(mTreeOwner);
2676 nsCOMPtr<nsIWebProgressListener> newListener =
2677 do_QueryInterface(aTreeOwner);
2678
2679 if (oldListener) {
2680 webProgress->RemoveProgressListener(oldListener);
2681 }
2682
2683 if (newListener) {
2684 webProgress->AddProgressListener(newListener,
2685 nsIWebProgress::NOTIFY_ALL);
2686 }
2687 }
2688 }
2689
2690 mTreeOwner = aTreeOwner; // Weak reference per API
2691
2692 for (auto* childDocLoader : mChildList.ForwardRange()) {
2693 nsCOMPtr<nsIDocShellTreeItem> child = do_QueryObject(childDocLoader);
2694 NS_ENSURE_TRUE(child, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(child)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "child" ") failed", nullptr
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 2694); return
NS_ERROR_FAILURE; } } while (false)
;
2695
2696 if (child->ItemType() == mItemType) {
2697 child->SetTreeOwner(aTreeOwner);
2698 }
2699 }
2700
2701 // If we're in the content process and have had a TreeOwner set on us, extract
2702 // our BrowserChild actor. If we've already had our BrowserChild set, assert
2703 // that it hasn't changed.
2704 if (mTreeOwner && XRE_IsContentProcess()) {
2705 nsCOMPtr<nsIBrowserChild> newBrowserChild = do_GetInterface(mTreeOwner);
2706 MOZ_ASSERT(newBrowserChild,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(newBrowserChild)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(newBrowserChild))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("newBrowserChild"
" (" "No BrowserChild actor for tree owner in Content!" ")",
"/root/firefox-clang/docshell/base/nsDocShell.cpp", 2707); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "newBrowserChild" ") (" "No BrowserChild actor for tree owner in Content!"
")"); do { MOZ_CrashSequence(__null, 2707); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2707 "No BrowserChild actor for tree owner in Content!")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(newBrowserChild)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(newBrowserChild))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("newBrowserChild"
" (" "No BrowserChild actor for tree owner in Content!" ")",
"/root/firefox-clang/docshell/base/nsDocShell.cpp", 2707); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "newBrowserChild" ") (" "No BrowserChild actor for tree owner in Content!"
")"); do { MOZ_CrashSequence(__null, 2707); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2708
2709 if (mBrowserChild) {
2710 nsCOMPtr<nsIBrowserChild> oldBrowserChild =
2711 do_QueryReferent(mBrowserChild);
2712 MOZ_RELEASE_ASSERT(do { static_assert( mozilla::detail::AssertionConditionType<
decltype(oldBrowserChild == newBrowserChild)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(oldBrowserChild == newBrowserChild
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"oldBrowserChild == newBrowserChild" " (" "Cannot change BrowserChild during nsDocShell lifetime!"
")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 2714
); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "oldBrowserChild == newBrowserChild"
") (" "Cannot change BrowserChild during nsDocShell lifetime!"
")"); do { MOZ_CrashSequence(__null, 2714); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2713 oldBrowserChild == newBrowserChild,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(oldBrowserChild == newBrowserChild)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(oldBrowserChild == newBrowserChild
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"oldBrowserChild == newBrowserChild" " (" "Cannot change BrowserChild during nsDocShell lifetime!"
")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 2714
); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "oldBrowserChild == newBrowserChild"
") (" "Cannot change BrowserChild during nsDocShell lifetime!"
")"); do { MOZ_CrashSequence(__null, 2714); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2714 "Cannot change BrowserChild during nsDocShell lifetime!")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(oldBrowserChild == newBrowserChild)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(oldBrowserChild == newBrowserChild
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"oldBrowserChild == newBrowserChild" " (" "Cannot change BrowserChild during nsDocShell lifetime!"
")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 2714
); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "oldBrowserChild == newBrowserChild"
") (" "Cannot change BrowserChild during nsDocShell lifetime!"
")"); do { MOZ_CrashSequence(__null, 2714); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2715 } else {
2716 mBrowserChild = do_GetWeakReference(newBrowserChild);
2717 }
2718 }
2719
2720 return NS_OK;
2721}
2722
2723NS_IMETHODIMPnsresult
2724nsDocShell::GetHistoryID(nsID& aID) {
2725 aID = mBrowsingContext->GetHistoryID();
2726 return NS_OK;
2727}
2728
2729const nsID& nsDocShell::HistoryID() { return mBrowsingContext->GetHistoryID(); }
2730
2731NS_IMETHODIMPnsresult
2732nsDocShell::GetIsInUnload(bool* aIsInUnload) {
2733 *aIsInUnload = mFiredUnloadEvent;
2734 return NS_OK;
2735}
2736
2737NS_IMETHODIMPnsresult
2738nsDocShell::GetInProcessChildCount(int32_t* aChildCount) {
2739 NS_ENSURE_ARG_POINTER(aChildCount)do { if ((__builtin_expect(!!(!(aChildCount)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aChildCount" ") failed"
, nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 2739); return NS_ERROR_INVALID_POINTER; } } while (false)
;
2740 *aChildCount = mChildList.Length();
2741 return NS_OK;
2742}
2743
2744NS_IMETHODIMPnsresult
2745nsDocShell::AddChild(nsIDocShellTreeItem* aChild) {
2746 NS_ENSURE_ARG_POINTER(aChild)do { if ((__builtin_expect(!!(!(aChild)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aChild" ") failed", nullptr
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 2746); return
NS_ERROR_INVALID_POINTER; } } while (false)
;
2747
2748 RefPtr<nsDocLoader> childAsDocLoader = GetAsDocLoader(aChild);
2749 NS_ENSURE_TRUE(childAsDocLoader, NS_ERROR_UNEXPECTED)do { if ((__builtin_expect(!!(!(childAsDocLoader)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "childAsDocLoader" ") failed"
, nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 2749); return NS_ERROR_UNEXPECTED; } } while (false)
;
2750
2751 // Make sure we're not creating a loop in the docshell tree
2752 nsDocLoader* ancestor = this;
2753 do {
2754 if (childAsDocLoader == ancestor) {
2755 return NS_ERROR_ILLEGAL_VALUE;
2756 }
2757 ancestor = ancestor->GetParent();
2758 } while (ancestor);
2759
2760 // Make sure to remove the child from its current parent.
2761 nsDocLoader* childsParent = childAsDocLoader->GetParent();
2762 if (childsParent) {
2763 nsresult rv = childsParent->RemoveChildLoader(childAsDocLoader);
2764 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 2764); return rv; } } while (false)
;
2765 }
2766
2767 // Make sure to clear the treeowner in case this child is a different type
2768 // from us.
2769 aChild->SetTreeOwner(nullptr);
2770
2771 nsresult res = AddChildLoader(childAsDocLoader);
2772 NS_ENSURE_SUCCESS(res, res)do { nsresult __rv = res; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "res", "res", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 2772); return res; } } while (false)
;
2773 NS_ASSERTION(!mChildList.IsEmpty(),do { if (!(!mChildList.IsEmpty())) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "child list must not be empty after a successful add", "!mChildList.IsEmpty()"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 2774); MOZ_PretendNoReturn
(); } } while (0)
2774 "child list must not be empty after a successful add")do { if (!(!mChildList.IsEmpty())) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "child list must not be empty after a successful add", "!mChildList.IsEmpty()"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 2774); MOZ_PretendNoReturn
(); } } while (0)
;
2775
2776 /* Set the child's global history if the parent has one */
2777 if (mBrowsingContext->GetUseGlobalHistory()) {
2778 // childDocShell->SetUseGlobalHistory(true);
2779 // this should be set through BC inherit
2780 MOZ_ASSERT(aChild->GetBrowsingContext()->GetUseGlobalHistory())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aChild->GetBrowsingContext()->GetUseGlobalHistory
())>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(aChild->GetBrowsingContext()->GetUseGlobalHistory
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("aChild->GetBrowsingContext()->GetUseGlobalHistory()",
"/root/firefox-clang/docshell/base/nsDocShell.cpp", 2780); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aChild->GetBrowsingContext()->GetUseGlobalHistory()"
")"); do { MOZ_CrashSequence(__null, 2780); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2781 }
2782
2783 if (aChild->ItemType() != mItemType) {
2784 return NS_OK;
2785 }
2786
2787 aChild->SetTreeOwner(mTreeOwner);
2788
2789 nsCOMPtr<nsIDocShell> childAsDocShell(do_QueryInterface(aChild));
2790 if (!childAsDocShell) {
2791 return NS_OK;
2792 }
2793
2794 // charset, style-disabling, and zoom will be inherited in SetupNewViewer()
2795
2796 // Now take this document's charset and set the child's parentCharset field
2797 // to it. We'll later use that field, in the loading process, for the
2798 // charset choosing algorithm.
2799 // If we fail, at any point, we just return NS_OK.
2800 // This code has some performance impact. But this will be reduced when
2801 // the current charset will finally be stored as an Atom, avoiding the
2802 // alias resolution extra look-up.
2803
2804 // we are NOT going to propagate the charset is this Chrome's docshell
2805 if (mItemType == nsIDocShellTreeItem::typeChrome) {
2806 return NS_OK;
2807 }
2808
2809 // get the parent's current charset
2810 if (!mDocumentViewer) {
2811 return NS_OK;
2812 }
2813 Document* doc = mDocumentViewer->GetDocument();
2814 if (!doc) {
2815 return NS_OK;
2816 }
2817
2818 const Encoding* parentCS = doc->GetDocumentCharacterSet();
2819 int32_t charsetSource = doc->GetDocumentCharacterSetSource();
2820 // set the child's parentCharset
2821 childAsDocShell->SetParentCharset(parentCS, charsetSource,
2822 doc->NodePrincipal());
2823
2824 // printf("### 1 >>> Adding child. Parent CS = %s. ItemType = %d.\n",
2825 // NS_LossyConvertUTF16toASCII(parentCS).get(), mItemType);
2826
2827 return NS_OK;
2828}
2829
2830NS_IMETHODIMPnsresult
2831nsDocShell::RemoveChild(nsIDocShellTreeItem* aChild) {
2832 NS_ENSURE_ARG_POINTER(aChild)do { if ((__builtin_expect(!!(!(aChild)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aChild" ") failed", nullptr
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 2832); return
NS_ERROR_INVALID_POINTER; } } while (false)
;
2833
2834 RefPtr<nsDocLoader> childAsDocLoader = GetAsDocLoader(aChild);
2835 NS_ENSURE_TRUE(childAsDocLoader, NS_ERROR_UNEXPECTED)do { if ((__builtin_expect(!!(!(childAsDocLoader)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "childAsDocLoader" ") failed"
, nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 2835); return NS_ERROR_UNEXPECTED; } } while (false)
;
2836
2837 nsresult rv = RemoveChildLoader(childAsDocLoader);
2838 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 2838); return rv; } } while (false)
;
2839
2840 aChild->SetTreeOwner(nullptr);
2841
2842 return nsDocLoader::AddDocLoaderAsChildOfRoot(childAsDocLoader);
2843}
2844
2845NS_IMETHODIMPnsresult
2846nsDocShell::GetInProcessChildAt(int32_t aIndex, nsIDocShellTreeItem** aChild) {
2847 NS_ENSURE_ARG_POINTER(aChild)do { if ((__builtin_expect(!!(!(aChild)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aChild" ") failed", nullptr
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 2847); return
NS_ERROR_INVALID_POINTER; } } while (false)
;
2848
2849 RefPtr<nsDocShell> child = GetInProcessChildAt(aIndex);
2850 NS_ENSURE_TRUE(child, NS_ERROR_UNEXPECTED)do { if ((__builtin_expect(!!(!(child)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "child" ") failed", nullptr
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 2850); return
NS_ERROR_UNEXPECTED; } } while (false)
;
2851
2852 child.forget(aChild);
2853
2854 return NS_OK;
2855}
2856
2857nsDocShell* nsDocShell::GetInProcessChildAt(int32_t aIndex) {
2858#ifdef DEBUG1
2859 if (aIndex < 0) {
2860 NS_WARNING("Negative index passed to GetChildAt")NS_DebugBreak(NS_DEBUG_WARNING, "Negative index passed to GetChildAt"
, nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 2860)
;
2861 } else if (static_cast<uint32_t>(aIndex) >= mChildList.Length()) {
2862 NS_WARNING("Too large an index passed to GetChildAt")NS_DebugBreak(NS_DEBUG_WARNING, "Too large an index passed to GetChildAt"
, nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 2862)
;
2863 }
2864#endif
2865
2866 nsIDocumentLoader* child = ChildAt(aIndex);
2867
2868 // child may be nullptr here.
2869 return static_cast<nsDocShell*>(child);
2870}
2871
2872nsresult nsDocShell::AddChildSHEntry(nsISHEntry* aCloneRef,
2873 nsISHEntry* aNewEntry,
2874 int32_t aChildOffset, uint32_t aLoadType,
2875 bool aCloneChildren) {
2876 MOZ_ASSERT(!mozilla::SessionHistoryInParent())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mozilla::SessionHistoryInParent())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mozilla::SessionHistoryInParent
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!mozilla::SessionHistoryInParent()", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 2876); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mozilla::SessionHistoryInParent()"
")"); do { MOZ_CrashSequence(__null, 2876); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2877 nsresult rv = NS_OK;
2878
2879 if (mLSHE && aLoadType != LOAD_PUSHSTATE) {
2880 /* You get here if you are currently building a
2881 * hierarchy ie.,you just visited a frameset page
2882 */
2883 if (NS_FAILED(mLSHE->ReplaceChild(aNewEntry))((bool)(__builtin_expect(!!(NS_FAILED_impl(mLSHE->ReplaceChild
(aNewEntry))), 0)))
) {
2884 rv = mLSHE->AddChild(aNewEntry, aChildOffset);
2885 }
2886 } else if (!aCloneRef) {
2887 /* This is an initial load in some subframe. Just append it if we can */
2888 if (mOSHE) {
2889 rv = mOSHE->AddChild(aNewEntry, aChildOffset, UseRemoteSubframes());
2890 }
2891 } else {
2892 RefPtr<ChildSHistory> shistory = GetRootSessionHistory();
2893 if (shistory) {
2894 rv = shistory->LegacySHistory()->AddNestedSHEntry(
2895 aCloneRef, aNewEntry, mBrowsingContext->Top(), aCloneChildren);
2896 }
2897 }
2898 return rv;
2899}
2900
2901nsresult nsDocShell::AddChildSHEntryToParent(nsISHEntry* aNewEntry,
2902 int32_t aChildOffset,
2903 bool aCloneChildren) {
2904 MOZ_ASSERT(!mozilla::SessionHistoryInParent())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mozilla::SessionHistoryInParent())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mozilla::SessionHistoryInParent
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!mozilla::SessionHistoryInParent()", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 2904); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mozilla::SessionHistoryInParent()"
")"); do { MOZ_CrashSequence(__null, 2904); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2905 /* You will get here when you are in a subframe and
2906 * a new url has been loaded on you.
2907 * The mOSHE in this subframe will be the previous url's
2908 * mOSHE. This mOSHE will be used as the identification
2909 * for this subframe in the CloneAndReplace function.
2910 */
2911
2912 // In this case, we will end up calling AddEntry, which increases the
2913 // current index by 1
2914 RefPtr<ChildSHistory> rootSH = GetRootSessionHistory();
2915 if (rootSH) {
2916 mPreviousEntryIndex = rootSH->Index();
2917 }
2918
2919 nsresult rv;
2920 // XXX(farre): this is not Fission safe, expect errors. This never
2921 // get's executed once session history in the parent is enabled.
2922 nsCOMPtr<nsIDocShell> parent = do_QueryInterface(GetAsSupports(mParent), &rv);
2923 NS_WARNING_ASSERTION(do { if (!(parent || !UseRemoteSubframes())) { NS_DebugBreak(
NS_DEBUG_WARNING, "Failed to add child session history entry! This will be resolved once "
"session history in the parent is enabled.", "parent || !UseRemoteSubframes()"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 2926); }
} while (false)
2924 parent || !UseRemoteSubframes(),do { if (!(parent || !UseRemoteSubframes())) { NS_DebugBreak(
NS_DEBUG_WARNING, "Failed to add child session history entry! This will be resolved once "
"session history in the parent is enabled.", "parent || !UseRemoteSubframes()"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 2926); }
} while (false)
2925 "Failed to add child session history entry! This will be resolved once "do { if (!(parent || !UseRemoteSubframes())) { NS_DebugBreak(
NS_DEBUG_WARNING, "Failed to add child session history entry! This will be resolved once "
"session history in the parent is enabled.", "parent || !UseRemoteSubframes()"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 2926); }
} while (false)
2926 "session history in the parent is enabled.")do { if (!(parent || !UseRemoteSubframes())) { NS_DebugBreak(
NS_DEBUG_WARNING, "Failed to add child session history entry! This will be resolved once "
"session history in the parent is enabled.", "parent || !UseRemoteSubframes()"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 2926); }
} while (false)
;
2927 if (parent) {
2928 rv = nsDocShell::Cast(parent)->AddChildSHEntry(
2929 mOSHE, aNewEntry, aChildOffset, mLoadType, aCloneChildren);
2930 }
2931
2932 if (rootSH) {
2933 mLoadedEntryIndex = rootSH->Index();
2934
2935 if (MOZ_UNLIKELY(MOZ_LOG_TEST(gPageCacheLog, LogLevel::Verbose))(__builtin_expect(!!((__builtin_expect(!!(mozilla::detail::log_test
(gPageCacheLog, LogLevel::Verbose)), 0))), 0))
) {
2936 MOZ_LOG(gPageCacheLog, LogLevel::Verbose,do { const ::mozilla::LogModule* moz_real_module = gPageCacheLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Verbose)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Verbose, "Previous index: %d, Loaded index: %d", mPreviousEntryIndex
, mLoadedEntryIndex); } } while (0)
2937 ("Previous index: %d, Loaded index: %d", mPreviousEntryIndex,do { const ::mozilla::LogModule* moz_real_module = gPageCacheLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Verbose)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Verbose, "Previous index: %d, Loaded index: %d", mPreviousEntryIndex
, mLoadedEntryIndex); } } while (0)
2938 mLoadedEntryIndex))do { const ::mozilla::LogModule* moz_real_module = gPageCacheLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Verbose)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Verbose, "Previous index: %d, Loaded index: %d", mPreviousEntryIndex
, mLoadedEntryIndex); } } while (0)
;
2939 }
2940 }
2941
2942 return rv;
2943}
2944
2945NS_IMETHODIMPnsresult
2946nsDocShell::GetCurrentSHEntry(nsISHEntry** aEntry, bool* aOSHE) {
2947 *aOSHE = false;
2948 *aEntry = nullptr;
2949 if (mLSHE) {
2950 NS_ADDREF(*aEntry = mLSHE)(*aEntry = mLSHE)->AddRef();
2951 } else if (mOSHE) {
2952 NS_ADDREF(*aEntry = mOSHE)(*aEntry = mOSHE)->AddRef();
2953 *aOSHE = true;
2954 }
2955 return NS_OK;
2956}
2957
2958NS_IMETHODIMPnsresult nsDocShell::SynchronizeLayoutHistoryState() {
2959 if (mActiveEntry && mActiveEntry->GetLayoutHistoryState() &&
2960 mBrowsingContext) {
2961 if (XRE_IsContentProcess()) {
2962 dom::ContentChild* contentChild = dom::ContentChild::GetSingleton();
2963 if (contentChild) {
2964 contentChild->SendSynchronizeLayoutHistoryState(
2965 mBrowsingContext, mActiveEntry->GetLayoutHistoryState());
2966 }
2967 } else {
2968 SessionHistoryEntry* entry =
2969 mBrowsingContext->Canonical()->GetActiveSessionHistoryEntry();
2970 if (entry) {
2971 entry->SetLayoutHistoryState(mActiveEntry->GetLayoutHistoryState());
2972 }
2973 }
2974 if (mLoadingEntry &&
2975 mLoadingEntry->mInfo.SharedId() == mActiveEntry->SharedId()) {
2976 mLoadingEntry->mInfo.SetLayoutHistoryState(
2977 mActiveEntry->GetLayoutHistoryState());
2978 }
2979 }
2980
2981 return NS_OK;
2982}
2983
2984void nsDocShell::SetLoadGroupDefaultLoadFlags(nsLoadFlags aLoadFlags) {
2985 if (mLoadGroup) {
2986 mLoadGroup->SetDefaultLoadFlags(aLoadFlags);
2987 } else {
2988 NS_WARNING(NS_DebugBreak(NS_DEBUG_WARNING, "nsDocShell::SetLoadGroupDefaultLoadFlags has no loadGroup to "
"propagate the mode to", nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 2990)
2989 "nsDocShell::SetLoadGroupDefaultLoadFlags has no loadGroup to "NS_DebugBreak(NS_DEBUG_WARNING, "nsDocShell::SetLoadGroupDefaultLoadFlags has no loadGroup to "
"propagate the mode to", nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 2990)
2990 "propagate the mode to")NS_DebugBreak(NS_DEBUG_WARNING, "nsDocShell::SetLoadGroupDefaultLoadFlags has no loadGroup to "
"propagate the mode to", nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 2990)
;
2991 }
2992}
2993
2994nsIScriptGlobalObject* nsDocShell::GetScriptGlobalObject() {
2995 NS_ENSURE_SUCCESS(EnsureScriptEnvironment(), nullptr)do { nsresult __rv = EnsureScriptEnvironment(); if (((bool)(__builtin_expect
(!!(NS_FAILED_impl(__rv)), 0)))) { const char* name = mozilla
::GetStaticErrorName(__rv); mozilla::SmprintfPointer msg = mozilla
::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%"
"X" "%s%s%s", "EnsureScriptEnvironment()", "nullptr", static_cast
<uint32_t>(__rv), name ? " (" : "", name ? name : "", name
? ")" : ""); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 2995); return
nullptr; } } while (false)
;
2996 return mScriptGlobal;
2997}
2998
2999Document* nsDocShell::GetDocument() {
3000 NS_ENSURE_SUCCESS(EnsureDocumentViewer(), nullptr)do { nsresult __rv = EnsureDocumentViewer(); if (((bool)(__builtin_expect
(!!(NS_FAILED_impl(__rv)), 0)))) { const char* name = mozilla
::GetStaticErrorName(__rv); mozilla::SmprintfPointer msg = mozilla
::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%"
"X" "%s%s%s", "EnsureDocumentViewer()", "nullptr", static_cast
<uint32_t>(__rv), name ? " (" : "", name ? name : "", name
? ")" : ""); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 3000); return
nullptr; } } while (false)
;
3001 return mDocumentViewer->GetDocument();
3002}
3003
3004Document* nsDocShell::GetExtantDocument() {
3005 return mDocumentViewer ? mDocumentViewer->GetDocument() : nullptr;
3006}
3007
3008nsPIDOMWindowOuter* nsDocShell::GetWindow() {
3009 if (NS_FAILED(EnsureScriptEnvironment())((bool)(__builtin_expect(!!(NS_FAILED_impl(EnsureScriptEnvironment
())), 0)))
) {
3010 return nullptr;
3011 }
3012 return mScriptGlobal;
3013}
3014
3015NS_IMETHODIMPnsresult
3016nsDocShell::GetDomWindow(mozIDOMWindowProxy** aWindow) {
3017 NS_ENSURE_ARG_POINTER(aWindow)do { if ((__builtin_expect(!!(!(aWindow)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aWindow" ") failed", nullptr
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 3017); return
NS_ERROR_INVALID_POINTER; } } while (false)
;
3018
3019 nsresult rv = EnsureScriptEnvironment();
3020 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 3020); return rv; } } while (false)
;
3021
3022 RefPtr<nsGlobalWindowOuter> window = mScriptGlobal;
3023 window.forget(aWindow);
3024 return NS_OK;
3025}
3026
3027NS_IMETHODIMPnsresult
3028nsDocShell::GetMessageManager(ContentFrameMessageManager** aMessageManager) {
3029 RefPtr<ContentFrameMessageManager> mm;
3030 if (RefPtr<BrowserChild> browserChild = BrowserChild::GetFrom(this)) {
3031 mm = browserChild->GetMessageManager();
3032 } else if (nsPIDOMWindowOuter* win = GetWindow()) {
3033 mm = win->GetMessageManager();
3034 }
3035 mm.forget(aMessageManager);
3036 return NS_OK;
3037}
3038
3039NS_IMETHODIMPnsresult
3040nsDocShell::GetIsNavigating(bool* aOut) {
3041 *aOut = mIsNavigating;
3042 return NS_OK;
3043}
3044
3045void nsDocShell::ClearFrameHistory(nsISHEntry* aEntry) {
3046 MOZ_ASSERT(!mozilla::SessionHistoryInParent())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mozilla::SessionHistoryInParent())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mozilla::SessionHistoryInParent
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!mozilla::SessionHistoryInParent()", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 3046); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mozilla::SessionHistoryInParent()"
")"); do { MOZ_CrashSequence(__null, 3046); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3047 RefPtr<ChildSHistory> rootSH = GetRootSessionHistory();
3048 if (!rootSH || !aEntry) {
3049 return;
3050 }
3051
3052 rootSH->LegacySHistory()->RemoveFrameEntries(aEntry);
3053}
3054
3055//-------------------------------------
3056//-- Helper Method for Print discovery
3057//-------------------------------------
3058bool nsDocShell::NavigationBlockedByPrinting(bool aDisplayErrorDialog) {
3059 if (!mBrowsingContext->Top()->GetIsPrinting()) {
3060 return false;
3061 }
3062 if (aDisplayErrorDialog) {
3063 DisplayLoadError(NS_ERROR_DOCUMENT_IS_PRINTMODE, nullptr, nullptr, nullptr);
3064 }
3065 return true;
3066}
3067
3068bool nsDocShell::IsNavigationAllowed(bool aDisplayPrintErrorDialog,
3069 bool aCheckIfUnloadFired) {
3070 bool isAllowed = !NavigationBlockedByPrinting(aDisplayPrintErrorDialog) &&
3071 (!aCheckIfUnloadFired || !mFiredUnloadEvent);
3072 if (!isAllowed) {
3073 return false;
3074 }
3075 if (!mDocumentViewer) {
3076 return true;
3077 }
3078 bool firingBeforeUnload;
3079 mDocumentViewer->GetBeforeUnloadFiring(&firingBeforeUnload);
3080 return !firingBeforeUnload;
3081}
3082
3083//*****************************************************************************
3084// nsDocShell::nsIWebNavigation
3085//*****************************************************************************
3086
3087NS_IMETHODIMPnsresult
3088nsDocShell::GetCanGoBack(bool* aCanGoBack) {
3089 *aCanGoBack = false;
3090 if (!IsNavigationAllowed(false)) {
3091 return NS_OK; // JS may not handle returning of an error code
3092 }
3093 RefPtr<ChildSHistory> rootSH = GetRootSessionHistory();
3094 if (rootSH) {
3095 *aCanGoBack = rootSH->CanGo(
3096 -1, StaticPrefs::browser_navigation_requireUserInteraction());
3097 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)
3098 ("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)
;
3099
3100 return NS_OK;
3101 }
3102 return NS_ERROR_FAILURE;
3103}
3104
3105NS_IMETHODIMPnsresult
3106nsDocShell::GetCanGoBackIgnoringUserInteraction(bool* aCanGoBack) {
3107 *aCanGoBack = false;
3108 if (!IsNavigationAllowed(false)) {
3109 return NS_OK; // JS may not handle returning of an error code
3110 }
3111 RefPtr<ChildSHistory> rootSH = GetRootSessionHistory();
3112 if (rootSH) {
3113 *aCanGoBack = rootSH->CanGo(-1, false);
3114 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)
3115 ("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)
3116 *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)
;
3117
3118 return NS_OK;
3119 }
3120 return NS_ERROR_FAILURE;
3121}
3122
3123NS_IMETHODIMPnsresult
3124nsDocShell::GetCanGoForward(bool* aCanGoForward) {
3125 *aCanGoForward = false;
3126 if (!IsNavigationAllowed(false)) {
3127 return NS_OK; // JS may not handle returning of an error code
3128 }
3129 RefPtr<ChildSHistory> rootSH = GetRootSessionHistory();
3130 if (rootSH) {
3131 *aCanGoForward = rootSH->CanGo(
3132 1, StaticPrefs::browser_navigation_requireUserInteraction());
3133 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)
3134 ("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)
;
3135 return NS_OK;
3136 }
3137 return NS_ERROR_FAILURE;
3138}
3139
3140NS_IMETHODIMPnsresult
3141nsDocShell::GoBack(bool aRequireUserInteraction, bool aUserActivation) {
3142 if (!IsNavigationAllowed()) {
3143 return NS_OK; // JS may not handle returning of an error code
3144 }
3145
3146 auto cleanupIsNavigating = MakeScopeExit([&]() { mIsNavigating = false; });
3147 mIsNavigating = true;
3148
3149 RefPtr<ChildSHistory> rootSH = GetRootSessionHistory();
3150 NS_ENSURE_TRUE(rootSH, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(rootSH)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "rootSH" ") failed", nullptr
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 3150); return
NS_ERROR_FAILURE; } } while (false)
;
3151 ErrorResult rv;
3152 rootSH->Go(-1, aRequireUserInteraction, aUserActivation, rv);
3153 return rv.StealNSResult();
3154}
3155
3156NS_IMETHODIMPnsresult
3157nsDocShell::GoForward(bool aRequireUserInteraction, bool aUserActivation) {
3158 if (!IsNavigationAllowed()) {
3159 return NS_OK; // JS may not handle returning of an error code
3160 }
3161
3162 auto cleanupIsNavigating = MakeScopeExit([&]() { mIsNavigating = false; });
3163 mIsNavigating = true;
3164
3165 RefPtr<ChildSHistory> rootSH = GetRootSessionHistory();
3166 NS_ENSURE_TRUE(rootSH, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(rootSH)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "rootSH" ") failed", nullptr
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 3166); return
NS_ERROR_FAILURE; } } while (false)
;
3167 ErrorResult rv;
3168 rootSH->Go(1, aRequireUserInteraction, aUserActivation, rv);
3169 return rv.StealNSResult();
3170}
3171
3172// XXX(nika): We may want to stop exposing this API in the child process? Going
3173// to a specific index from multiple different processes could definitely race.
3174NS_IMETHODIMPnsresult
3175nsDocShell::GotoIndex(int32_t aIndex, bool aUserActivation) {
3176 if (!IsNavigationAllowed()) {
3177 return NS_OK; // JS may not handle returning of an error code
3178 }
3179
3180 auto cleanupIsNavigating = MakeScopeExit([&]() { mIsNavigating = false; });
3181 mIsNavigating = true;
3182
3183 RefPtr<ChildSHistory> rootSH = GetRootSessionHistory();
3184 NS_ENSURE_TRUE(rootSH, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(rootSH)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "rootSH" ") failed", nullptr
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 3184); return
NS_ERROR_FAILURE; } } while (false)
;
3185
3186 ErrorResult rv;
3187 rootSH->GotoIndex(aIndex, aIndex - rootSH->Index(), false, aUserActivation,
3188 rv);
3189 return rv.StealNSResult();
3190}
3191
3192nsresult nsDocShell::LoadURI(nsIURI* aURI,
3193 const LoadURIOptions& aLoadURIOptions) {
3194 if (!IsNavigationAllowed()) {
3195 return NS_OK; // JS may not handle returning of an error code
3196 }
3197 RefPtr<nsDocShellLoadState> loadState;
3198 nsresult rv = nsDocShellLoadState::CreateFromLoadURIOptions(
3199 mBrowsingContext, aURI, aLoadURIOptions, getter_AddRefs(loadState));
3200 MOZ_ASSERT(rv != NS_ERROR_MALFORMED_URI)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(rv != NS_ERROR_MALFORMED_URI)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(rv != NS_ERROR_MALFORMED_URI
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"rv != NS_ERROR_MALFORMED_URI", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 3200); AnnotateMozCrashReason("MOZ_ASSERT" "(" "rv != NS_ERROR_MALFORMED_URI"
")"); do { MOZ_CrashSequence(__null, 3200); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3201 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) || !loadState) {
3202 return NS_ERROR_FAILURE;
3203 }
3204
3205 return LoadURI(loadState, true);
3206}
3207
3208NS_IMETHODIMPnsresult
3209nsDocShell::LoadURIFromScript(nsIURI* aURI,
3210 JS::Handle<JS::Value> aLoadURIOptions,
3211 JSContext* aCx) {
3212 // generate dictionary for aLoadURIOptions and forward call
3213 LoadURIOptions loadURIOptions;
3214 if (!loadURIOptions.Init(aCx, aLoadURIOptions)) {
3215 return NS_ERROR_INVALID_ARG;
3216 }
3217 return LoadURI(aURI, loadURIOptions);
3218}
3219
3220nsresult nsDocShell::FixupAndLoadURIString(
3221 const nsAString& aURIString, const LoadURIOptions& aLoadURIOptions) {
3222 if (!IsNavigationAllowed()) {
3223 return NS_OK; // JS may not handle returning of an error code
3224 }
3225
3226 RefPtr<nsDocShellLoadState> loadState;
3227 nsresult rv = nsDocShellLoadState::CreateFromLoadURIOptions(
3228 mBrowsingContext, aURIString, aLoadURIOptions, getter_AddRefs(loadState));
3229
3230 uint32_t loadFlags = aLoadURIOptions.mLoadFlags;
3231 if (NS_ERROR_MALFORMED_URI == rv) {
3232 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)
3233 ("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)
3234 "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)
3235 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)
;
3236
3237 // We need to store a session history entry. We don't have a valid URI, so
3238 // we use about:blank instead.
3239 nsCOMPtr<nsIURI> uri;
3240 MOZ_ALWAYS_SUCCEEDS(NS_NewURI(getter_AddRefs(uri), "about:blank"_ns))do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(NS_NewURI(getter_AddRefs(uri), "about:blank"_ns))), 1)))), 1
))) { } else { do { do { } while (false); MOZ_ReportCrash("" "NS_SUCCEEDED(NS_NewURI(getter_AddRefs(uri), \"about:blank\"_ns))"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 3240); AnnotateMozCrashReason
("MOZ_CRASH(" "NS_SUCCEEDED(NS_NewURI(getter_AddRefs(uri), \"about:blank\"_ns))"
")"); do { MOZ_CrashSequence(__null, 3240); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
;
3241 nsCOMPtr<nsIPrincipal> triggeringPrincipal;
3242 if (aLoadURIOptions.mTriggeringPrincipal) {
3243 triggeringPrincipal = aLoadURIOptions.mTriggeringPrincipal;
3244 } else {
3245 triggeringPrincipal = nsContentUtils::GetSystemPrincipal();
3246 }
3247 if (mozilla::SessionHistoryInParent()) {
3248 UniquePtr<SessionHistoryInfo> previousActiveEntry(mActiveEntry.release());
3249 mActiveEntry = MakeUnique<SessionHistoryInfo>(
3250 uri, triggeringPrincipal, nullptr, nullptr, nullptr,
3251 nsLiteralCString("text/html"));
3252 mBrowsingContext->SetActiveSessionHistoryEntry(
3253 Nothing(), mActiveEntry.get(), previousActiveEntry.get(),
3254 MAKE_LOAD_TYPE(LOAD_NORMAL, loadFlags)((LOAD_NORMAL) | ((loadFlags) << 16)),
3255 /* aUpdatedCacheKey = */ 0);
3256 }
3257 if (DisplayLoadError(rv, nullptr, PromiseFlatStringTPromiseFlatString<char16_t>(aURIString).get(),
3258 nullptr) &&
3259 (loadFlags & LOAD_FLAGS_ERROR_LOAD_CHANGES_RV) != 0) {
3260 return NS_ERROR_LOAD_SHOWED_ERRORPAGE;
3261 }
3262 }
3263
3264 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) || !loadState) {
3265 return NS_ERROR_FAILURE;
3266 }
3267
3268 return LoadURI(loadState, true);
3269}
3270
3271NS_IMETHODIMPnsresult
3272nsDocShell::FixupAndLoadURIStringFromScript(
3273 const nsAString& aURIString, JS::Handle<JS::Value> aLoadURIOptions,
3274 JSContext* aCx) {
3275 // generate dictionary for aLoadURIOptions and forward call
3276 LoadURIOptions loadURIOptions;
3277 if (!loadURIOptions.Init(aCx, aLoadURIOptions)) {
3278 return NS_ERROR_INVALID_ARG;
3279 }
3280 return FixupAndLoadURIString(aURIString, loadURIOptions);
3281}
3282
3283void nsDocShell::UnblockEmbedderLoadEventForFailure(bool aFireFrameErrorEvent) {
3284 // If we're not in a content frame, or are at a BrowsingContext tree boundary,
3285 // such as the content-chrome boundary, don't fire the error event.
3286 if (mBrowsingContext->IsTopContent() || mBrowsingContext->IsChrome()) {
3287 return;
3288 }
3289
3290 // If embedder is same-process, then unblocking the load event is already
3291 // handled by nsDocLoader. Fire the error event on our embedder element if
3292 // requested.
3293 //
3294 // XXX: Bug 1440212 is looking into potentially changing this behaviour to act
3295 // more like the remote case when in-process.
3296 RefPtr<Element> element = mBrowsingContext->GetEmbedderElement();
3297 if (element) {
3298 if (aFireFrameErrorEvent) {
3299 if (RefPtr<nsFrameLoaderOwner> flo = do_QueryObject(element)) {
3300 if (RefPtr<nsFrameLoader> fl = flo->GetFrameLoader()) {
3301 fl->FireErrorEvent();
3302 }
3303 }
3304 }
3305 return;
3306 }
3307
3308 // If we have a cross-process parent document, we must notify it that we no
3309 // longer block its load event. This is necessary for OOP sub-documents
3310 // because error documents do not result in a call to
3311 // SendMaybeFireEmbedderLoadEvents via any of the normal call paths.
3312 // (Obviously, we must do this before any of the returns below.)
3313 RefPtr<BrowserChild> browserChild = BrowserChild::GetFrom(this);
3314 if (browserChild &&
3315 !mBrowsingContext->GetParentWindowContext()->IsInProcess()) {
3316 mozilla::Unused << browserChild->SendMaybeFireEmbedderLoadEvents(
3317 aFireFrameErrorEvent ? EmbedderElementEventType::ErrorEvent
3318 : EmbedderElementEventType::NoEvent);
3319 }
3320}
3321
3322NS_IMETHODIMPnsresult
3323nsDocShell::DisplayLoadError(nsresult aError, nsIURI* aURI,
3324 const char16_t* aURL, nsIChannel* aFailedChannel,
3325 bool* aDisplayedErrorPage) {
3326 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
)
3327 ("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
)
3328 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
)
;
3329
3330 *aDisplayedErrorPage = false;
3331 // Get prompt and string bundle services
3332 nsCOMPtr<nsIPrompt> prompter;
3333 nsCOMPtr<nsIStringBundle> stringBundle;
3334 GetPromptAndStringBundle(getter_AddRefs(prompter),
3335 getter_AddRefs(stringBundle));
3336
3337 NS_ENSURE_TRUE(stringBundle, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(stringBundle)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "stringBundle" ") failed"
, nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 3337); return NS_ERROR_FAILURE; } } while (false)
;
3338 NS_ENSURE_TRUE(prompter, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(prompter)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "prompter" ") failed", nullptr
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 3338); return
NS_ERROR_FAILURE; } } while (false)
;
3339
3340 const char* error = nullptr;
3341 // The key used to select the appropriate error message from the properties
3342 // file.
3343 const char* errorDescriptionID = nullptr;
3344 AutoTArray<nsString, 3> formatStrs;
3345 bool addHostPort = false;
3346 bool isBadStsCertError = false;
3347 nsresult rv = NS_OK;
3348 nsAutoString messageStr;
3349 nsAutoCString cssClass;
3350 nsAutoCString errorPage;
3351
3352 errorPage.AssignLiteral("neterror");
3353
3354 // Turn the error code into a human readable error message.
3355 if (NS_ERROR_UNKNOWN_PROTOCOL == aError) {
3356 NS_ENSURE_ARG_POINTER(aURI)do { if ((__builtin_expect(!!(!(aURI)), 0))) { NS_DebugBreak(
NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aURI" ") failed", nullptr
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 3356); return
NS_ERROR_INVALID_POINTER; } } while (false)
;
3357
3358 // Extract the schemes into a comma delimited list.
3359 nsAutoCString scheme;
3360 aURI->GetScheme(scheme);
3361 CopyASCIItoUTF16(scheme, *formatStrs.AppendElement());
3362 nsCOMPtr<nsINestedURI> nestedURI = do_QueryInterface(aURI);
3363 while (nestedURI) {
3364 nsCOMPtr<nsIURI> tempURI;
3365 nsresult rv2;
3366 rv2 = nestedURI->GetInnerURI(getter_AddRefs(tempURI));
3367 if (NS_SUCCEEDED(rv2)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv2)), 1))) && tempURI) {
3368 tempURI->GetScheme(scheme);
3369 formatStrs[0].AppendLiteral(", ");
3370 AppendASCIItoUTF16(scheme, formatStrs[0]);
3371 }
3372 nestedURI = do_QueryInterface(tempURI);
3373 }
3374 error = "unknownProtocolFound";
3375 } else if (NS_ERROR_NET_EMPTY_RESPONSE == aError) {
3376 NS_ENSURE_ARG_POINTER(aURI)do { if ((__builtin_expect(!!(!(aURI)), 0))) { NS_DebugBreak(
NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aURI" ") failed", nullptr
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 3376); return
NS_ERROR_INVALID_POINTER; } } while (false)
;
3377 error = "httpErrorPage";
3378 } else if (NS_ERROR_NET_ERROR_RESPONSE == aError) {
3379 NS_ENSURE_ARG_POINTER(aURI)do { if ((__builtin_expect(!!(!(aURI)), 0))) { NS_DebugBreak(
NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aURI" ") failed", nullptr
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 3379); return
NS_ERROR_INVALID_POINTER; } } while (false)
;
3380 error = "serverError";
3381 } else if (NS_ERROR_FILE_NOT_FOUND == aError) {
3382 NS_ENSURE_ARG_POINTER(aURI)do { if ((__builtin_expect(!!(!(aURI)), 0))) { NS_DebugBreak(
NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aURI" ") failed", nullptr
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 3382); return
NS_ERROR_INVALID_POINTER; } } while (false)
;
3383 error = "fileNotFound";
3384 } else if (NS_ERROR_FILE_ACCESS_DENIED == aError) {
3385 NS_ENSURE_ARG_POINTER(aURI)do { if ((__builtin_expect(!!(!(aURI)), 0))) { NS_DebugBreak(
NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aURI" ") failed", nullptr
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 3385); return
NS_ERROR_INVALID_POINTER; } } while (false)
;
3386 error = "fileAccessDenied";
3387 } else if (NS_ERROR_UNKNOWN_HOST == aError) {
3388 NS_ENSURE_ARG_POINTER(aURI)do { if ((__builtin_expect(!!(!(aURI)), 0))) { NS_DebugBreak(
NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aURI" ") failed", nullptr
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 3388); return
NS_ERROR_INVALID_POINTER; } } while (false)
;
3389 // Get the host
3390 nsAutoCString host;
3391 nsCOMPtr<nsIURI> innermostURI = NS_GetInnermostURI(aURI);
3392 innermostURI->GetHost(host);
3393 CopyUTF8toUTF16(host, *formatStrs.AppendElement());
3394 errorDescriptionID = "dnsNotFound2";
3395 error = "dnsNotFound";
3396 } else if (NS_ERROR_CONNECTION_REFUSED == aError ||
3397 NS_ERROR_PROXY_BAD_GATEWAY == aError) {
3398 NS_ENSURE_ARG_POINTER(aURI)do { if ((__builtin_expect(!!(!(aURI)), 0))) { NS_DebugBreak(
NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aURI" ") failed", nullptr
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 3398); return
NS_ERROR_INVALID_POINTER; } } while (false)
;
3399 addHostPort = true;
3400 error = "connectionFailure";
3401 } else if (NS_ERROR_NET_INTERRUPT == aError) {
3402 NS_ENSURE_ARG_POINTER(aURI)do { if ((__builtin_expect(!!(!(aURI)), 0))) { NS_DebugBreak(
NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aURI" ") failed", nullptr
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 3402); return
NS_ERROR_INVALID_POINTER; } } while (false)
;
3403 addHostPort = true;
3404 error = "netInterrupt";
3405 } else if (NS_ERROR_NET_TIMEOUT == aError ||
3406 NS_ERROR_PROXY_GATEWAY_TIMEOUT == aError ||
3407 NS_ERROR_NET_TIMEOUT_EXTERNAL == aError) {
3408 NS_ENSURE_ARG_POINTER(aURI)do { if ((__builtin_expect(!!(!(aURI)), 0))) { NS_DebugBreak(
NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aURI" ") failed", nullptr
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 3408); return
NS_ERROR_INVALID_POINTER; } } while (false)
;
3409 // Get the host
3410 nsAutoCString host;
3411 aURI->GetHost(host);
3412 CopyUTF8toUTF16(host, *formatStrs.AppendElement());
3413 error = "netTimeout";
3414 } else if (NS_ERROR_CSP_FRAME_ANCESTOR_VIOLATION == aError ||
3415 NS_ERROR_CSP_FORM_ACTION_VIOLATION == aError) {
3416 // CSP error
3417 cssClass.AssignLiteral("neterror");
3418 error = "cspBlocked";
3419 } else if (NS_ERROR_XFO_VIOLATION == aError) {
3420 // XFO error
3421 cssClass.AssignLiteral("neterror");
3422 error = "xfoBlocked";
3423 } else if (NS_ERROR_GET_MODULE(aError) == NS_ERROR_MODULE_SECURITY21) {
3424 nsCOMPtr<nsINSSErrorsService> nsserr =
3425 do_GetService(NS_NSS_ERRORS_SERVICE_CONTRACTID"@mozilla.org/nss_errors_service;1");
3426
3427 uint32_t errorClass;
3428 if (!nsserr || NS_FAILED(nsserr->GetErrorClass(aError, &errorClass))((bool)(__builtin_expect(!!(NS_FAILED_impl(nsserr->GetErrorClass
(aError, &errorClass))), 0)))
) {
3429 errorClass = nsINSSErrorsService::ERROR_CLASS_SSL_PROTOCOL;
3430 }
3431
3432 nsCOMPtr<nsITransportSecurityInfo> tsi;
3433 if (aFailedChannel) {
3434 aFailedChannel->GetSecurityInfo(getter_AddRefs(tsi));
3435 }
3436 if (tsi) {
3437 uint32_t securityState;
3438 tsi->GetSecurityState(&securityState);
3439 if (securityState & nsIWebProgressListener::STATE_USES_SSL_3) {
3440 error = "sslv3Used";
Value stored to 'error' is never read
3441 addHostPort = true;
3442 } else if (securityState &
3443 nsIWebProgressListener::STATE_USES_WEAK_CRYPTO) {
3444 error = "weakCryptoUsed";
3445 addHostPort = true;
3446 }
3447 } else {
3448 // No channel, let's obtain the generic error message
3449 if (nsserr) {
3450 nsserr->GetErrorMessage(aError, messageStr);
3451 }
3452 }
3453 // We don't have a message string here anymore but DisplayLoadError
3454 // requires a non-empty messageStr.
3455 messageStr.Truncate();
3456 messageStr.AssignLiteral(u" ");
3457 if (errorClass == nsINSSErrorsService::ERROR_CLASS_BAD_CERT) {
3458 error = "nssBadCert";
3459
3460 // If this is an HTTP Strict Transport Security host or a pinned host
3461 // and the certificate is bad, don't allow overrides (RFC 6797 section
3462 // 12.1).
3463 bool isStsHost = false;
3464 bool isPinnedHost = false;
3465 OriginAttributes attrsForHSTS;
3466 if (aFailedChannel) {
3467 StoragePrincipalHelper::GetOriginAttributesForHSTS(aFailedChannel,
3468 attrsForHSTS);
3469 } else {
3470 attrsForHSTS = GetOriginAttributes();
3471 }
3472
3473 if (XRE_IsParentProcess()) {
3474 nsCOMPtr<nsISiteSecurityService> sss =
3475 do_GetService(NS_SSSERVICE_CONTRACTID"@mozilla.org/ssservice;1", &rv);
3476 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 3476); return rv; } } while (false)
;
3477 rv = sss->IsSecureURI(aURI, attrsForHSTS, &isStsHost);
3478 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 3478); return rv; } } while (false)
;
3479 } else {
3480 mozilla::dom::ContentChild* cc =
3481 mozilla::dom::ContentChild::GetSingleton();
3482 cc->SendIsSecureURI(aURI, attrsForHSTS, &isStsHost);
3483 }
3484 nsCOMPtr<nsIPublicKeyPinningService> pkps =
3485 do_GetService(NS_PKPSERVICE_CONTRACTID"@mozilla.org/security/publickeypinningservice;1", &rv);
3486 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 3486); return rv; } } while (false)
;
3487 rv = pkps->HostHasPins(aURI, &isPinnedHost);
3488
3489 if (Preferences::GetBool("browser.xul.error_pages.expert_bad_cert",
3490 false)) {
3491 cssClass.AssignLiteral("expertBadCert");
3492 }
3493
3494 // HSTS/pinning takes precedence over the expert bad cert pref. We
3495 // never want to show the "Add Exception" button for these sites.
3496 // In the future we should differentiate between an HSTS host and a
3497 // pinned host and display a more informative message to the user.
3498 if (isStsHost || isPinnedHost) {
3499 isBadStsCertError = true;
3500 cssClass.AssignLiteral("badStsCert");
3501 }
3502
3503 errorPage.Assign("certerror");
3504 } else {
3505 error = "nssFailure2";
3506 }
3507 } else if (NS_ERROR_PHISHING_URI == aError ||
3508 NS_ERROR_MALWARE_URI == aError ||
3509 NS_ERROR_UNWANTED_URI == aError ||
3510 NS_ERROR_HARMFUL_URI == aError) {
3511 nsAutoCString host;
3512 aURI->GetHost(host);
3513 CopyUTF8toUTF16(host, *formatStrs.AppendElement());
3514
3515 // Malware and phishing detectors may want to use an alternate error
3516 // page, but if the pref's not set, we'll fall back on the standard page
3517 nsAutoCString alternateErrorPage;
3518 nsresult rv = Preferences::GetCString("urlclassifier.alternate_error_page",
3519 alternateErrorPage);
3520 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
3521 errorPage.Assign(alternateErrorPage);
3522 }
3523
3524 if (NS_ERROR_PHISHING_URI == aError) {
3525 error = "deceptiveBlocked";
3526 } else if (NS_ERROR_MALWARE_URI == aError) {
3527 error = "malwareBlocked";
3528 } else if (NS_ERROR_UNWANTED_URI == aError) {
3529 error = "unwantedBlocked";
3530 } else if (NS_ERROR_HARMFUL_URI == aError) {
3531 error = "harmfulBlocked";
3532 }
3533
3534 cssClass.AssignLiteral("blacklist");
3535 } else if (NS_ERROR_CONTENT_CRASHED == aError) {
3536 errorPage.AssignLiteral("tabcrashed");
3537 error = "tabcrashed";
3538
3539 RefPtr<EventTarget> handler = mChromeEventHandler;
3540 if (handler) {
3541 nsCOMPtr<Element> element = do_QueryInterface(handler);
3542 element->GetAttribute(u"crashedPageTitle"_ns, messageStr);
3543 }
3544
3545 // DisplayLoadError requires a non-empty messageStr to proceed and call
3546 // LoadErrorPage. If the page doesn't have a title, we will use a blank
3547 // space which will be trimmed and thus treated as empty by the front-end.
3548 if (messageStr.IsEmpty()) {
3549 messageStr.AssignLiteral(u" ");
3550 }
3551 } else if (NS_ERROR_FRAME_CRASHED == aError) {
3552 errorPage.AssignLiteral("framecrashed");
3553 error = "framecrashed";
3554 messageStr.AssignLiteral(u" ");
3555 } else if (NS_ERROR_BUILDID_MISMATCH == aError) {
3556 errorPage.AssignLiteral("restartrequired");
3557 error = "restartrequired";
3558
3559 // DisplayLoadError requires a non-empty messageStr to proceed and call
3560 // LoadErrorPage. If the page doesn't have a title, we will use a blank
3561 // space which will be trimmed and thus treated as empty by the front-end.
3562 if (messageStr.IsEmpty()) {
3563 messageStr.AssignLiteral(u" ");
3564 }
3565 } else {
3566 // Errors requiring simple formatting
3567 switch (aError) {
3568 case NS_ERROR_MALFORMED_URI:
3569 // URI is malformed
3570 error = "malformedURI";
3571 errorDescriptionID = "malformedURI2";
3572 break;
3573 case NS_ERROR_REDIRECT_LOOP:
3574 // Doc failed to load because the server generated too many redirects
3575 error = "redirectLoop";
3576 break;
3577 case NS_ERROR_UNKNOWN_SOCKET_TYPE:
3578 // Doc failed to load because PSM is not installed
3579 error = "unknownSocketType";
3580 break;
3581 case NS_ERROR_NET_RESET:
3582 // Doc failed to load because the server kept reseting the connection
3583 // before we could read any data from it
3584 error = "netReset";
3585 break;
3586 case NS_ERROR_DOCUMENT_NOT_CACHED:
3587 // Doc failed to load because the cache does not contain a copy of
3588 // the document.
3589 error = "notCached";
3590 break;
3591 case NS_ERROR_OFFLINE:
3592 // Doc failed to load because we are offline.
3593 error = "netOffline";
3594 break;
3595 case NS_ERROR_DOCUMENT_IS_PRINTMODE:
3596 // Doc navigation attempted while Printing or Print Preview
3597 error = "isprinting";
3598 break;
3599 case NS_ERROR_PORT_ACCESS_NOT_ALLOWED:
3600 // Port blocked for security reasons
3601 addHostPort = true;
3602 error = "deniedPortAccess";
3603 break;
3604 case NS_ERROR_UNKNOWN_PROXY_HOST:
3605 // Proxy hostname could not be resolved.
3606 error = "proxyResolveFailure";
3607 break;
3608 case NS_ERROR_PROXY_CONNECTION_REFUSED:
3609 case NS_ERROR_PROXY_FORBIDDEN:
3610 case NS_ERROR_PROXY_NOT_IMPLEMENTED:
3611 case NS_ERROR_PROXY_AUTHENTICATION_FAILED:
3612 case NS_ERROR_PROXY_TOO_MANY_REQUESTS:
3613 // Proxy connection was refused.
3614 error = "proxyConnectFailure";
3615 break;
3616 case NS_ERROR_INVALID_CONTENT_ENCODING:
3617 // Bad Content Encoding.
3618 error = "contentEncodingError";
3619 break;
3620 case NS_ERROR_UNSAFE_CONTENT_TYPE:
3621 // Channel refused to load from an unrecognized content type.
3622 error = "unsafeContentType";
3623 break;
3624 case NS_ERROR_CORRUPTED_CONTENT:
3625 // Broken Content Detected. e.g. Content-MD5 check failure.
3626 error = "corruptedContentErrorv2";
3627 break;
3628 case NS_ERROR_INTERCEPTION_FAILED:
3629 // ServiceWorker intercepted request, but something went wrong.
3630 error = "corruptedContentErrorv2";
3631 break;
3632 case NS_ERROR_NET_INADEQUATE_SECURITY:
3633 // Server negotiated bad TLS for HTTP/2.
3634 error = "inadequateSecurityError";
3635 addHostPort = true;
3636 break;
3637 case NS_ERROR_BLOCKED_BY_POLICY:
3638 // Page blocked by policy
3639 error = "blockedByPolicy";
3640 break;
3641 case NS_ERROR_DOM_COOP_FAILED:
3642 error = "blockedByCOOP";
3643 errorDescriptionID = "blockedByCORP";
3644 break;
3645 case NS_ERROR_DOM_COEP_FAILED:
3646 error = "blockedByCOEP";
3647 errorDescriptionID = "blockedByCORP";
3648 break;
3649 case NS_ERROR_DOM_INVALID_HEADER_VALUE:
3650 error = "invalidHeaderValue";
3651 break;
3652 case NS_ERROR_NET_HTTP2_SENT_GOAWAY:
3653 case NS_ERROR_NET_HTTP3_PROTOCOL_ERROR:
3654 // HTTP/2 or HTTP/3 stack detected a protocol error
3655 error = "networkProtocolError";
3656 break;
3657 case NS_ERROR_BASIC_HTTP_AUTH_DISABLED:
3658 error = "basicHttpAuthDisabled";
3659 break;
3660 default:
3661 break;
3662 }
3663 }
3664
3665 nsresult delegateErrorCode = aError;
3666 // If the HTTPS-Only Mode upgraded this request and the upgrade might have
3667 // caused this error, we replace the error-page with about:httpsonlyerror
3668 if (nsHTTPSOnlyUtils::CouldBeHttpsOnlyError(aFailedChannel, aError)) {
3669 errorPage.AssignLiteral("httpsonlyerror");
3670 delegateErrorCode = NS_ERROR_HTTPS_ONLY;
3671 } else if (isBadStsCertError) {
3672 delegateErrorCode = NS_ERROR_BAD_HSTS_CERT;
3673 }
3674
3675 if (nsCOMPtr<nsILoadURIDelegate> loadURIDelegate = GetLoadURIDelegate()) {
3676 nsCOMPtr<nsIURI> errorPageURI;
3677 rv = loadURIDelegate->HandleLoadError(
3678 aURI, delegateErrorCode, NS_ERROR_GET_MODULE(delegateErrorCode),
3679 getter_AddRefs(errorPageURI));
3680 // If the docshell is going away there's no point in showing an error page.
3681 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) || mIsBeingDestroyed) {
3682 *aDisplayedErrorPage = false;
3683 return NS_OK;
3684 }
3685
3686 if (errorPageURI) {
3687 *aDisplayedErrorPage =
3688 NS_SUCCEEDED(LoadErrorPage(errorPageURI, aURI, aFailedChannel))((bool)(__builtin_expect(!!(!NS_FAILED_impl(LoadErrorPage(errorPageURI
, aURI, aFailedChannel))), 1)))
;
3689 return NS_OK;
3690 }
3691 }
3692
3693 // Test if the error should be displayed
3694 if (!error) {
3695 return NS_OK;
3696 }
3697
3698 if (!errorDescriptionID) {
3699 errorDescriptionID = error;
3700 }
3701
3702 glean::page::load_error
3703 .Get(IsSubframe() ? "frame"_ns : "top"_ns,
3704 mozilla::dom::LoadErrorToTelemetryLabel(aError))
3705 .Add();
3706
3707 // Test if the error needs to be formatted
3708 if (!messageStr.IsEmpty()) {
3709 // already obtained message
3710 } else {
3711 if (addHostPort) {
3712 // Build up the host:port string.
3713 nsAutoCString hostport;
3714 if (aURI) {
3715 aURI->GetHostPort(hostport);
3716 } else {
3717 hostport.Assign('?');
3718 }
3719 CopyUTF8toUTF16(hostport, *formatStrs.AppendElement());
3720 }
3721
3722 nsAutoCString spec;
3723 rv = NS_ERROR_NOT_AVAILABLE;
3724 auto& nextFormatStr = *formatStrs.AppendElement();
3725 if (aURI) {
3726 // displaying "file://" is aesthetically unpleasing and could even be
3727 // confusing to the user
3728 if (aURI->SchemeIs("file")) {
3729 aURI->GetPathQueryRef(spec);
3730 } else {
3731 aURI->GetSpec(spec);
3732 }
3733
3734 nsCOMPtr<nsITextToSubURI> textToSubURI(
3735 do_GetService(NS_ITEXTTOSUBURI_CONTRACTID"@mozilla.org/intl/texttosuburi;1", &rv));
3736 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
3737 rv = textToSubURI->UnEscapeURIForUI(spec, nextFormatStr);
3738 }
3739 } else {
3740 spec.Assign('?');
3741 }
3742 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3743 CopyUTF8toUTF16(spec, nextFormatStr);
3744 }
3745 rv = NS_OK;
3746
3747 nsAutoString str;
3748 rv =
3749 stringBundle->FormatStringFromName(errorDescriptionID, formatStrs, str);
3750 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 3750); return rv; } } while (false)
;
3751 messageStr.Assign(str);
3752 }
3753
3754 // Display the error as a page or an alert prompt
3755 NS_ENSURE_FALSE(messageStr.IsEmpty(), NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(!(messageStr.IsEmpty()))), 0)
)) { NS_DebugBreak(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "!(messageStr.IsEmpty())"
") failed", nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 3755); return NS_ERROR_FAILURE; } } while (false)
;
3756
3757 if ((NS_ERROR_NET_INTERRUPT == aError || NS_ERROR_NET_RESET == aError) &&
3758 aURI->SchemeIs("https")) {
3759 // Maybe TLS intolerant. Treat this as an SSL error.
3760 error = "nssFailure2";
3761 }
3762
3763 if (mBrowsingContext->GetUseErrorPages()) {
3764 // Display an error page
3765 nsresult loadedPage =
3766 LoadErrorPage(aURI, aURL, errorPage.get(), error, messageStr.get(),
3767 cssClass.get(), aFailedChannel);
3768 *aDisplayedErrorPage = NS_SUCCEEDED(loadedPage)((bool)(__builtin_expect(!!(!NS_FAILED_impl(loadedPage)), 1))
)
;
3769 } else {
3770 // The prompter reqires that our private window has a document (or it
3771 // asserts). Satisfy that assertion now since GetDoc will force
3772 // creation of one if it hasn't already been created.
3773 if (mScriptGlobal) {
3774 Unused << mScriptGlobal->GetDoc();
3775 }
3776
3777 // Display a message box
3778 prompter->Alert(nullptr, messageStr.get());
3779 }
3780
3781 return NS_OK;
3782}
3783
3784#define PREF_SAFEBROWSING_ALLOWOVERRIDE"browser.safebrowsing.allowOverride" "browser.safebrowsing.allowOverride"
3785
3786nsresult nsDocShell::LoadErrorPage(nsIURI* aURI, const char16_t* aURL,
3787 const char* aErrorPage,
3788 const char* aErrorType,
3789 const char16_t* aDescription,
3790 const char* aCSSClass,
3791 nsIChannel* aFailedChannel) {
3792 if (mIsBeingDestroyed) {
3793 return NS_ERROR_NOT_AVAILABLE;
3794 }
3795
3796#if defined(DEBUG1)
3797 if (MOZ_LOG_TEST(gDocShellLog, LogLevel::Debug)(__builtin_expect(!!(mozilla::detail::log_test(gDocShellLog, LogLevel
::Debug)), 0))
) {
3798 nsAutoCString chanName;
3799 if (aFailedChannel) {
3800 aFailedChannel->GetName(chanName);
3801 } else {
3802 chanName.AssignLiteral("<no channel>");
3803 }
3804
3805 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)
3806 ("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)
3807 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)
3808 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)
;
3809 }
3810#endif
3811
3812 nsAutoCString url;
3813 if (aURI) {
3814 nsresult rv = aURI->GetSpec(url);
3815 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 3815); return rv; } } while (false)
;
3816 } else if (aURL) {
3817 CopyUTF16toUTF8(MakeStringSpan(aURL), url);
3818 } else {
3819 return NS_ERROR_INVALID_POINTER;
3820 }
3821
3822 // Create a URL to pass all the error information through to the page.
3823
3824#undef SAFE_ESCAPE
3825#define SAFE_ESCAPE(output, input, params)if (NS_warn_if_impl(!NS_Escape(input, output, params), "!NS_Escape(input, output, params)"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 3825)) {
return NS_ERROR_OUT_OF_MEMORY; }
\
3826 if (NS_WARN_IF(!NS_Escape(input, output, params))NS_warn_if_impl(!NS_Escape(input, output, params), "!NS_Escape(input, output, params)"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 3826)
) { \
3827 return NS_ERROR_OUT_OF_MEMORY; \
3828 }
3829
3830 nsCString escapedUrl, escapedError, escapedDescription, escapedCSSClass;
3831 SAFE_ESCAPE(escapedUrl, url, url_Path)if (NS_warn_if_impl(!NS_Escape(url, escapedUrl, url_Path), "!NS_Escape(url, escapedUrl, url_Path)"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 3831)) {
return NS_ERROR_OUT_OF_MEMORY; }
;
3832 SAFE_ESCAPE(escapedError, nsDependentCString(aErrorType), url_Path)if (NS_warn_if_impl(!NS_Escape(nsDependentCString(aErrorType)
, escapedError, url_Path), "!NS_Escape(nsDependentCString(aErrorType), escapedError, url_Path)"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 3832)) {
return NS_ERROR_OUT_OF_MEMORY; }
;
3833 SAFE_ESCAPE(escapedDescription, NS_ConvertUTF16toUTF8(aDescription),if (NS_warn_if_impl(!NS_Escape(NS_ConvertUTF16toUTF8(aDescription
), escapedDescription, url_Path), "!NS_Escape(NS_ConvertUTF16toUTF8(aDescription), escapedDescription, url_Path)"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 3834)) {
return NS_ERROR_OUT_OF_MEMORY; }
3834 url_Path)if (NS_warn_if_impl(!NS_Escape(NS_ConvertUTF16toUTF8(aDescription
), escapedDescription, url_Path), "!NS_Escape(NS_ConvertUTF16toUTF8(aDescription), escapedDescription, url_Path)"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 3834)) {
return NS_ERROR_OUT_OF_MEMORY; }
;
3835 if (aCSSClass) {
3836 nsCString cssClass(aCSSClass);
3837 SAFE_ESCAPE(escapedCSSClass, cssClass, url_Path)if (NS_warn_if_impl(!NS_Escape(cssClass, escapedCSSClass, url_Path
), "!NS_Escape(cssClass, escapedCSSClass, url_Path)", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 3837)) { return NS_ERROR_OUT_OF_MEMORY; }
;
3838 }
3839 nsCString errorPageUrl("about:");
3840 errorPageUrl.AppendASCII(aErrorPage);
3841 errorPageUrl.AppendLiteral("?e=");
3842
3843 errorPageUrl.AppendASCII(escapedError.get());
3844 errorPageUrl.AppendLiteral("&u=");
3845 errorPageUrl.AppendASCII(escapedUrl.get());
3846 if ((strcmp(aErrorPage, "blocked") == 0) &&
3847 Preferences::GetBool(PREF_SAFEBROWSING_ALLOWOVERRIDE"browser.safebrowsing.allowOverride", true)) {
3848 errorPageUrl.AppendLiteral("&o=1");
3849 }
3850 if (!escapedCSSClass.IsEmpty()) {
3851 errorPageUrl.AppendLiteral("&s=");
3852 errorPageUrl.AppendASCII(escapedCSSClass.get());
3853 }
3854 errorPageUrl.AppendLiteral("&c=UTF-8");
3855
3856 nsCOMPtr<nsICaptivePortalService> cps = do_GetService(NS_CAPTIVEPORTAL_CID{ 0xbdbe0555, 0xfc3d, 0x4f7b, {0x92, 0x05, 0xc3, 0x09, 0xce, 0xb2
, 0xd6, 0x41}}
);
3857 int32_t cpsState;
3858 if (cps && NS_SUCCEEDED(cps->GetState(&cpsState))((bool)(__builtin_expect(!!(!NS_FAILED_impl(cps->GetState(
&cpsState))), 1)))
&&
3859 cpsState == nsICaptivePortalService::LOCKED_PORTAL) {
3860 errorPageUrl.AppendLiteral("&captive=true");
3861 }
3862
3863 errorPageUrl.AppendLiteral("&d=");
3864 errorPageUrl.AppendASCII(escapedDescription.get());
3865
3866 nsCOMPtr<nsIURI> errorPageURI;
3867 nsresult rv = NS_NewURI(getter_AddRefs(errorPageURI), errorPageUrl);
3868 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 3868); return rv; } } while (false)
;
3869
3870 return LoadErrorPage(errorPageURI, aURI, aFailedChannel);
3871}
3872
3873nsresult nsDocShell::LoadErrorPage(nsIURI* aErrorURI, nsIURI* aFailedURI,
3874 nsIChannel* aFailedChannel) {
3875 mFailedChannel = aFailedChannel;
3876 mFailedURI = aFailedURI;
3877 mFailedLoadType = mLoadType;
3878
3879 if (mLSHE) {
3880 // Abandon mLSHE's BFCache entry and create a new one. This way, if
3881 // we go back or forward to another SHEntry with the same doc
3882 // identifier, the error page won't persist.
3883 mLSHE->AbandonBFCacheEntry();
3884 }
3885
3886 RefPtr<nsDocShellLoadState> loadState = new nsDocShellLoadState(aErrorURI);
3887 loadState->SetTriggeringPrincipal(nsContentUtils::GetSystemPrincipal());
3888 if (mBrowsingContext) {
3889 loadState->SetTriggeringSandboxFlags(mBrowsingContext->GetSandboxFlags());
3890 loadState->SetTriggeringWindowId(
3891 mBrowsingContext->GetCurrentInnerWindowId());
3892 nsPIDOMWindowInner* innerWin = mScriptGlobal->GetCurrentInnerWindow();
3893 if (innerWin) {
3894 loadState->SetTriggeringStorageAccess(innerWin->UsingStorageAccess());
3895 }
3896 }
3897 loadState->SetLoadType(LOAD_ERROR_PAGE);
3898 loadState->SetFirstParty(true);
3899 loadState->SetSourceBrowsingContext(mBrowsingContext);
3900 if (mozilla::SessionHistoryInParent() && mLoadingEntry) {
3901 // We keep the loading entry for the load that failed here. If the user
3902 // reloads we want to try to reload the original load, not the error page.
3903 loadState->SetLoadingSessionHistoryInfo(
3904 MakeUnique<LoadingSessionHistoryInfo>(*mLoadingEntry));
3905 }
3906 return InternalLoad(loadState);
3907}
3908
3909MOZ_CAN_RUN_SCRIPT_BOUNDARY NS_IMETHODIMPnsresult
3910nsDocShell::Reload(uint32_t aReloadFlags) {
3911 return ReloadNavigable(Nothing(), aReloadFlags, nullptr,
3912 UserNavigationInvolvement::BrowserUI);
3913}
3914
3915// https://html.spec.whatwg.org/#reload
3916// To reload a navigable navigable given an optional serialized state-or-null
3917// navigationAPIState (default null) and an optional user navigation
3918// involvement userInvolvement (default "none"):
3919nsresult nsDocShell::ReloadNavigable(
3920 mozilla::Maybe<NotNull<JSContext*>> aCx, uint32_t aReloadFlags,
3921 nsIStructuredCloneContainer* aNavigationAPIState,
3922 UserNavigationInvolvement aUserInvolvement) {
3923 if (!IsNavigationAllowed()) {
3924 return NS_OK; // JS may not handle returning of an error code
3925 }
3926
3927 NS_ASSERTION(((aReloadFlags & INTERNAL_LOAD_FLAGS_LOADURI_SETUP_FLAGS) == 0),do { if (!(((aReloadFlags & INTERNAL_LOAD_FLAGS_LOADURI_SETUP_FLAGS
) == 0))) { NS_DebugBreak(NS_DEBUG_ASSERTION, "Reload command not updated to use load flags!"
, "((aReloadFlags & INTERNAL_LOAD_FLAGS_LOADURI_SETUP_FLAGS) == 0)"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 3928); MOZ_PretendNoReturn
(); } } while (0)
3928 "Reload command not updated to use load flags!")do { if (!(((aReloadFlags & INTERNAL_LOAD_FLAGS_LOADURI_SETUP_FLAGS
) == 0))) { NS_DebugBreak(NS_DEBUG_ASSERTION, "Reload command not updated to use load flags!"
, "((aReloadFlags & INTERNAL_LOAD_FLAGS_LOADURI_SETUP_FLAGS) == 0)"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 3928); MOZ_PretendNoReturn
(); } } while (0)
;
3929 NS_ASSERTION((aReloadFlags & EXTRA_LOAD_FLAGS) == 0,do { if (!((aReloadFlags & (nsIWebNavigation::LOAD_FLAGS_FROM_EXTERNAL
| nsIWebNavigation::LOAD_FLAGS_FIRST_LOAD | nsIWebNavigation
::LOAD_FLAGS_ALLOW_POPUPS | 0xffff0000)) == 0)) { NS_DebugBreak
(NS_DEBUG_ASSERTION, "Don't pass these flags to Reload", "(aReloadFlags & EXTRA_LOAD_FLAGS) == 0"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 3930); MOZ_PretendNoReturn
(); } } while (0)
3930 "Don't pass these flags to Reload")do { if (!((aReloadFlags & (nsIWebNavigation::LOAD_FLAGS_FROM_EXTERNAL
| nsIWebNavigation::LOAD_FLAGS_FIRST_LOAD | nsIWebNavigation
::LOAD_FLAGS_ALLOW_POPUPS | 0xffff0000)) == 0)) { NS_DebugBreak
(NS_DEBUG_ASSERTION, "Don't pass these flags to Reload", "(aReloadFlags & EXTRA_LOAD_FLAGS) == 0"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 3930); MOZ_PretendNoReturn
(); } } while (0)
;
3931
3932 uint32_t loadType = MAKE_LOAD_TYPE(LOAD_RELOAD_NORMAL, aReloadFlags)((LOAD_RELOAD_NORMAL) | ((aReloadFlags) << 16));
3933 NS_ENSURE_TRUE(IsValidLoadType(loadType), NS_ERROR_INVALID_ARG)do { if ((__builtin_expect(!!(!(IsValidLoadType(loadType))), 0
))) { NS_DebugBreak(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "IsValidLoadType(loadType)"
") failed", nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 3933); return NS_ERROR_INVALID_ARG; } } while (false)
;
3934 NS_ENSURE_TRUE(do { if ((__builtin_expect(!!(!(aUserInvolvement == UserNavigationInvolvement
::BrowserUI || aCx)), 0))) { NS_DebugBreak(NS_DEBUG_WARNING, "NS_ENSURE_TRUE("
"aUserInvolvement == UserNavigationInvolvement::BrowserUI || aCx"
") failed", nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 3936); return NS_ERROR_INVALID_ARG; } } while (false)
3935 aUserInvolvement == UserNavigationInvolvement::BrowserUI || aCx,do { if ((__builtin_expect(!!(!(aUserInvolvement == UserNavigationInvolvement
::BrowserUI || aCx)), 0))) { NS_DebugBreak(NS_DEBUG_WARNING, "NS_ENSURE_TRUE("
"aUserInvolvement == UserNavigationInvolvement::BrowserUI || aCx"
") failed", nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 3936); return NS_ERROR_INVALID_ARG; } } while (false)
3936 NS_ERROR_INVALID_ARG)do { if ((__builtin_expect(!!(!(aUserInvolvement == UserNavigationInvolvement
::BrowserUI || aCx)), 0))) { NS_DebugBreak(NS_DEBUG_WARNING, "NS_ENSURE_TRUE("
"aUserInvolvement == UserNavigationInvolvement::BrowserUI || aCx"
") failed", nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 3936); return NS_ERROR_INVALID_ARG; } } while (false)
;
3937
3938 RefPtr<nsDocShell> docShell(this);
3939
3940 // 1. If userInvolvement is not "browser UI", then:
3941 if (aUserInvolvement != UserNavigationInvolvement::BrowserUI) {
3942 // 1.1 Let navigation be navigable's active window's navigation API.
3943 nsPIDOMWindowOuter* windowOuter = GetWindow();
3944 MOZ_DIAGNOSTIC_ASSERT(windowOuter)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(windowOuter)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(windowOuter))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("windowOuter", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 3944); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "windowOuter"
")"); do { MOZ_CrashSequence(__null, 3944); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3945 nsPIDOMWindowInner* windowInner = windowOuter->GetCurrentInnerWindow();
3946 MOZ_DIAGNOSTIC_ASSERT(windowInner)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(windowInner)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(windowInner))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("windowInner", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 3946); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "windowInner"
")"); do { MOZ_CrashSequence(__null, 3946); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3947 RefPtr navigation = windowInner->Navigation();
3948
3949 // 1.2 Let destinationNavigationAPIState be navigable's active session
3950 // history entry's navigation API state.
3951 // 1.3 If navigationAPIState is not null, then set
3952 // destinationNavigationAPIState to navigationAPIState.
3953 RefPtr<nsIStructuredCloneContainer> destinationNavigationAPIState =
3954 aNavigationAPIState;
3955 if (!destinationNavigationAPIState) {
3956 destinationNavigationAPIState =
3957 mActiveEntry ? mActiveEntry->GetNavigationState() : nullptr;
3958 }
3959
3960 // 1.4 Let continue be the result of firing a push/replace/reload navigate
3961 // event at navigation with navigationType set to "reload",
3962 // isSameDocument set to false, userInvolvement set to userInvolvement,
3963 // destinationURL set to navigable's active session history entry's URL,
3964 // and navigationAPIState set to destinationNavigationAPIState.
3965 // 1.5 If continue is false, then return.
3966 RefPtr destinationURL = mActiveEntry ? mActiveEntry->GetURI() : nullptr;
3967 if (navigation &&
3968 !navigation->FirePushReplaceReloadNavigateEvent(
3969 *aCx, NavigationType::Reload, destinationURL,
3970 /* aIsSameDocument */ false, /* aIsSync */ false,
3971 Some(aUserInvolvement),
3972 /* aSourceElement*/ nullptr, /* aFormDataEntryList */ nullptr,
3973 destinationNavigationAPIState,
3974 /* aClassiCHistoryAPIState */ nullptr)) {
3975 return NS_OK;
3976 }
3977 }
3978
3979 // The following steps are implemented by the remainder of ReloadNavigable.
3980
3981 // Send notifications to the HistoryListener if any, about the impending
3982 // reload
3983 RefPtr<ChildSHistory> rootSH = GetRootSessionHistory();
3984 if (mozilla::SessionHistoryInParent()) {
3985 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)
;
3986 bool forceReload = IsForceReloadType(loadType);
3987 if (!XRE_IsParentProcess()) {
3988 ++mPendingReloadCount;
3989 nsCOMPtr<nsIDocumentViewer> viewer(mDocumentViewer);
3990 NS_ENSURE_STATE(viewer)do { if ((__builtin_expect(!!(!(viewer)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "viewer" ") failed", nullptr
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 3990); return
NS_ERROR_UNEXPECTED; } } while (false)
;
3991
3992 bool okToUnload = true;
3993 MOZ_TRY(viewer->PermitUnload(&okToUnload))__extension__({ auto mozTryVarTempResult = ::mozilla::ToResult
(viewer->PermitUnload(&okToUnload)); if ((__builtin_expect
(!!(mozTryVarTempResult.isErr()), 0))) { return mozTryVarTempResult
.propagateErr(); } mozTryVarTempResult.unwrap(); })
;
3994 if (!okToUnload) {
3995 return NS_OK;
3996 }
3997
3998 RefPtr<Document> doc(GetDocument());
3999 RefPtr<BrowsingContext> browsingContext(mBrowsingContext);
4000 nsCOMPtr<nsIURI> currentURI(mCurrentURI);
4001 nsCOMPtr<nsIReferrerInfo> referrerInfo(mReferrerInfo);
4002 RefPtr<StopDetector> stopDetector = new StopDetector();
4003 nsCOMPtr<nsILoadGroup> loadGroup;
4004 GetLoadGroup(getter_AddRefs(loadGroup));
4005 if (loadGroup) {
4006 // loadGroup may be null in theory. In that case stopDetector just
4007 // doesn't do anything.
4008 loadGroup->AddRequest(stopDetector, nullptr);
4009 }
4010
4011 ContentChild::GetSingleton()->SendNotifyOnHistoryReload(
4012 mBrowsingContext, forceReload,
4013 [docShell, doc, loadType, browsingContext, currentURI, referrerInfo,
4014 loadGroup, stopDetector](
4015 std::tuple<bool, Maybe<NotNull<RefPtr<nsDocShellLoadState>>>,
4016 Maybe<bool>>&& aResult) {
4017 auto scopeExit = MakeScopeExit([loadGroup, stopDetector]() {
4018 if (loadGroup) {
4019 loadGroup->RemoveRequest(stopDetector, nullptr, NS_OK);
4020 }
4021 });
4022
4023 // Decrease mPendingReloadCount before any other early returns!
4024 if (--(docShell->mPendingReloadCount) > 0) {
4025 return;
4026 }
4027
4028 if (stopDetector->Canceled()) {
4029 return;
4030 }
4031 bool canReload;
4032 Maybe<NotNull<RefPtr<nsDocShellLoadState>>> loadState;
4033 Maybe<bool> reloadingActiveEntry;
4034
4035 std::tie(canReload, loadState, reloadingActiveEntry) = aResult;
4036
4037 if (!canReload) {
4038 return;
4039 }
4040
4041 if (loadState.isSome()) {
4042 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)
4043 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)
4044 ("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)
;
4045 loadState.ref()->SetNotifiedBeforeUnloadListeners(true);
4046 docShell->LoadHistoryEntry(loadState.ref(), loadType,
4047 reloadingActiveEntry.ref());
4048 } else {
4049 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)
4050 ("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)
;
4051 ReloadDocument(docShell, doc, loadType, browsingContext,
4052 currentURI, referrerInfo,
4053 /* aNotifiedBeforeUnloadListeners */ true);
4054 }
4055 },
4056 [](mozilla::ipc::ResponseRejectReason) {});
4057 } else {
4058 // Parent process
4059 bool canReload = false;
4060 Maybe<NotNull<RefPtr<nsDocShellLoadState>>> loadState;
4061 Maybe<bool> reloadingActiveEntry;
4062 if (!mBrowsingContext->IsDiscarded()) {
4063 mBrowsingContext->Canonical()->NotifyOnHistoryReload(
4064 forceReload, canReload, loadState, reloadingActiveEntry);
4065 }
4066 if (canReload) {
4067 if (loadState.isSome()) {
4068 MOZ_LOG(gSHLog, LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = gSHLog; if
((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "nsDocShell %p Reload - LoadHistoryEntry",
this); } } while (0)
4069 ("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)
;
4070 LoadHistoryEntry(loadState.ref(), loadType,
4071 reloadingActiveEntry.ref());
4072 } else {
4073 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)
4074 ("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)
;
4075 RefPtr<Document> doc = GetDocument();
4076 RefPtr<BrowsingContext> bc = mBrowsingContext;
4077 nsCOMPtr<nsIURI> currentURI = mCurrentURI;
4078 nsCOMPtr<nsIReferrerInfo> referrerInfo = mReferrerInfo;
4079 ReloadDocument(this, doc, loadType, bc, currentURI, referrerInfo);
4080 }
4081 }
4082 }
4083 return NS_OK;
4084 }
4085
4086 bool canReload = true;
4087 if (rootSH) {
4088 rootSH->LegacySHistory()->NotifyOnHistoryReload(&canReload);
4089 }
4090
4091 if (!canReload) {
4092 return NS_OK;
4093 }
4094
4095 /* If you change this part of code, make sure bug 45297 does not re-occur */
4096 if (mOSHE) {
4097 nsCOMPtr<nsISHEntry> oshe = mOSHE;
4098 return LoadHistoryEntry(
4099 oshe, loadType,
4100 aReloadFlags & nsIWebNavigation::LOAD_FLAGS_USER_ACTIVATION);
4101 }
4102
4103 if (mLSHE) { // In case a reload happened before the current load is done
4104 nsCOMPtr<nsISHEntry> lshe = mLSHE;
4105 return LoadHistoryEntry(
4106 lshe, loadType,
4107 aReloadFlags & nsIWebNavigation::LOAD_FLAGS_USER_ACTIVATION);
4108 }
4109
4110 RefPtr<Document> doc = GetDocument();
4111 RefPtr<BrowsingContext> bc = mBrowsingContext;
4112 nsCOMPtr<nsIURI> currentURI = mCurrentURI;
4113 nsCOMPtr<nsIReferrerInfo> referrerInfo = mReferrerInfo;
4114 return ReloadDocument(this, doc, loadType, bc, currentURI, referrerInfo);
4115}
4116
4117/* static */
4118nsresult nsDocShell::ReloadDocument(nsDocShell* aDocShell, Document* aDocument,
4119 uint32_t aLoadType,
4120 BrowsingContext* aBrowsingContext,
4121 nsIURI* aCurrentURI,
4122 nsIReferrerInfo* aReferrerInfo,
4123 bool aNotifiedBeforeUnloadListeners) {
4124 if (!aDocument) {
4125 return NS_OK;
4126 }
4127
4128 // Do not inherit owner from document
4129 uint32_t flags = INTERNAL_LOAD_FLAGS_NONE;
4130 nsAutoString srcdoc;
4131 nsIURI* baseURI = nullptr;
4132 nsCOMPtr<nsIURI> originalURI;
4133 nsCOMPtr<nsIURI> resultPrincipalURI;
4134 bool loadReplace = false;
4135
4136 nsIPrincipal* triggeringPrincipal = aDocument->NodePrincipal();
4137 nsCOMPtr<nsIContentSecurityPolicy> csp = aDocument->GetCsp();
4138 uint32_t triggeringSandboxFlags = aDocument->GetSandboxFlags();
4139 uint64_t triggeringWindowId = aDocument->InnerWindowID();
4140 bool triggeringStorageAccess = aDocument->UsingStorageAccess();
4141 net::ClassificationFlags triggeringClassificationFlags =
4142 aDocument->GetScriptTrackingFlags();
4143
4144 nsAutoString contentTypeHint;
4145 aDocument->GetContentType(contentTypeHint);
4146
4147 if (aDocument->IsSrcdocDocument()) {
4148 aDocument->GetSrcdocData(srcdoc);
4149 flags |= INTERNAL_LOAD_FLAGS_IS_SRCDOC;
4150 baseURI = aDocument->GetBaseURI();
4151 } else {
4152 srcdoc = VoidString();
4153 }
4154 nsCOMPtr<nsIChannel> chan = aDocument->GetChannel();
4155 if (chan) {
4156 uint32_t loadFlags;
4157 chan->GetLoadFlags(&loadFlags);
4158 loadReplace = loadFlags & nsIChannel::LOAD_REPLACE;
4159 nsCOMPtr<nsIHttpChannel> httpChan(do_QueryInterface(chan));
4160 if (httpChan) {
4161 httpChan->GetOriginalURI(getter_AddRefs(originalURI));
4162 }
4163
4164 nsCOMPtr<nsILoadInfo> loadInfo = chan->LoadInfo();
4165 loadInfo->GetResultPrincipalURI(getter_AddRefs(resultPrincipalURI));
4166 }
4167
4168 if (!triggeringPrincipal) {
4169 MOZ_ASSERT(false, "Reload needs a valid triggeringPrincipal")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "Reload needs a valid triggeringPrincipal"
")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 4169
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") (" "Reload needs a valid triggeringPrincipal"
")"); do { MOZ_CrashSequence(__null, 4169); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4170 return NS_ERROR_FAILURE;
4171 }
4172
4173 // Stack variables to ensure changes to the member variables don't affect to
4174 // the call.
4175 nsCOMPtr<nsIURI> currentURI = aCurrentURI;
4176
4177 // Reload always rewrites result principal URI.
4178 Maybe<nsCOMPtr<nsIURI>> emplacedResultPrincipalURI;
4179 emplacedResultPrincipalURI.emplace(std::move(resultPrincipalURI));
4180
4181 RefPtr<WindowContext> context = aBrowsingContext->GetCurrentWindowContext();
4182 RefPtr<nsDocShellLoadState> loadState = new nsDocShellLoadState(currentURI);
4183 loadState->SetReferrerInfo(aReferrerInfo);
4184 loadState->SetOriginalURI(originalURI);
4185 loadState->SetMaybeResultPrincipalURI(emplacedResultPrincipalURI);
4186 loadState->SetLoadReplace(loadReplace);
4187 loadState->SetTriggeringPrincipal(triggeringPrincipal);
4188 loadState->SetTriggeringSandboxFlags(triggeringSandboxFlags);
4189 loadState->SetTriggeringWindowId(triggeringWindowId);
4190 loadState->SetTriggeringStorageAccess(triggeringStorageAccess);
4191 loadState->SetTriggeringClassificationFlags(triggeringClassificationFlags);
4192 loadState->SetPrincipalToInherit(triggeringPrincipal);
4193 loadState->SetCsp(csp);
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 RefPtr kungFuDeathGrip = this;
4216 if (RefPtr<Document> doc = GetDocument(); doc && !doc->ShouldIgnoreOpens()) {
4217 SetOngoingNavigation(Nothing());
4218 }
4219
4220 // Revoke any pending event related to content viewer restoration
4221 mRestorePresentationEvent.Revoke();
4222
4223 if (mLoadType == LOAD_ERROR_PAGE) {
4224 if (mLSHE) {
4225 // Since error page loads never unset mLSHE, do so now
4226 SetHistoryEntryAndUpdateBC(Some(nullptr), Some<nsISHEntry*>(mLSHE));
4227 }
4228 mActiveEntryIsLoadingFromSessionHistory = false;
4229
4230 mFailedChannel = nullptr;
4231 mFailedURI = nullptr;
4232 }
4233
4234 if (nsIWebNavigation::STOP_CONTENT & aStopFlags) {
4235 // Stop the document loading and animations
4236 if (mDocumentViewer) {
4237 nsCOMPtr<nsIDocumentViewer> viewer = mDocumentViewer;
4238 viewer->Stop();
4239 }
4240 } else if (nsIWebNavigation::STOP_NETWORK & aStopFlags) {
4241 // Stop the document loading only
4242 if (mDocumentViewer) {
4243 RefPtr<Document> doc = mDocumentViewer->GetDocument();
4244 if (doc) {
4245 doc->StopDocumentLoad();
4246 }
4247 }
4248 }
4249
4250 if (nsIWebNavigation::STOP_NETWORK & aStopFlags) {
4251 // Suspend any timers that were set for this loader. We'll clear
4252 // them out for good in CreateDocumentViewer.
4253 if (mRefreshURIList) {
4254 SuspendRefreshURIs();
4255 mSavedRefreshURIList.swap(mRefreshURIList);
4256 mRefreshURIList = nullptr;
4257 }
4258
4259 // XXXbz We could also pass |this| to nsIURILoader::Stop. That will
4260 // just call Stop() on us as an nsIDocumentLoader... We need fewer
4261 // redundant apis!
4262 Stop();
4263
4264 // Clear out mChannelToDisconnectOnPageHide. This page won't go in the
4265 // BFCache now, and the Stop above will have removed the DocumentChannel
4266 // from the loadgroup.
4267 mChannelToDisconnectOnPageHide = 0;
4268 }
4269
4270 for (auto* child : mChildList.ForwardRange()) {
4271 nsCOMPtr<nsIWebNavigation> shellAsNav(do_QueryObject(child));
4272 if (shellAsNav) {
4273 shellAsNav->Stop(aStopFlags);
4274 }
4275 }
4276
4277 return NS_OK;
4278}
4279
4280NS_IMETHODIMPnsresult
4281nsDocShell::GetDocument(Document** aDocument) {
4282 NS_ENSURE_ARG_POINTER(aDocument)do { if ((__builtin_expect(!!(!(aDocument)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aDocument" ") failed", nullptr
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 4282); return
NS_ERROR_INVALID_POINTER; } } while (false)
;
4283 NS_ENSURE_SUCCESS(EnsureDocumentViewer(), NS_ERROR_FAILURE)do { nsresult __rv = EnsureDocumentViewer(); if (((bool)(__builtin_expect
(!!(NS_FAILED_impl(__rv)), 0)))) { const char* name = mozilla
::GetStaticErrorName(__rv); mozilla::SmprintfPointer msg = mozilla
::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%"
"X" "%s%s%s", "EnsureDocumentViewer()", "NS_ERROR_FAILURE", static_cast
<uint32_t>(__rv), name ? " (" : "", name ? name : "", name
? ")" : ""); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 4283); return
NS_ERROR_FAILURE; } } while (false)
;
4284
4285 RefPtr<Document> doc = mDocumentViewer->GetDocument();
4286 if (!doc) {
4287 return NS_ERROR_NOT_AVAILABLE;
4288 }
4289
4290 doc.forget(aDocument);
4291 return NS_OK;
4292}
4293
4294NS_IMETHODIMPnsresult
4295nsDocShell::GetCurrentURI(nsIURI** aURI) {
4296 NS_ENSURE_ARG_POINTER(aURI)do { if ((__builtin_expect(!!(!(aURI)), 0))) { NS_DebugBreak(
NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aURI" ") failed", nullptr
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 4296); return
NS_ERROR_INVALID_POINTER; } } while (false)
;
4297
4298 nsCOMPtr<nsIURI> uri = mCurrentURI;
4299 uri.forget(aURI);
4300 return NS_OK;
4301}
4302
4303NS_IMETHODIMPnsresult
4304nsDocShell::GetSessionHistoryXPCOM(nsISupports** aSessionHistory) {
4305 NS_ENSURE_ARG_POINTER(aSessionHistory)do { if ((__builtin_expect(!!(!(aSessionHistory)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aSessionHistory" ") failed"
, nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 4305); return NS_ERROR_INVALID_POINTER; } } while (false)
;
4306 RefPtr<ChildSHistory> shistory = GetSessionHistory();
4307 shistory.forget(aSessionHistory);
4308 return NS_OK;
4309}
4310
4311//*****************************************************************************
4312// nsDocShell::nsIWebPageDescriptor
4313//*****************************************************************************
4314
4315NS_IMETHODIMPnsresult
4316nsDocShell::LoadPageAsViewSource(nsIDocShell* aOtherDocShell,
4317 const nsAString& aURI) {
4318 if (!aOtherDocShell) {
4319 return NS_ERROR_INVALID_POINTER;
4320 }
4321 nsCOMPtr<nsIURI> newURI;
4322 nsresult rv = NS_NewURI(getter_AddRefs(newURI), aURI);
4323 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
4324 return rv;
4325 }
4326
4327 RefPtr<nsDocShellLoadState> loadState;
4328 uint32_t cacheKey;
4329 auto* otherDocShell = nsDocShell::Cast(aOtherDocShell);
4330 if (mozilla::SessionHistoryInParent()) {
4331 loadState = new nsDocShellLoadState(newURI);
4332 if (!otherDocShell->FillLoadStateFromCurrentEntry(*loadState)) {
4333 return NS_ERROR_INVALID_POINTER;
4334 }
4335 cacheKey = otherDocShell->GetCacheKeyFromCurrentEntry().valueOr(0);
4336 } else {
4337 nsCOMPtr<nsISHEntry> entry;
4338 bool isOriginalSHE;
4339 otherDocShell->GetCurrentSHEntry(getter_AddRefs(entry), &isOriginalSHE);
4340 if (!entry) {
4341 return NS_ERROR_INVALID_POINTER;
4342 }
4343 rv = entry->CreateLoadInfo(getter_AddRefs(loadState));
4344 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 4344); return rv; } } while (false)
;
4345 entry->GetCacheKey(&cacheKey);
4346 loadState->SetURI(newURI);
4347 loadState->SetSHEntry(nullptr);
4348 }
4349
4350 // We're doing a load of the page, via an API that
4351 // is only exposed to system code. The triggering principal for this load
4352 // should be the system principal.
4353 loadState->SetTriggeringPrincipal(nsContentUtils::GetSystemPrincipal());
4354 loadState->SetOriginalURI(nullptr);
4355 loadState->SetResultPrincipalURI(nullptr);
4356
4357 return InternalLoad(loadState, Some(cacheKey));
4358}
4359
4360NS_IMETHODIMPnsresult
4361nsDocShell::GetCurrentDescriptor(nsISupports** aPageDescriptor) {
4362 MOZ_ASSERT(aPageDescriptor, "Null out param?")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aPageDescriptor)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aPageDescriptor))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("aPageDescriptor"
" (" "Null out param?" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 4362); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPageDescriptor"
") (" "Null out param?" ")"); do { MOZ_CrashSequence(__null,
4362); __attribute__((nomerge)) ::abort(); } while (false); }
} while (false)
;
4363
4364 *aPageDescriptor = nullptr;
4365
4366 nsISHEntry* src = mOSHE ? mOSHE : mLSHE;
4367 if (src) {
4368 nsCOMPtr<nsISHEntry> dest;
4369
4370 nsresult rv = src->Clone(getter_AddRefs(dest));
4371 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
4372 return rv;
4373 }
4374
4375 // null out inappropriate cloned attributes...
4376 dest->SetParent(nullptr);
4377 dest->SetIsSubFrame(false);
4378
4379 return CallQueryInterface(dest, aPageDescriptor);
4380 }
4381
4382 return NS_ERROR_NOT_AVAILABLE;
4383}
4384
4385already_AddRefed<nsIInputStream> nsDocShell::GetPostDataFromCurrentEntry()
4386 const {
4387 nsCOMPtr<nsIInputStream> postData;
4388 if (mozilla::SessionHistoryInParent()) {
4389 if (mActiveEntry) {
4390 postData = mActiveEntry->GetPostData();
4391 } else if (mLoadingEntry) {
4392 postData = mLoadingEntry->mInfo.GetPostData();
4393 }
4394 } else {
4395 if (mOSHE) {
4396 postData = mOSHE->GetPostData();
4397 } else if (mLSHE) {
4398 postData = mLSHE->GetPostData();
4399 }
4400 }
4401
4402 return postData.forget();
4403}
4404
4405Maybe<uint32_t> nsDocShell::GetCacheKeyFromCurrentEntry() const {
4406 if (mozilla::SessionHistoryInParent()) {
4407 if (mActiveEntry) {
4408 return Some(mActiveEntry->GetCacheKey());
4409 }
4410
4411 if (mLoadingEntry) {
4412 return Some(mLoadingEntry->mInfo.GetCacheKey());
4413 }
4414 } else {
4415 if (mOSHE) {
4416 return Some(mOSHE->GetCacheKey());
4417 }
4418
4419 if (mLSHE) {
4420 return Some(mLSHE->GetCacheKey());
4421 }
4422 }
4423
4424 return Nothing();
4425}
4426
4427bool nsDocShell::FillLoadStateFromCurrentEntry(
4428 nsDocShellLoadState& aLoadState) {
4429 if (mLoadingEntry) {
4430 mLoadingEntry->mInfo.FillLoadInfo(aLoadState);
4431 return true;
4432 }
4433 if (mActiveEntry) {
4434 mActiveEntry->FillLoadInfo(aLoadState);
4435 return true;
4436 }
4437 return false;
4438}
4439
4440//*****************************************************************************
4441// nsDocShell::nsIBaseWindow
4442//*****************************************************************************
4443
4444NS_IMETHODIMPnsresult
4445nsDocShell::InitWindow(nsIWidget* aParentWidget, int32_t aX, int32_t aY,
4446 int32_t aWidth, int32_t aHeight) {
4447 SetParentWidget(aParentWidget);
4448 SetPositionAndSize(aX, aY, aWidth, aHeight, 0);
4449 NS_ENSURE_TRUE(Initialize(), NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(Initialize())), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "Initialize()" ") failed"
, nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 4449); return NS_ERROR_FAILURE; } } while (false)
;
4450 return NS_OK;
4451}
4452
4453NS_IMETHODIMPnsresult
4454nsDocShell::Destroy() {
4455 // XXX: We allow this function to be called just once. If you are going to
4456 // reset new variables in this function, please make sure the variables will
4457 // never be re-initialized. Adding assertions to check |mIsBeingDestroyed|
4458 // in the setter functions for the variables would be enough.
4459 if (mIsBeingDestroyed) {
4460 return NS_ERROR_DOCSHELL_DYING;
4461 }
4462
4463 NS_ASSERTION(mItemType == typeContent || mItemType == typeChrome,do { if (!(mItemType == typeContent || mItemType == typeChrome
)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "Unexpected item type in docshell"
, "mItemType == typeContent || mItemType == typeChrome", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 4464); MOZ_PretendNoReturn(); } } while (0)
4464 "Unexpected item type in docshell")do { if (!(mItemType == typeContent || mItemType == typeChrome
)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "Unexpected item type in docshell"
, "mItemType == typeContent || mItemType == typeChrome", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 4464); MOZ_PretendNoReturn(); } } while (0)
;
4465
4466 nsCOMPtr<nsIObserverService> serv = services::GetObserverService();
4467 if (serv) {
4468 const char* msg = mItemType == typeContent
4469 ? NS_WEBNAVIGATION_DESTROY"webnavigation-destroy"
4470 : NS_CHROME_WEBNAVIGATION_DESTROY"chrome-webnavigation-destroy";
4471 serv->NotifyObservers(GetAsSupports(this), msg, nullptr);
4472 }
4473
4474 mIsBeingDestroyed = true;
4475
4476 // Brak the cycle with the initial client, if present.
4477 mInitialClientSource.reset();
4478
4479 // Make sure to blow away our mLoadingURI just in case. No loads
4480 // from inside this pagehide.
4481 mLoadingURI = nullptr;
4482
4483 // Fire unload event before we blow anything away.
4484 (void)FirePageHideNotification(true);
4485
4486 // Clear pointers to any detached nsEditorData that's lying
4487 // around in shistory entries. Breaks cycle. See bug 430921.
4488 if (mOSHE) {
4489 mOSHE->SetEditorData(nullptr);
4490 }
4491 if (mLSHE) {
4492 mLSHE->SetEditorData(nullptr);
4493 }
4494
4495 // Note: mContentListener can be null if Init() failed and we're being
4496 // called from the destructor.
4497 if (mContentListener) {
4498 mContentListener->DropDocShellReference();
4499 mContentListener->SetParentContentListener(nullptr);
4500 // Note that we do NOT set mContentListener to null here; that
4501 // way if someone tries to do a load in us after this point
4502 // the nsDSURIContentListener will block it. All of which
4503 // means that we should do this before calling Stop(), of
4504 // course.
4505 }
4506
4507 // Stop any URLs that are currently being loaded...
4508 Stop(nsIWebNavigation::STOP_ALL);
4509
4510 mEditorData = nullptr;
4511
4512 // Save the state of the current document, before destroying the window.
4513 // This is needed to capture the state of a frameset when the new document
4514 // causes the frameset to be destroyed...
4515 PersistLayoutHistoryState();
4516
4517 // Remove this docshell from its parent's child list
4518 nsCOMPtr<nsIDocShellTreeItem> docShellParentAsItem =
4519 do_QueryInterface(GetAsSupports(mParent));
4520 if (docShellParentAsItem) {
4521 docShellParentAsItem->RemoveChild(this);
4522 }
4523
4524 if (mDocumentViewer) {
4525 mDocumentViewer->Close(nullptr);
4526 mDocumentViewer->Destroy();
4527 mDocumentViewer = nullptr;
4528 }
4529
4530 nsDocLoader::Destroy();
4531
4532 mParentWidget = nullptr;
4533 SetCurrentURIInternal(nullptr);
4534
4535 if (mScriptGlobal) {
4536 mScriptGlobal->DetachFromDocShell(!mWillChangeProcess);
4537 mScriptGlobal = nullptr;
4538 }
4539
4540 if (GetSessionHistory()) {
4541 // We want to destroy these content viewers now rather than
4542 // letting their destruction wait for the session history
4543 // entries to get garbage collected. (Bug 488394)
4544 GetSessionHistory()->EvictLocalDocumentViewers();
4545 }
4546
4547 if (mWillChangeProcess && !mBrowsingContext->IsDiscarded()) {
4548 mBrowsingContext->PrepareForProcessChange();
4549 }
4550
4551 SetTreeOwner(nullptr);
4552
4553 mBrowserChild = nullptr;
4554
4555 mChromeEventHandler = nullptr;
4556
4557 mBCWebProgressStatusFilter = nullptr;
4558
4559 // Cancel any timers that were set for this docshell; this is needed
4560 // to break the cycle between us and the timers.
4561 CancelRefreshURITimers();
4562
4563 return NS_OK;
4564}
4565
4566double nsDocShell::GetWidgetCSSToDeviceScale() {
4567 if (mParentWidget) {
4568 return mParentWidget->GetDefaultScale().scale;
4569 }
4570 if (nsCOMPtr<nsIBaseWindow> ownerWindow = do_QueryInterface(mTreeOwner)) {
4571 return ownerWindow->GetWidgetCSSToDeviceScale();
4572 }
4573 return 1.0;
4574}
4575
4576NS_IMETHODIMPnsresult
4577nsDocShell::GetDevicePixelsPerDesktopPixel(double* aScale) {
4578 if (mParentWidget) {
4579 *aScale = mParentWidget->GetDesktopToDeviceScale().scale;
4580 return NS_OK;
4581 }
4582
4583 nsCOMPtr<nsIBaseWindow> ownerWindow(do_QueryInterface(mTreeOwner));
4584 if (ownerWindow) {
4585 return ownerWindow->GetDevicePixelsPerDesktopPixel(aScale);
4586 }
4587
4588 *aScale = 1.0;
4589 return NS_OK;
4590}
4591
4592NS_IMETHODIMPnsresult
4593nsDocShell::SetPosition(int32_t aX, int32_t aY) {
4594 mBounds.MoveTo(aX, aY);
4595
4596 if (mDocumentViewer) {
4597 NS_ENSURE_SUCCESS(mDocumentViewer->Move(aX, aY), NS_ERROR_FAILURE)do { nsresult __rv = mDocumentViewer->Move(aX, aY); if (((
bool)(__builtin_expect(!!(NS_FAILED_impl(__rv)), 0)))) { const
char* name = mozilla::GetStaticErrorName(__rv); mozilla::SmprintfPointer
msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "mDocumentViewer->Move(aX, aY)"
, "NS_ERROR_FAILURE", static_cast<uint32_t>(__rv), name
? " (" : "", name ? name : "", name ? ")" : ""); NS_DebugBreak
(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 4597); return NS_ERROR_FAILURE; } } while (false)
;
4598 }
4599
4600 return NS_OK;
4601}
4602
4603NS_IMETHODIMPnsresult
4604nsDocShell::SetPositionDesktopPix(int32_t aX, int32_t aY) {
4605 nsCOMPtr<nsIBaseWindow> ownerWindow(do_QueryInterface(mTreeOwner));
4606 if (ownerWindow) {
4607 return ownerWindow->SetPositionDesktopPix(aX, aY);
4608 }
4609
4610 double scale = 1.0;
4611 GetDevicePixelsPerDesktopPixel(&scale);
4612 return SetPosition(NSToIntRound(aX * scale), NSToIntRound(aY * scale));
4613}
4614
4615NS_IMETHODIMPnsresult
4616nsDocShell::GetPosition(int32_t* aX, int32_t* aY) {
4617 return GetPositionAndSize(aX, aY, nullptr, nullptr);
4618}
4619
4620NS_IMETHODIMPnsresult
4621nsDocShell::SetSize(int32_t aWidth, int32_t aHeight, bool aRepaint) {
4622 int32_t x = 0, y = 0;
4623 GetPosition(&x, &y);
4624 return SetPositionAndSize(x, y, aWidth, aHeight,
4625 aRepaint ? nsIBaseWindow::eRepaint : 0);
4626}
4627
4628NS_IMETHODIMPnsresult
4629nsDocShell::GetSize(int32_t* aWidth, int32_t* aHeight) {
4630 return GetPositionAndSize(nullptr, nullptr, aWidth, aHeight);
4631}
4632
4633NS_IMETHODIMPnsresult
4634nsDocShell::SetPositionAndSize(int32_t aX, int32_t aY, int32_t aWidth,
4635 int32_t aHeight, uint32_t aFlags) {
4636 mBounds.SetRect(aX, aY, aWidth, aHeight);
4637
4638 // Hold strong ref, since SetBounds can make us null out mDocumentViewer
4639 nsCOMPtr<nsIDocumentViewer> viewer = mDocumentViewer;
4640 if (viewer) {
4641 uint32_t cvflags = (aFlags & nsIBaseWindow::eDelayResize)
4642 ? nsIDocumentViewer::eDelayResize
4643 : 0;
4644 // XXX Border figured in here or is that handled elsewhere?
4645 nsresult rv = viewer->SetBoundsWithFlags(mBounds, cvflags);
4646 NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "NS_ERROR_FAILURE", static_cast
<uint32_t>(__rv), name ? " (" : "", name ? name : "", name
? ")" : ""); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 4646); return
NS_ERROR_FAILURE; } } while (false)
;
4647 }
4648
4649 return NS_OK;
4650}
4651
4652NS_IMETHODIMPnsresult
4653nsDocShell::GetPositionAndSize(int32_t* aX, int32_t* aY, int32_t* aWidth,
4654 int32_t* aHeight) {
4655 if (mParentWidget) {
4656 // ensure size is up-to-date if window has changed resolution
4657 LayoutDeviceIntRect r = mParentWidget->GetClientBounds();
4658 SetPositionAndSize(mBounds.X(), mBounds.Y(), r.Width(), r.Height(), 0);
4659 }
4660
4661 // We should really consider just getting this information from
4662 // our window instead of duplicating the storage and code...
4663 if (aWidth || aHeight) {
4664 // Caller wants to know our size; make sure to give them up to
4665 // date information.
4666 RefPtr<Document> doc(do_GetInterface(GetAsSupports(mParent)));
4667 if (doc) {
4668 doc->FlushPendingNotifications(FlushType::Layout);
4669 }
4670 }
4671
4672 DoGetPositionAndSize(aX, aY, aWidth, aHeight);
4673 return NS_OK;
4674}
4675
4676void nsDocShell::DoGetPositionAndSize(int32_t* aX, int32_t* aY, int32_t* aWidth,
4677 int32_t* aHeight) {
4678 if (aX) {
4679 *aX = mBounds.X();
4680 }
4681 if (aY) {
4682 *aY = mBounds.Y();
4683 }
4684 if (aWidth) {
4685 *aWidth = mBounds.Width();
4686 }
4687 if (aHeight) {
4688 *aHeight = mBounds.Height();
4689 }
4690}
4691
4692NS_IMETHODIMPnsresult
4693nsDocShell::SetDimensions(DimensionRequest&& aRequest) {
4694 return NS_ERROR_NOT_IMPLEMENTED;
4695}
4696
4697NS_IMETHODIMPnsresult
4698nsDocShell::GetDimensions(DimensionKind aDimensionKind, int32_t* aX,
4699 int32_t* aY, int32_t* aCX, int32_t* aCY) {
4700 return NS_ERROR_NOT_IMPLEMENTED;
4701}
4702
4703NS_IMETHODIMPnsresult
4704nsDocShell::Repaint(bool aForce) {
4705 PresShell* presShell = GetPresShell();
4706 NS_ENSURE_TRUE(presShell, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(presShell)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "presShell" ") failed", nullptr
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 4706); return
NS_ERROR_FAILURE; } } while (false)
;
4707
4708 RefPtr<nsViewManager> viewManager = presShell->GetViewManager();
4709 NS_ENSURE_TRUE(viewManager, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(viewManager)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "viewManager" ") failed"
, nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 4709); return NS_ERROR_FAILURE; } } while (false)
;
4710
4711 viewManager->InvalidateAllViews();
4712 return NS_OK;
4713}
4714
4715NS_IMETHODIMPnsresult
4716nsDocShell::GetParentWidget(nsIWidget** aParentWidget) {
4717 NS_ENSURE_ARG_POINTER(aParentWidget)do { if ((__builtin_expect(!!(!(aParentWidget)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aParentWidget" ") failed"
, nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 4717); return NS_ERROR_INVALID_POINTER; } } while (false)
;
4718
4719 *aParentWidget = mParentWidget;
4720 NS_IF_ADDREF(*aParentWidget)ns_if_addref(*aParentWidget);
4721
4722 return NS_OK;
4723}
4724
4725NS_IMETHODIMPnsresult
4726nsDocShell::SetParentWidget(nsIWidget* aParentWidget) {
4727 MOZ_ASSERT(!mIsBeingDestroyed)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mIsBeingDestroyed)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mIsBeingDestroyed))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("!mIsBeingDestroyed"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 4727); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!mIsBeingDestroyed" ")"); do { MOZ_CrashSequence
(__null, 4727); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
4728 mParentWidget = aParentWidget;
4729
4730 return NS_OK;
4731}
4732
4733NS_IMETHODIMPnsresult
4734nsDocShell::GetNativeHandle(nsAString& aNativeHandle) {
4735 // the nativeHandle should be accessed from nsIAppWindow
4736 return NS_ERROR_NOT_IMPLEMENTED;
4737}
4738
4739NS_IMETHODIMPnsresult
4740nsDocShell::GetVisibility(bool* aVisibility) {
4741 NS_ENSURE_ARG_POINTER(aVisibility)do { if ((__builtin_expect(!!(!(aVisibility)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aVisibility" ") failed"
, nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 4741); return NS_ERROR_INVALID_POINTER; } } while (false)
;
4742
4743 *aVisibility = false;
4744
4745 if (!mDocumentViewer) {
4746 return NS_OK;
4747 }
4748
4749 PresShell* presShell = GetPresShell();
4750 if (!presShell) {
4751 return NS_OK;
4752 }
4753
4754 // get the view manager
4755 nsViewManager* vm = presShell->GetViewManager();
4756 NS_ENSURE_TRUE(vm, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(vm)), 0))) { NS_DebugBreak(NS_DEBUG_WARNING
, "NS_ENSURE_TRUE(" "vm" ") failed", nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 4756); return NS_ERROR_FAILURE; } } while (false)
;
4757
4758 // get the root view
4759 nsView* view = vm->GetRootView(); // views are not ref counted
4760 NS_ENSURE_TRUE(view, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(view)), 0))) { NS_DebugBreak(
NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "view" ") failed", nullptr
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 4760); return
NS_ERROR_FAILURE; } } while (false)
;
4761
4762 // if our root view is hidden, we are not visible
4763 if (view->GetVisibility() == ViewVisibility::Hide) {
4764 return NS_OK;
4765 }
4766
4767 // otherwise, we must walk up the document and view trees checking
4768 // for a hidden view, unless we're an off screen browser, which
4769 // would make this test meaningless.
4770
4771 RefPtr<nsDocShell> docShell = this;
4772 RefPtr<nsDocShell> parentItem = docShell->GetInProcessParentDocshell();
4773 while (parentItem) {
4774 // Null-check for crash in bug 267804
4775 if (!parentItem->GetPresShell()) {
4776 MOZ_ASSERT_UNREACHABLE("parent docshell has null pres shell")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "MOZ_ASSERT_UNREACHABLE: "
"parent docshell has null pres shell" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 4776); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "parent docshell has null pres shell"
")"); do { MOZ_CrashSequence(__null, 4776); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4777 return NS_OK;
4778 }
4779
4780 vm = docShell->GetPresShell()->GetViewManager();
4781 if (vm) {
4782 view = vm->GetRootView();
4783 }
4784
4785 if (view) {
4786 view = view->GetParent(); // anonymous inner view
4787 if (view) {
4788 view = view->GetParent(); // subdocumentframe's view
4789 }
4790 }
4791
4792 nsIFrame* frame = view ? view->GetFrame() : nullptr;
4793 if (frame && !frame->IsVisibleConsideringAncestors(
4794 nsIFrame::VISIBILITY_CROSS_CHROME_CONTENT_BOUNDARY)) {
4795 return NS_OK;
4796 }
4797
4798 docShell = parentItem;
4799 parentItem = docShell->GetInProcessParentDocshell();
4800 }
4801
4802 nsCOMPtr<nsIBaseWindow> treeOwnerAsWin(do_QueryInterface(mTreeOwner));
4803 if (!treeOwnerAsWin) {
4804 *aVisibility = true;
4805 return NS_OK;
4806 }
4807
4808 // Check with the tree owner as well to give embedders a chance to
4809 // expose visibility as well.
4810 nsresult rv = treeOwnerAsWin->GetVisibility(aVisibility);
4811 if (rv == NS_ERROR_NOT_IMPLEMENTED) {
4812 // The tree owner had no opinion on our visibility.
4813 *aVisibility = true;
4814 return NS_OK;
4815 }
4816 return rv;
4817}
4818
4819void nsDocShell::ActivenessMaybeChanged() {
4820 const bool isActive = mBrowsingContext->IsActive();
4821 if (RefPtr<PresShell> presShell = GetPresShell()) {
4822 presShell->ActivenessMaybeChanged();
4823 }
4824
4825 // Tell the window about it
4826 if (mScriptGlobal) {
4827 mScriptGlobal->SetIsBackground(!isActive);
4828 if (RefPtr<Document> doc = mScriptGlobal->GetExtantDoc()) {
4829 // Update orientation when the top-level browsing context becomes active.
4830 if (isActive && mBrowsingContext->IsTop() &&
4831 !mBrowsingContext->Windowless()) {
4832 // We only care about the top-level browsing context.
4833 auto orientation = mBrowsingContext->GetOrientationLock();
4834 ScreenOrientation::UpdateActiveOrientationLock(orientation);
4835 }
4836
4837 doc->PostVisibilityUpdateEvent();
4838 }
4839 }
4840
4841 // Tell the nsDOMNavigationTiming about it
4842 RefPtr<nsDOMNavigationTiming> timing = mTiming;
4843 if (!timing && mDocumentViewer) {
4844 if (Document* doc = mDocumentViewer->GetDocument()) {
4845 timing = doc->GetNavigationTiming();
4846 }
4847 }
4848 if (timing) {
4849 timing->NotifyDocShellStateChanged(
4850 isActive ? nsDOMNavigationTiming::DocShellState::eActive
4851 : nsDOMNavigationTiming::DocShellState::eInactive);
4852 }
4853
4854 // Restart or stop meta refresh timers if necessary
4855 if (mDisableMetaRefreshWhenInactive) {
4856 if (isActive) {
4857 ResumeRefreshURIs();
4858 } else {
4859 SuspendRefreshURIs();
4860 }
4861 }
4862
4863 if (InputTaskManager::CanSuspendInputEvent()) {
4864 mBrowsingContext->Group()->UpdateInputTaskManagerIfNeeded(isActive);
4865 }
4866}
4867
4868NS_IMETHODIMPnsresult
4869nsDocShell::SetDefaultLoadFlags(uint32_t aDefaultLoadFlags) {
4870 if (!mWillChangeProcess) {
4871 // Intentionally ignoring handling discarded browsing contexts.
4872 Unused << mBrowsingContext->SetDefaultLoadFlags(aDefaultLoadFlags);
4873 } else {
4874 // Bug 1623565: DevTools tries to clean up defaultLoadFlags on
4875 // shutdown. Sorry DevTools, your DocShell is in another process.
4876 NS_WARNING("nsDocShell::SetDefaultLoadFlags called on Zombie DocShell")NS_DebugBreak(NS_DEBUG_WARNING, "nsDocShell::SetDefaultLoadFlags called on Zombie DocShell"
, nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 4876)
;
4877 }
4878 return NS_OK;
4879}
4880
4881NS_IMETHODIMPnsresult
4882nsDocShell::GetDefaultLoadFlags(uint32_t* aDefaultLoadFlags) {
4883 *aDefaultLoadFlags = mBrowsingContext->GetDefaultLoadFlags();
4884 return NS_OK;
4885}
4886
4887NS_IMETHODIMPnsresult
4888nsDocShell::GetFailedChannel(nsIChannel** aFailedChannel) {
4889 NS_ENSURE_ARG_POINTER(aFailedChannel)do { if ((__builtin_expect(!!(!(aFailedChannel)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aFailedChannel" ") failed"
, nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 4889); return NS_ERROR_INVALID_POINTER; } } while (false)
;
4890 Document* doc = GetDocument();
4891 if (!doc) {
4892 *aFailedChannel = nullptr;
4893 return NS_OK;
4894 }
4895 NS_IF_ADDREF(*aFailedChannel = doc->GetFailedChannel())ns_if_addref(*aFailedChannel = doc->GetFailedChannel());
4896 return NS_OK;
4897}
4898
4899NS_IMETHODIMPnsresult
4900nsDocShell::SetVisibility(bool aVisibility) {
4901 // Show()/Hide() may change mDocumentViewer.
4902 nsCOMPtr<nsIDocumentViewer> viewer = mDocumentViewer;
4903 if (!viewer) {
4904 return NS_OK;
4905 }
4906 if (aVisibility) {
4907 viewer->Show();
4908 } else {
4909 viewer->Hide();
4910 }
4911
4912 return NS_OK;
4913}
4914
4915NS_IMETHODIMPnsresult
4916nsDocShell::GetEnabled(bool* aEnabled) {
4917 NS_ENSURE_ARG_POINTER(aEnabled)do { if ((__builtin_expect(!!(!(aEnabled)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aEnabled" ") failed", nullptr
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 4917); return
NS_ERROR_INVALID_POINTER; } } while (false)
;
4918 *aEnabled = true;
4919 return NS_ERROR_NOT_IMPLEMENTED;
4920}
4921
4922NS_IMETHODIMPnsresult
4923nsDocShell::SetEnabled(bool aEnabled) { return NS_ERROR_NOT_IMPLEMENTED; }
4924
4925NS_IMETHODIMPnsresult
4926nsDocShell::GetMainWidget(nsIWidget** aMainWidget) {
4927 // We don't create our own widget, so simply return the parent one.
4928 return GetParentWidget(aMainWidget);
4929}
4930
4931NS_IMETHODIMPnsresult
4932nsDocShell::GetTitle(nsAString& aTitle) {
4933 aTitle = mTitle;
4934 return NS_OK;
4935}
4936
4937NS_IMETHODIMPnsresult
4938nsDocShell::SetTitle(const nsAString& aTitle) {
4939 // Avoid unnecessary updates of the title if the URI and the title haven't
4940 // changed.
4941 if (mTitleValidForCurrentURI && mTitle == aTitle) {
4942 return NS_OK;
4943 }
4944
4945 // Store local title
4946 mTitle = aTitle;
4947 mTitleValidForCurrentURI = true;
4948
4949 // When title is set on the top object it should then be passed to the
4950 // tree owner.
4951 if (mBrowsingContext->IsTop()) {
4952 nsCOMPtr<nsIBaseWindow> treeOwnerAsWin(do_QueryInterface(mTreeOwner));
4953 if (treeOwnerAsWin) {
4954 treeOwnerAsWin->SetTitle(aTitle);
4955 }
4956 }
4957
4958 if (mCurrentURI && mLoadType != LOAD_ERROR_PAGE) {
4959 UpdateGlobalHistoryTitle(mCurrentURI);
4960 }
4961
4962 // Update SessionHistory with the document's title.
4963 if (mLoadType != LOAD_BYPASS_HISTORY && mLoadType != LOAD_ERROR_PAGE) {
4964 SetTitleOnHistoryEntry(true);
4965 }
4966
4967 return NS_OK;
4968}
4969
4970void nsDocShell::SetTitleOnHistoryEntry(bool aUpdateEntryInSessionHistory) {
4971 if (mOSHE) {
4972 mOSHE->SetTitle(mTitle);
4973 }
4974
4975 if (mActiveEntry && mBrowsingContext) {
4976 mActiveEntry->SetTitle(mTitle);
4977 if (aUpdateEntryInSessionHistory) {
4978 if (XRE_IsParentProcess()) {
4979 SessionHistoryEntry* entry =
4980 mBrowsingContext->Canonical()->GetActiveSessionHistoryEntry();
4981 if (entry) {
4982 entry->SetTitle(mTitle);
4983 }
4984 } else {
4985 mozilla::Unused
4986 << ContentChild::GetSingleton()->SendSessionHistoryEntryTitle(
4987 mBrowsingContext, mTitle);
4988 }
4989 }
4990 }
4991}
4992
4993nsPoint nsDocShell::GetCurScrollPos() {
4994 nsPoint scrollPos;
4995 if (ScrollContainerFrame* sf = GetRootScrollContainerFrame()) {
4996 scrollPos = sf->GetVisualViewportOffset();
4997 }
4998 return scrollPos;
4999}
5000
5001nsresult nsDocShell::SetCurScrollPosEx(int32_t aCurHorizontalPos,
5002 int32_t aCurVerticalPos) {
5003 ScrollContainerFrame* sf = GetRootScrollContainerFrame();
5004 NS_ENSURE_TRUE(sf, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(sf)), 0))) { NS_DebugBreak(NS_DEBUG_WARNING
, "NS_ENSURE_TRUE(" "sf" ") failed", nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 5004); return NS_ERROR_FAILURE; } } while (false)
;
5005
5006 ScrollMode scrollMode =
5007 sf->IsSmoothScroll() ? ScrollMode::SmoothMsd : ScrollMode::Instant;
5008
5009 nsPoint targetPos(aCurHorizontalPos, aCurVerticalPos);
5010 sf->ScrollTo(targetPos, scrollMode);
5011
5012 // Set the visual viewport offset as well.
5013
5014 RefPtr<PresShell> presShell = GetPresShell();
5015 NS_ENSURE_TRUE(presShell, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(presShell)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "presShell" ") failed", nullptr
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 5015); return
NS_ERROR_FAILURE; } } while (false)
;
5016
5017 nsPresContext* presContext = presShell->GetPresContext();
5018 NS_ENSURE_TRUE(presContext, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(presContext)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "presContext" ") failed"
, nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 5018); return NS_ERROR_FAILURE; } } while (false)
;
5019
5020 // Only the root content document can have a distinct visual viewport offset.
5021 if (!presContext->IsRootContentDocumentCrossProcess()) {
5022 return NS_OK;
5023 }
5024
5025 // Not on a platform with a distinct visual viewport - don't bother setting
5026 // the visual viewport offset.
5027 if (!presShell->IsVisualViewportSizeSet()) {
5028 return NS_OK;
5029 }
5030
5031 presShell->ScrollToVisual(targetPos, layers::FrameMetrics::eMainThread,
5032 scrollMode);
5033
5034 return NS_OK;
5035}
5036
5037void nsDocShell::SetScrollbarPreference(mozilla::ScrollbarPreference aPref) {
5038 if (mScrollbarPref == aPref) {
5039 return;
5040 }
5041 mScrollbarPref = aPref;
5042 auto* ps = GetPresShell();
5043 if (!ps) {
5044 return;
5045 }
5046 nsIFrame* rootScrollContainerFrame = ps->GetRootScrollContainerFrame();
5047 if (!rootScrollContainerFrame) {
5048 return;
5049 }
5050 ps->FrameNeedsReflow(rootScrollContainerFrame,
5051 IntrinsicDirty::FrameAncestorsAndDescendants,
5052 NS_FRAME_IS_DIRTY);
5053}
5054
5055//*****************************************************************************
5056// nsDocShell::nsIRefreshURI
5057//*****************************************************************************
5058
5059NS_IMETHODIMPnsresult
5060nsDocShell::RefreshURI(nsIURI* aURI, nsIPrincipal* aPrincipal,
5061 uint32_t aDelay) {
5062 MOZ_ASSERT(!mIsBeingDestroyed)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mIsBeingDestroyed)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mIsBeingDestroyed))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("!mIsBeingDestroyed"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 5062); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!mIsBeingDestroyed" ")"); do { MOZ_CrashSequence
(__null, 5062); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
5063
5064 NS_ENSURE_ARG(aURI)do { if ((__builtin_expect(!!(!(aURI)), 0))) { NS_DebugBreak(
NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aURI" ") failed", nullptr
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 5064); return
NS_ERROR_INVALID_ARG; } } while (false)
;
5065
5066 /* Check if Meta refresh/redirects are permitted. Some
5067 * embedded applications may not want to do this.
5068 * Must do this before sending out NOTIFY_REFRESH events
5069 * because listeners may have side effects (e.g. displaying a
5070 * button to manually trigger the refresh later).
5071 */
5072 bool allowRedirects = true;
5073 GetAllowMetaRedirects(&allowRedirects);
5074 if (!allowRedirects) {
5075 return NS_OK;
5076 }
5077
5078 // If any web progress listeners are listening for NOTIFY_REFRESH events,
5079 // give them a chance to block this refresh.
5080 bool sameURI;
5081 nsresult rv = aURI->Equals(mCurrentURI, &sameURI);
5082 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
5083 sameURI = false;
5084 }
5085 if (!RefreshAttempted(this, aURI, aDelay, sameURI)) {
5086 return NS_OK;
5087 }
5088
5089 nsCOMPtr<nsITimerCallback> refreshTimer =
5090 new nsRefreshTimer(this, aURI, aPrincipal, aDelay);
5091
5092 BusyFlags busyFlags = GetBusyFlags();
5093
5094 if (!mRefreshURIList) {
5095 mRefreshURIList = nsArray::Create();
5096 }
5097
5098 if (busyFlags & BUSY_FLAGS_BUSY ||
5099 (!mBrowsingContext->IsActive() && mDisableMetaRefreshWhenInactive)) {
5100 // We don't want to create the timer right now. Instead queue up the
5101 // request and trigger the timer in EndPageLoad() or whenever we become
5102 // active.
5103 mRefreshURIList->AppendElement(refreshTimer);
5104 } else {
5105 // There is no page loading going on right now. Create the
5106 // timer and fire it right away.
5107 nsCOMPtr<nsPIDOMWindowOuter> win = GetWindow();
5108 NS_ENSURE_TRUE(win, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(win)), 0))) { NS_DebugBreak(NS_DEBUG_WARNING
, "NS_ENSURE_TRUE(" "win" ") failed", nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 5108); return NS_ERROR_FAILURE; } } while (false)
;
5109
5110 nsCOMPtr<nsITimer> timer;
5111 MOZ_TRY_VAR(timer, NS_NewTimerWithCallback(refreshTimer, aDelay,(timer) = __extension__({ auto mozTryVarTempResult = ::mozilla
::ToResult(NS_NewTimerWithCallback(refreshTimer, aDelay, nsITimer
::TYPE_ONE_SHOT)); if ((__builtin_expect(!!(mozTryVarTempResult
.isErr()), 0))) { return mozTryVarTempResult.propagateErr(); }
mozTryVarTempResult.unwrap(); });
5112 nsITimer::TYPE_ONE_SHOT))(timer) = __extension__({ auto mozTryVarTempResult = ::mozilla
::ToResult(NS_NewTimerWithCallback(refreshTimer, aDelay, nsITimer
::TYPE_ONE_SHOT)); if ((__builtin_expect(!!(mozTryVarTempResult
.isErr()), 0))) { return mozTryVarTempResult.propagateErr(); }
mozTryVarTempResult.unwrap(); });
;
5113
5114 mRefreshURIList->AppendElement(timer); // owning timer ref
5115 }
5116 return NS_OK;
5117}
5118
5119nsresult nsDocShell::ForceRefreshURIFromTimer(nsIURI* aURI,
5120 nsIPrincipal* aPrincipal,
5121 uint32_t aDelay,
5122 nsITimer* aTimer) {
5123 MOZ_ASSERT(aTimer, "Must have a timer here")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aTimer)>::isValid, "invalid assertion condition")
; if ((__builtin_expect(!!(!(!!(aTimer))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aTimer" " (" "Must have a timer here"
")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 5123
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aTimer" ") (" "Must have a timer here"
")"); do { MOZ_CrashSequence(__null, 5123); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5124
5125 // Remove aTimer from mRefreshURIList if needed
5126 if (mRefreshURIList) {
5127 uint32_t n = 0;
5128 mRefreshURIList->GetLength(&n);
5129
5130 for (uint32_t i = 0; i < n; ++i) {
5131 nsCOMPtr<nsITimer> timer = do_QueryElementAt(mRefreshURIList, i);
5132 if (timer == aTimer) {
5133 mRefreshURIList->RemoveElementAt(i);
5134 break;
5135 }
5136 }
5137 }
5138
5139 return ForceRefreshURI(aURI, aPrincipal, aDelay);
5140}
5141
5142NS_IMETHODIMPnsresult
5143nsDocShell::ForceRefreshURI(nsIURI* aURI, nsIPrincipal* aPrincipal,
5144 uint32_t aDelay) {
5145 NS_ENSURE_ARG(aURI)do { if ((__builtin_expect(!!(!(aURI)), 0))) { NS_DebugBreak(
NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aURI" ") failed", nullptr
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 5145); return
NS_ERROR_INVALID_ARG; } } while (false)
;
5146
5147 RefPtr<nsDocShellLoadState> loadState = new nsDocShellLoadState(aURI);
5148 loadState->SetOriginalURI(mCurrentURI);
5149 loadState->SetResultPrincipalURI(aURI);
5150 loadState->SetResultPrincipalURIIsSome(true);
5151 loadState->SetKeepResultPrincipalURIIfSet(true);
5152 loadState->SetIsMetaRefresh(true);
5153
5154 RefPtr<Document> doc = GetDocument();
5155 NS_ENSURE_STATE(doc)do { if ((__builtin_expect(!!(!(doc)), 0))) { NS_DebugBreak(NS_DEBUG_WARNING
, "NS_ENSURE_TRUE(" "doc" ") failed", nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 5155); return NS_ERROR_UNEXPECTED; } } while (false)
;
5156
5157 // Set the triggering pricipal to aPrincipal if available, or current
5158 // document's principal otherwise.
5159 nsCOMPtr<nsIPrincipal> principal = aPrincipal;
5160 if (!principal) {
5161 principal = doc->NodePrincipal();
5162 }
5163 loadState->SetTriggeringPrincipal(principal);
5164 loadState->SetCsp(doc->GetCsp());
5165 loadState->SetHasValidUserGestureActivation(
5166 doc->HasValidTransientUserGestureActivation());
5167
5168 loadState->SetTextDirectiveUserActivation(
5169 doc->ConsumeTextDirectiveUserActivation() ||
5170 loadState->HasValidUserGestureActivation());
5171 loadState->SetTriggeringSandboxFlags(doc->GetSandboxFlags());
5172 loadState->SetTriggeringWindowId(doc->InnerWindowID());
5173 loadState->SetTriggeringStorageAccess(doc->UsingStorageAccess());
5174 loadState->SetTriggeringClassificationFlags(doc->GetScriptTrackingFlags());
5175
5176 loadState->SetPrincipalIsExplicit(true);
5177
5178 /* Check if this META refresh causes a redirection
5179 * to another site.
5180 */
5181 bool equalUri = false;
5182 nsresult rv = aURI->Equals(mCurrentURI, &equalUri);
5183
5184 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && !equalUri && aDelay <= REFRESH_REDIRECT_TIMER15000) {
5185 /* It is a META refresh based redirection within the threshold time
5186 * we have in mind (15000 ms as defined by REFRESH_REDIRECT_TIMER).
5187 * Pass a REPLACE flag to LoadURI().
5188 */
5189 loadState->SetLoadType(LOAD_REFRESH_REPLACE);
5190 } else {
5191 loadState->SetLoadType(LOAD_REFRESH);
5192 }
5193
5194 const bool sendReferrer = StaticPrefs::network_http_referer_sendFromRefresh();
5195 /* The document's referrer policy is needed instead of mReferrerInfo's
5196 * referrer policy.
5197 */
5198 const nsCOMPtr<nsIReferrerInfo> referrerInfo =
5199 new ReferrerInfo(*doc, sendReferrer);
5200 /* We mimic HTTP, which passes the original referrer. See step 3 of
5201 * <https://html.spec.whatwg.org/multipage/browsing-the-web.html#create-navigation-params-by-fetching>.
5202 */
5203 loadState->SetReferrerInfo(referrerInfo);
5204
5205 loadState->SetLoadFlags(
5206 nsIWebNavigation::LOAD_FLAGS_DISALLOW_INHERIT_PRINCIPAL);
5207 loadState->SetFirstParty(true);
5208
5209 /*
5210 * LoadURI(...) will cancel all refresh timers... This causes the
5211 * Timer and its refreshData instance to be released...
5212 */
5213 LoadURI(loadState, false);
5214
5215 return NS_OK;
5216}
5217
5218static const char16_t* SkipASCIIWhitespace(const char16_t* aStart,
5219 const char16_t* aEnd) {
5220 const char16_t* iter = aStart;
5221 while (iter != aEnd && mozilla::IsAsciiWhitespace(*iter)) {
5222 ++iter;
5223 }
5224 return iter;
5225}
5226
5227static std::tuple<const char16_t*, const char16_t*> ExtractURLString(
5228 const char16_t* aPosition, const char16_t* aEnd) {
5229 MOZ_ASSERT(aPosition != aEnd)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aPosition != aEnd)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aPosition != aEnd))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("aPosition != aEnd"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 5229); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aPosition != aEnd" ")"); do { MOZ_CrashSequence
(__null, 5229); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
5230
5231 // 1. Let urlString be the substring of input from the code point at
5232 // position to the end of the string.
5233 const char16_t* urlStart = aPosition;
5234 const char16_t* urlEnd = aEnd;
5235
5236 // 2. If the code point in input pointed to by position is U+0055 (U) or
5237 // U+0075 (u), then advance position to the next code point.
5238 // Otherwise, jump to the step labeled skip quotes.
5239 if (*aPosition == 'U' || *aPosition == 'u') {
5240 ++aPosition;
5241
5242 // 3. If the code point in input pointed to by position is U+0052 (R) or
5243 // U+0072 (r), then advance position to the next code point.
5244 // Otherwise, jump to the step labeled parse.
5245 if (aPosition == aEnd || (*aPosition != 'R' && *aPosition != 'r')) {
5246 return std::make_tuple(urlStart, urlEnd);
5247 }
5248
5249 ++aPosition;
5250
5251 // 4. If the code point in input pointed to by position is U+004C (L) or
5252 // U+006C (l), then advance position to the next code point.
5253 // Otherwise, jump to the step labeled parse.
5254 if (aPosition == aEnd || (*aPosition != 'L' && *aPosition != 'l')) {
5255 return std::make_tuple(urlStart, urlEnd);
5256 }
5257
5258 ++aPosition;
5259
5260 // 5. Skip ASCII whitespace within input given position.
5261 aPosition = SkipASCIIWhitespace(aPosition, aEnd);
5262
5263 // 6. If the code point in input pointed to by position is U+003D (=),
5264 // then advance position to the next code point. Otherwise, jump to
5265 // the step labeled parse.
5266 if (aPosition == aEnd || *aPosition != '=') {
5267 return std::make_tuple(urlStart, urlEnd);
5268 }
5269
5270 ++aPosition;
5271
5272 // 7. Skip ASCII whitespace within input given position.
5273 aPosition = SkipASCIIWhitespace(aPosition, aEnd);
5274 }
5275
5276 // 8. Skip quotes: If the code point in input pointed to by position is
5277 // U+0027 (') or U+0022 ("), then let quote be that code point, and
5278 // advance position to the next code point. Otherwise, let quote be
5279 // the empty string.
5280 Maybe<char> quote;
5281 if (aPosition != aEnd && (*aPosition == '\'' || *aPosition == '"')) {
5282 quote.emplace(*aPosition);
5283 ++aPosition;
5284 }
5285
5286 // 9. Set urlString to the substring of input from the code point at
5287 // position to the end of the string.
5288 urlStart = aPosition;
5289 urlEnd = aEnd;
5290
5291 // 10. If quote is not the empty string, and there is a code point in
5292 // urlString equal to quote, then truncate urlString at that code
5293 // point, so that it and all subsequent code points are removed.
5294 const char16_t* quotePos;
5295 if (quote.isSome() &&
5296 (quotePos = nsCharTraits<char16_t>::find(
5297 urlStart, std::distance(urlStart, aEnd), quote.value()))) {
5298 urlEnd = quotePos;
5299 }
5300
5301 return std::make_tuple(urlStart, urlEnd);
5302}
5303
5304void nsDocShell::SetupRefreshURIFromHeader(Document* aDocument,
5305 const nsAString& aHeader) {
5306 if (mIsBeingDestroyed) {
5307 return;
5308 }
5309
5310 const char16_t* position = aHeader.BeginReading();
5311 const char16_t* end = aHeader.EndReading();
5312
5313 // See https://html.spec.whatwg.org/#shared-declarative-refresh-steps.
5314
5315 // 3. Skip ASCII whitespace
5316 position = SkipASCIIWhitespace(position, end);
5317
5318 // 4. Let time be 0.
5319 CheckedInt<uint32_t> milliSeconds;
5320
5321 // 5. Collect a sequence of code points that are ASCII digits
5322 const char16_t* digitsStart = position;
5323 while (position != end && mozilla::IsAsciiDigit(*position)) {
5324 ++position;
5325 }
5326
5327 if (position == digitsStart) {
5328 // 6. If timeString is the empty string, then:
5329 // 1. If the code point in input pointed to by position is not U+002E
5330 // (.), then return.
5331 if (position == end || *position != '.') {
5332 return;
5333 }
5334 } else {
5335 // 7. Otherwise, set time to the result of parsing timeString using the
5336 // rules for parsing non-negative integers.
5337 nsContentUtils::ParseHTMLIntegerResultFlags result;
5338 uint32_t seconds =
5339 nsContentUtils::ParseHTMLInteger(digitsStart, position, &result);
5340 MOZ_ASSERT(!(result & nsContentUtils::eParseHTMLInteger_Negative))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!(result & nsContentUtils::eParseHTMLInteger_Negative
))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!(result & nsContentUtils::eParseHTMLInteger_Negative
)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!(result & nsContentUtils::eParseHTMLInteger_Negative)"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 5340); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!(result & nsContentUtils::eParseHTMLInteger_Negative)"
")"); do { MOZ_CrashSequence(__null, 5340); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5341 if (result & nsContentUtils::eParseHTMLInteger_Error) {
5342 // The spec assumes no errors here (since we only pass ASCII digits in),
5343 // but we can still overflow, so this block should deal with that (and
5344 // only that).
5345 MOZ_ASSERT(do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!(result & ~(nsContentUtils::eParseHTMLInteger_DidNotConsumeAllInput
| nsContentUtils::eParseHTMLInteger_Error | nsContentUtils::
eParseHTMLInteger_ErrorOverflow)))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!(result & ~(nsContentUtils
::eParseHTMLInteger_DidNotConsumeAllInput | nsContentUtils::eParseHTMLInteger_Error
| nsContentUtils::eParseHTMLInteger_ErrorOverflow))))), 0)))
{ do { } while (false); MOZ_ReportAssertionFailure("!(result & ~(nsContentUtils::eParseHTMLInteger_DidNotConsumeAllInput | nsContentUtils::eParseHTMLInteger_Error | nsContentUtils::eParseHTMLInteger_ErrorOverflow))"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 5348); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!(result & ~(nsContentUtils::eParseHTMLInteger_DidNotConsumeAllInput | nsContentUtils::eParseHTMLInteger_Error | nsContentUtils::eParseHTMLInteger_ErrorOverflow))"
")"); do { MOZ_CrashSequence(__null, 5348); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
5346 !(result & ~(nsContentUtils::eParseHTMLInteger_DidNotConsumeAllInput |do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!(result & ~(nsContentUtils::eParseHTMLInteger_DidNotConsumeAllInput
| nsContentUtils::eParseHTMLInteger_Error | nsContentUtils::
eParseHTMLInteger_ErrorOverflow)))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!(result & ~(nsContentUtils
::eParseHTMLInteger_DidNotConsumeAllInput | nsContentUtils::eParseHTMLInteger_Error
| nsContentUtils::eParseHTMLInteger_ErrorOverflow))))), 0)))
{ do { } while (false); MOZ_ReportAssertionFailure("!(result & ~(nsContentUtils::eParseHTMLInteger_DidNotConsumeAllInput | nsContentUtils::eParseHTMLInteger_Error | nsContentUtils::eParseHTMLInteger_ErrorOverflow))"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 5348); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!(result & ~(nsContentUtils::eParseHTMLInteger_DidNotConsumeAllInput | nsContentUtils::eParseHTMLInteger_Error | nsContentUtils::eParseHTMLInteger_ErrorOverflow))"
")"); do { MOZ_CrashSequence(__null, 5348); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
5347 nsContentUtils::eParseHTMLInteger_Error |do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!(result & ~(nsContentUtils::eParseHTMLInteger_DidNotConsumeAllInput
| nsContentUtils::eParseHTMLInteger_Error | nsContentUtils::
eParseHTMLInteger_ErrorOverflow)))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!(result & ~(nsContentUtils
::eParseHTMLInteger_DidNotConsumeAllInput | nsContentUtils::eParseHTMLInteger_Error
| nsContentUtils::eParseHTMLInteger_ErrorOverflow))))), 0)))
{ do { } while (false); MOZ_ReportAssertionFailure("!(result & ~(nsContentUtils::eParseHTMLInteger_DidNotConsumeAllInput | nsContentUtils::eParseHTMLInteger_Error | nsContentUtils::eParseHTMLInteger_ErrorOverflow))"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 5348); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!(result & ~(nsContentUtils::eParseHTMLInteger_DidNotConsumeAllInput | nsContentUtils::eParseHTMLInteger_Error | nsContentUtils::eParseHTMLInteger_ErrorOverflow))"
")"); do { MOZ_CrashSequence(__null, 5348); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
5348 nsContentUtils::eParseHTMLInteger_ErrorOverflow)))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!(result & ~(nsContentUtils::eParseHTMLInteger_DidNotConsumeAllInput
| nsContentUtils::eParseHTMLInteger_Error | nsContentUtils::
eParseHTMLInteger_ErrorOverflow)))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!(result & ~(nsContentUtils
::eParseHTMLInteger_DidNotConsumeAllInput | nsContentUtils::eParseHTMLInteger_Error
| nsContentUtils::eParseHTMLInteger_ErrorOverflow))))), 0)))
{ do { } while (false); MOZ_ReportAssertionFailure("!(result & ~(nsContentUtils::eParseHTMLInteger_DidNotConsumeAllInput | nsContentUtils::eParseHTMLInteger_Error | nsContentUtils::eParseHTMLInteger_ErrorOverflow))"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 5348); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!(result & ~(nsContentUtils::eParseHTMLInteger_DidNotConsumeAllInput | nsContentUtils::eParseHTMLInteger_Error | nsContentUtils::eParseHTMLInteger_ErrorOverflow))"
")"); do { MOZ_CrashSequence(__null, 5348); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5349 return;
5350 }
5351 MOZ_ASSERT(do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!(result & nsContentUtils::eParseHTMLInteger_DidNotConsumeAllInput
))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!(result & nsContentUtils::eParseHTMLInteger_DidNotConsumeAllInput
)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!(result & nsContentUtils::eParseHTMLInteger_DidNotConsumeAllInput)"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 5352); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!(result & nsContentUtils::eParseHTMLInteger_DidNotConsumeAllInput)"
")"); do { MOZ_CrashSequence(__null, 5352); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
5352 !(result & nsContentUtils::eParseHTMLInteger_DidNotConsumeAllInput))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!(result & nsContentUtils::eParseHTMLInteger_DidNotConsumeAllInput
))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!(result & nsContentUtils::eParseHTMLInteger_DidNotConsumeAllInput
)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!(result & nsContentUtils::eParseHTMLInteger_DidNotConsumeAllInput)"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 5352); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!(result & nsContentUtils::eParseHTMLInteger_DidNotConsumeAllInput)"
")"); do { MOZ_CrashSequence(__null, 5352); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5353
5354 milliSeconds = seconds;
5355 milliSeconds *= 1000;
5356 if (!milliSeconds.isValid()) {
5357 return;
5358 }
5359 }
5360
5361 // 8. Collect a sequence of code points that are ASCII digits and U+002E FULL
5362 // STOP characters (.) from input given position. Ignore any collected
5363 // characters.
5364 while (position != end &&
5365 (mozilla::IsAsciiDigit(*position) || *position == '.')) {
5366 ++position;
5367 }
5368
5369 // 9. Let urlRecord be document's URL.
5370 nsCOMPtr<nsIURI> urlRecord(aDocument->GetDocumentURI());
5371
5372 // 10. If position is not past the end of input
5373 if (position != end) {
5374 // 1. If the code point in input pointed to by position is not U+003B (;),
5375 // U+002C (,), or ASCII whitespace, then return.
5376 if (*position != ';' && *position != ',' &&
5377 !mozilla::IsAsciiWhitespace(*position)) {
5378 return;
5379 }
5380
5381 // 2. Skip ASCII whitespace within input given position.
5382 position = SkipASCIIWhitespace(position, end);
5383
5384 // 3. If the code point in input pointed to by position is U+003B (;) or
5385 // U+002C (,), then advance position to the next code point.
5386 if (position != end && (*position == ';' || *position == ',')) {
5387 ++position;
5388
5389 // 4. Skip ASCII whitespace within input given position.
5390 position = SkipASCIIWhitespace(position, end);
5391 }
5392
5393 // 11. If position is not past the end of input, then:
5394 if (position != end) {
5395 const char16_t* urlStart;
5396 const char16_t* urlEnd;
5397
5398 // 1-10. See ExtractURLString.
5399 std::tie(urlStart, urlEnd) = ExtractURLString(position, end);
5400
5401 // 11. Parse: Parse urlString relative to document. If that fails, return.
5402 // Otherwise, set urlRecord to the resulting URL record.
5403 nsresult rv =
5404 NS_NewURI(getter_AddRefs(urlRecord),
5405 Substring(urlStart, std::distance(urlStart, urlEnd)),
5406 /* charset = */ nullptr, aDocument->GetDocBaseURI());
5407 NS_ENSURE_SUCCESS_VOID(rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS_VOID(%s) failed with "
"result 0x%" "X" "%s%s%s", "rv", static_cast<uint32_t>
(__rv), name ? " (" : "", name ? name : "", name ? ")" : "");
NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 5407); return; } } while (false)
;
5408 }
5409 }
5410
5411 nsIPrincipal* principal = aDocument->NodePrincipal();
5412 nsCOMPtr<nsIScriptSecurityManager> securityManager =
5413 nsContentUtils::GetSecurityManager();
5414 nsresult rv = securityManager->CheckLoadURIWithPrincipal(
5415 principal, urlRecord,
5416 nsIScriptSecurityManager::LOAD_IS_AUTOMATIC_DOCUMENT_REPLACEMENT,
5417 aDocument->InnerWindowID());
5418 NS_ENSURE_SUCCESS_VOID(rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS_VOID(%s) failed with "
"result 0x%" "X" "%s%s%s", "rv", static_cast<uint32_t>
(__rv), name ? " (" : "", name ? name : "", name ? ")" : "");
NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 5418); return; } } while (false)
;
5419
5420 bool isjs = true;
5421 rv = NS_URIChainHasFlags(
5422 urlRecord, nsIProtocolHandler::URI_OPENING_EXECUTES_SCRIPT, &isjs);
5423 NS_ENSURE_SUCCESS_VOID(rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS_VOID(%s) failed with "
"result 0x%" "X" "%s%s%s", "rv", static_cast<uint32_t>
(__rv), name ? " (" : "", name ? name : "", name ? ")" : "");
NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 5423); return; } } while (false)
;
5424
5425 if (isjs) {
5426 return;
5427 }
5428
5429 RefreshURI(urlRecord, principal, milliSeconds.value());
5430}
5431
5432static void DoCancelRefreshURITimers(nsIMutableArray* aTimerList) {
5433 if (!aTimerList) {
5434 return;
5435 }
5436
5437 uint32_t n = 0;
5438 aTimerList->GetLength(&n);
5439
5440 while (n) {
5441 nsCOMPtr<nsITimer> timer(do_QueryElementAt(aTimerList, --n));
5442
5443 aTimerList->RemoveElementAt(n); // bye bye owning timer ref
5444
5445 if (timer) {
5446 timer->Cancel();
5447 }
5448 }
5449}
5450
5451NS_IMETHODIMPnsresult
5452nsDocShell::CancelRefreshURITimers() {
5453 DoCancelRefreshURITimers(mRefreshURIList);
5454 DoCancelRefreshURITimers(mSavedRefreshURIList);
5455 DoCancelRefreshURITimers(mBFCachedRefreshURIList);
5456 mRefreshURIList = nullptr;
5457 mSavedRefreshURIList = nullptr;
5458 mBFCachedRefreshURIList = nullptr;
5459
5460 return NS_OK;
5461}
5462
5463NS_IMETHODIMPnsresult
5464nsDocShell::GetRefreshPending(bool* aResult) {
5465 if (!mRefreshURIList) {
5466 *aResult = false;
5467 return NS_OK;
5468 }
5469
5470 uint32_t count;
5471 nsresult rv = mRefreshURIList->GetLength(&count);
5472 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
5473 *aResult = (count != 0);
5474 }
5475 return rv;
5476}
5477
5478void nsDocShell::RefreshURIToQueue() {
5479 if (mRefreshURIList) {
5480 uint32_t n = 0;
5481 mRefreshURIList->GetLength(&n);
5482
5483 for (uint32_t i = 0; i < n; ++i) {
5484 nsCOMPtr<nsITimer> timer = do_QueryElementAt(mRefreshURIList, i);
5485 if (!timer) {
5486 continue; // this must be a nsRefreshURI already
5487 }
5488
5489 // Replace this timer object with a nsRefreshTimer object.
5490 nsCOMPtr<nsITimerCallback> callback;
5491 timer->GetCallback(getter_AddRefs(callback));
5492
5493 timer->Cancel();
5494
5495 mRefreshURIList->ReplaceElementAt(callback, i);
5496 }
5497 }
5498}
5499
5500NS_IMETHODIMPnsresult
5501nsDocShell::SuspendRefreshURIs() {
5502 RefreshURIToQueue();
5503
5504 // Suspend refresh URIs for our child shells as well.
5505 for (auto* child : mChildList.ForwardRange()) {
5506 nsCOMPtr<nsIDocShell> shell = do_QueryObject(child);
5507 if (shell) {
5508 shell->SuspendRefreshURIs();
5509 }
5510 }
5511
5512 return NS_OK;
5513}
5514
5515NS_IMETHODIMPnsresult
5516nsDocShell::ResumeRefreshURIs() {
5517 RefreshURIFromQueue();
5518
5519 // Resume refresh URIs for our child shells as well.
5520 for (auto* child : mChildList.ForwardRange()) {
5521 nsCOMPtr<nsIDocShell> shell = do_QueryObject(child);
5522 if (shell) {
5523 shell->ResumeRefreshURIs();
5524 }
5525 }
5526
5527 return NS_OK;
5528}
5529
5530nsresult nsDocShell::RefreshURIFromQueue() {
5531 if (!mRefreshURIList) {
5532 return NS_OK;
5533 }
5534 uint32_t n = 0;
5535 mRefreshURIList->GetLength(&n);
5536
5537 while (n) {
5538 nsCOMPtr<nsITimerCallback> refreshInfo =
5539 do_QueryElementAt(mRefreshURIList, --n);
5540
5541 if (refreshInfo) {
5542 // This is the nsRefreshTimer object, waiting to be
5543 // setup in a timer object and fired.
5544 // Create the timer and trigger it.
5545 uint32_t delay = static_cast<nsRefreshTimer*>(
5546 static_cast<nsITimerCallback*>(refreshInfo))
5547 ->GetDelay();
5548 nsCOMPtr<nsPIDOMWindowOuter> win = GetWindow();
5549 if (win) {
5550 nsCOMPtr<nsITimer> timer;
5551 NS_NewTimerWithCallback(getter_AddRefs(timer), refreshInfo, delay,
5552 nsITimer::TYPE_ONE_SHOT);
5553
5554 if (timer) {
5555 // Replace the nsRefreshTimer element in the queue with
5556 // its corresponding timer object, so that in case another
5557 // load comes through before the timer can go off, the timer will
5558 // get cancelled in CancelRefreshURITimer()
5559 mRefreshURIList->ReplaceElementAt(timer, n);
5560 }
5561 }
5562 }
5563 }
5564
5565 return NS_OK;
5566}
5567
5568static bool IsFollowupPartOfMultipart(nsIRequest* aRequest) {
5569 nsCOMPtr<nsIMultiPartChannel> multiPartChannel = do_QueryInterface(aRequest);
5570 bool firstPart = false;
5571 return multiPartChannel &&
5572 NS_SUCCEEDED(multiPartChannel->GetIsFirstPart(&firstPart))((bool)(__builtin_expect(!!(!NS_FAILED_impl(multiPartChannel->
GetIsFirstPart(&firstPart))), 1)))
&&
5573 !firstPart;
5574}
5575
5576nsresult nsDocShell::Embed(nsIDocumentViewer* aDocumentViewer,
5577 WindowGlobalChild* aWindowActor,
5578 bool aIsTransientAboutBlank, nsIRequest* aRequest,
5579 nsIURI* aPreviousURI) {
5580 // Save the LayoutHistoryState of the previous document, before
5581 // setting up new document
5582 PersistLayoutHistoryState();
5583
5584 nsresult rv = SetupNewViewer(aDocumentViewer, aWindowActor);
5585 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 5585); return rv; } } while (false)
;
5586
5587 // XXX What if SetupNewViewer fails?
5588 if (mozilla::SessionHistoryInParent() ? !!mLoadingEntry : !!mLSHE) {
5589 // Set history.state
5590 SetDocCurrentStateObj(mLSHE,
5591 mLoadingEntry ? &mLoadingEntry->mInfo : nullptr);
5592 }
5593
5594 if (mLSHE) {
5595 // Restore the editing state, if it's stored in session history.
5596 if (mLSHE->HasDetachedEditor()) {
5597 ReattachEditorToWindow(mLSHE);
5598 }
5599
5600 SetHistoryEntryAndUpdateBC(Nothing(), Some<nsISHEntry*>(mLSHE));
5601 }
5602
5603 if (!aIsTransientAboutBlank && mozilla::SessionHistoryInParent() &&
5604 !IsFollowupPartOfMultipart(aRequest)) {
5605 bool expired = false;
5606 uint32_t cacheKey = 0;
5607 nsCOMPtr<nsICacheInfoChannel> cacheChannel = do_QueryInterface(aRequest);
5608 if (cacheChannel) {
5609 // Check if the page has expired from cache
5610 uint32_t expTime = 0;
5611 cacheChannel->GetCacheTokenExpirationTime(&expTime);
5612 uint32_t now = PRTimeToSeconds(PR_Now());
5613 if (expTime <= now) {
5614 expired = true;
5615 }
5616
5617 // The checks for updating cache key are similar to the old session
5618 // history in OnNewURI. Try to update the cache key if
5619 // - we should update session history and aren't doing a session
5620 // history load.
5621 // - we're doing a forced reload.
5622 if (((!mLoadingEntry || !mLoadingEntry->mLoadIsFromSessionHistory) &&
5623 mBrowsingContext->ShouldUpdateSessionHistory(mLoadType)) ||
5624 IsForceReloadType(mLoadType)) {
5625 cacheChannel->GetCacheKey(&cacheKey);
5626 }
5627 }
5628
5629 MOZ_LOG(gSHLog, LogLevel::Debug, ("document %p Embed", this))do { const ::mozilla::LogModule* moz_real_module = gSHLog; if
((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "document %p Embed", this); } } while (0)
;
5630 MoveLoadingToActiveEntry(expired, cacheKey, aPreviousURI);
5631 }
5632
5633 bool updateHistory = true;
5634
5635 // Determine if this type of load should update history
5636 switch (mLoadType) {
5637 case LOAD_NORMAL_REPLACE:
5638 case LOAD_REFRESH_REPLACE:
5639 case LOAD_STOP_CONTENT_AND_REPLACE:
5640 case LOAD_RELOAD_BYPASS_CACHE:
5641 case LOAD_RELOAD_BYPASS_PROXY:
5642 case LOAD_RELOAD_BYPASS_PROXY_AND_CACHE:
5643 case LOAD_REPLACE_BYPASS_CACHE:
5644 updateHistory = false;
5645 break;
5646 default:
5647 break;
5648 }
5649
5650 if (!updateHistory) {
5651 SetLayoutHistoryState(nullptr);
5652 }
5653
5654 return NS_OK;
5655}
5656
5657//*****************************************************************************
5658// nsDocShell::nsIWebProgressListener
5659//*****************************************************************************
5660
5661NS_IMETHODIMPnsresult
5662nsDocShell::OnProgressChange(nsIWebProgress* aProgress, nsIRequest* aRequest,
5663 int32_t aCurSelfProgress, int32_t aMaxSelfProgress,
5664 int32_t aCurTotalProgress,
5665 int32_t aMaxTotalProgress) {
5666 // Listeners in the parent process only care about aCurTotalProgress and
5667 // aMaxTotalProgress, which is internally managed by nsDocLoader. Because of
5668 // this, we don't send progress notifications except when they are recorded by
5669 // the toplevel context, and only report them on the toplevel context in the
5670 // parent process.
5671 //
5672 // FIXME: We should track progress for out-of-process iframes and manage total
5673 // progress in the parent process for more accurate notifications.
5674 MOZ_ASSERT(do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mBrowsingContext->IsTop())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mBrowsingContext->IsTop()
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"mBrowsingContext->IsTop()" " (" "notification excluded in AddProgressListener(...) for non-toplevel BCs"
")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 5676
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mBrowsingContext->IsTop()"
") (" "notification excluded in AddProgressListener(...) for non-toplevel BCs"
")"); do { MOZ_CrashSequence(__null, 5676); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
5675 mBrowsingContext->IsTop(),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mBrowsingContext->IsTop())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mBrowsingContext->IsTop()
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"mBrowsingContext->IsTop()" " (" "notification excluded in AddProgressListener(...) for non-toplevel BCs"
")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 5676
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mBrowsingContext->IsTop()"
") (" "notification excluded in AddProgressListener(...) for non-toplevel BCs"
")"); do { MOZ_CrashSequence(__null, 5676); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
5676 "notification excluded in AddProgressListener(...) for non-toplevel BCs")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mBrowsingContext->IsTop())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mBrowsingContext->IsTop()
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"mBrowsingContext->IsTop()" " (" "notification excluded in AddProgressListener(...) for non-toplevel BCs"
")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 5676
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mBrowsingContext->IsTop()"
") (" "notification excluded in AddProgressListener(...) for non-toplevel BCs"
")"); do { MOZ_CrashSequence(__null, 5676); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5677
5678 if (nsCOMPtr<nsIWebProgressListener> listener = BCWebProgressListener()) {
5679 listener->OnProgressChange(aProgress, aRequest, aCurSelfProgress,
5680 aMaxSelfProgress, aCurTotalProgress,
5681 aMaxTotalProgress);
5682 }
5683
5684 return NS_OK;
5685}
5686
5687NS_IMETHODIMPnsresult
5688nsDocShell::OnStateChange(nsIWebProgress* aProgress, nsIRequest* aRequest,
5689 uint32_t aStateFlags, nsresult aStatus) {
5690 // If we're receiving a notification on ourselves which has at least one of
5691 // the state change flags in kStateChangeFlagFilter, also notify WebProgress
5692 // on BrowsingContextWebProgress, potentially over IPC.
5693 //
5694 // NOTE: We don't notify for bubbled notifications (aProgress != this), as
5695 // BrowsingContextWebProgress independently handles event bubbling in the
5696 // parent process.
5697 //
5698 // NOTE: We don't filter notifications when registering our listener, as
5699 // `STATE_IS_REDIRECTED_DOCUMENT` cannot be filtered for at registration time.
5700 static constexpr uint32_t kStateChangeFlagFilter =
5701 STATE_IS_NETWORK | STATE_IS_DOCUMENT | STATE_IS_WINDOW |
5702 STATE_IS_REDIRECTED_DOCUMENT;
5703 if (aProgress == this && (aStateFlags & kStateChangeFlagFilter) != 0) {
5704 if (nsCOMPtr<nsIWebProgressListener> listener = BCWebProgressListener()) {
5705 listener->OnStateChange(aProgress, aRequest, aStateFlags, aStatus);
5706 }
5707 }
5708
5709 if ((~aStateFlags & (STATE_START | STATE_IS_NETWORK)) == 0) {
5710 // Save timing statistics.
5711 nsCOMPtr<nsIChannel> channel(do_QueryInterface(aRequest));
5712 nsCOMPtr<nsIURI> uri;
5713 channel->GetURI(getter_AddRefs(uri));
5714 nsAutoCString aURI;
5715 uri->GetAsciiSpec(aURI);
5716
5717 if (this == aProgress) {
5718 mozilla::Unused << MaybeInitTiming();
5719 mTiming->NotifyFetchStart(uri,
5720 ConvertLoadTypeToNavigationType(mLoadType));
5721 // If we are starting a DocumentChannel, we need to pass the timing
5722 // statistics so that should a process switch occur, the starting type can
5723 // be passed to the new DocShell running in the other content process.
5724 if (RefPtr<DocumentChannel> docChannel = do_QueryObject(aRequest)) {
5725 docChannel->SetNavigationTiming(mTiming);
5726 }
5727 }
5728
5729 // Page has begun to load
5730 mBusyFlags = (BusyFlags)(BUSY_FLAGS_BUSY | BUSY_FLAGS_BEFORE_PAGE_LOAD);
5731
5732 if ((aStateFlags & STATE_RESTORING) == 0) {
5733 if (SessionStorePlatformCollection()) {
5734 if (IsForceReloadType(mLoadType)) {
5735 if (WindowContext* windowContext =
5736 mBrowsingContext->GetCurrentWindowContext()) {
5737 SessionStoreChild::From(windowContext->GetWindowGlobalChild())
5738 ->ResetSessionStore(mBrowsingContext,
5739 mBrowsingContext->GetSessionStoreEpoch());
5740 }
5741 }
5742 }
5743 }
5744 } else if ((~aStateFlags & (STATE_TRANSFERRING | STATE_IS_DOCUMENT)) == 0) {
5745 // Page is loading
5746 mBusyFlags = (BusyFlags)(BUSY_FLAGS_BUSY | BUSY_FLAGS_PAGE_LOADING);
5747 } else if ((aStateFlags & STATE_STOP) && (aStateFlags & STATE_IS_NETWORK)) {
5748 // Page has finished loading
5749 mBusyFlags = BUSY_FLAGS_NONE;
5750 }
5751
5752 if ((~aStateFlags & (STATE_IS_DOCUMENT | STATE_STOP)) == 0) {
5753 nsCOMPtr<nsIWebProgress> webProgress =
5754 do_QueryInterface(GetAsSupports(this));
5755 // Is the document stop notification for this document?
5756 if (aProgress == webProgress.get()) {
5757 nsCOMPtr<nsIChannel> channel(do_QueryInterface(aRequest));
5758 EndPageLoad(aProgress, channel, aStatus);
5759 }
5760 }
5761 // note that redirect state changes will go through here as well, but it
5762 // is better to handle those in OnRedirectStateChange where more
5763 // information is available.
5764 return NS_OK;
5765}
5766
5767NS_IMETHODIMPnsresult
5768nsDocShell::OnLocationChange(nsIWebProgress* aProgress, nsIRequest* aRequest,
5769 nsIURI* aURI, uint32_t aFlags) {
5770 // If we're receiving a notification on ourselves, also notify WebProgress on
5771 // BrowsingContextWebProgress, potentially over IPC.
5772 //
5773 // NOTE: We don't notify for bubbled notifications (aProgress != this), as
5774 // BrowsingContextWebProgress independently handles event bubbling in the
5775 // parent process.
5776 //
5777 // NOTE: Tests depend on this happening before UpdateSecurityState.
5778 if (aProgress == this) {
5779 if (nsCOMPtr<nsIWebProgressListener> listener = BCWebProgressListener()) {
5780 listener->OnLocationChange(aProgress, aRequest, aURI, aFlags);
5781 }
5782 }
5783
5784 // Since we've now changed Documents, notify the BrowsingContext that we've
5785 // changed. Ideally we'd just let the BrowsingContext do this when it
5786 // changes the current window global, but that happens before this and we
5787 // have a lot of tests that depend on the specific ordering of messages.
5788 bool isTopLevel = false;
5789 if (XRE_IsParentProcess() &&
5790 !(aFlags & nsIWebProgressListener::LOCATION_CHANGE_SAME_DOCUMENT) &&
5791 NS_SUCCEEDED(aProgress->GetIsTopLevel(&isTopLevel))((bool)(__builtin_expect(!!(!NS_FAILED_impl(aProgress->GetIsTopLevel
(&isTopLevel))), 1)))
&& isTopLevel) {
5792 GetBrowsingContext()->Canonical()->UpdateSecurityState();
5793 }
5794 return NS_OK;
5795}
5796
5797void nsDocShell::OnRedirectStateChange(nsIChannel* aOldChannel,
5798 nsIChannel* aNewChannel,
5799 uint32_t aRedirectFlags,
5800 uint32_t aStateFlags) {
5801 NS_ASSERTION(aStateFlags & STATE_REDIRECTING,do { if (!(aStateFlags & STATE_REDIRECTING)) { NS_DebugBreak
(NS_DEBUG_ASSERTION, "Calling OnRedirectStateChange when there is no redirect"
, "aStateFlags & STATE_REDIRECTING", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 5802); MOZ_PretendNoReturn(); } } while (0)
5802 "Calling OnRedirectStateChange when there is no redirect")do { if (!(aStateFlags & STATE_REDIRECTING)) { NS_DebugBreak
(NS_DEBUG_ASSERTION, "Calling OnRedirectStateChange when there is no redirect"
, "aStateFlags & STATE_REDIRECTING", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 5802); MOZ_PretendNoReturn(); } } while (0)
;
5803
5804 if (!(aStateFlags & STATE_IS_DOCUMENT)) {
5805 return; // not a toplevel document
5806 }
5807
5808 nsCOMPtr<nsIURI> oldURI, newURI;
5809 aOldChannel->GetURI(getter_AddRefs(oldURI));
5810 aNewChannel->GetURI(getter_AddRefs(newURI));
5811 if (!oldURI || !newURI) {
5812 return;
5813 }
5814
5815 // DocumentChannel adds redirect chain to global history in the parent
5816 // process. The redirect chain can't be queried from the content process, so
5817 // there's no need to update global history here.
5818 RefPtr<DocumentChannel> docChannel = do_QueryObject(aOldChannel);
5819 if (!docChannel) {
5820 // Below a URI visit is saved (see AddURIVisit method doc).
5821 // The visit chain looks something like:
5822 // ...
5823 // Site N - 1
5824 // => Site N
5825 // (redirect to =>) Site N + 1 (we are here!)
5826
5827 // Get N - 1 and transition type
5828 nsCOMPtr<nsIURI> previousURI;
5829 uint32_t previousFlags = 0;
5830 ExtractLastVisit(aOldChannel, getter_AddRefs(previousURI), &previousFlags);
5831
5832 if (aRedirectFlags & nsIChannelEventSink::REDIRECT_INTERNAL ||
5833 net::ChannelIsPost(aOldChannel)) {
5834 // 1. Internal redirects are ignored because they are specific to the
5835 // channel implementation.
5836 // 2. POSTs are not saved by global history.
5837 //
5838 // Regardless, we need to propagate the previous visit to the new
5839 // channel.
5840 SaveLastVisit(aNewChannel, previousURI, previousFlags);
5841 } else {
5842 // Get the HTTP response code, if available.
5843 uint32_t responseStatus = 0;
5844 nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(aOldChannel);
5845 if (httpChannel) {
5846 Unused << httpChannel->GetResponseStatus(&responseStatus);
5847 }
5848
5849 // Add visit N -1 => N
5850 AddURIVisit(oldURI, previousURI, previousFlags, responseStatus);
5851
5852 // Since N + 1 could be the final destination, we will not save N => N + 1
5853 // here. OnNewURI will do that, so we will cache it.
5854 SaveLastVisit(aNewChannel, oldURI, aRedirectFlags);
5855 }
5856 }
5857
5858 if (!(aRedirectFlags & nsIChannelEventSink::REDIRECT_INTERNAL) &&
5859 mLoadType & (LOAD_CMD_RELOAD | LOAD_CMD_HISTORY)) {
5860 mLoadType = LOAD_NORMAL_REPLACE;
5861 SetHistoryEntryAndUpdateBC(Some(nullptr), Nothing());
5862 }
5863}
5864
5865NS_IMETHODIMPnsresult
5866nsDocShell::OnStatusChange(nsIWebProgress* aWebProgress, nsIRequest* aRequest,
5867 nsresult aStatus, const char16_t* aMessage) {
5868 // If we're receiving a notification on ourselves, also notify WebProgress on
5869 // BrowsingContextWebProgress, potentially over IPC.
5870 //
5871 // NOTE: We don't notify for bubbled notifications (aWebProgress != this), as
5872 // BrowsingContextWebProgress independently handles event bubbling in the
5873 // parent process.
5874 if (aWebProgress == this) {
5875 if (nsCOMPtr<nsIWebProgressListener> listener = BCWebProgressListener()) {
5876 listener->OnStatusChange(aWebProgress, aRequest, aStatus, aMessage);
5877 }
5878 }
5879
5880 return NS_OK;
5881}
5882
5883NS_IMETHODIMPnsresult
5884nsDocShell::OnSecurityChange(nsIWebProgress* aWebProgress, nsIRequest* aRequest,
5885 uint32_t aState) {
5886 // If we're receiving a notification on ourselves, also notify WebProgress on
5887 // BrowsingContextWebProgress, potentially over IPC.
5888 //
5889 // NOTE: We don't notify for bubbled notifications (aWebProgress != this), as
5890 // BrowsingContextWebProgress independently handles event bubbling in the
5891 // parent process.
5892 if (aWebProgress == this) {
5893 if (nsCOMPtr<nsIWebProgressListener> listener = BCWebProgressListener()) {
5894 listener->OnSecurityChange(aWebProgress, aRequest, aState);
5895 }
5896 }
5897
5898 return NS_OK;
5899}
5900
5901NS_IMETHODIMPnsresult
5902nsDocShell::OnContentBlockingEvent(nsIWebProgress* aWebProgress,
5903 nsIRequest* aRequest, uint32_t aEvent) {
5904 MOZ_ASSERT_UNREACHABLE("notification excluded in AddProgressListener(...)")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "MOZ_ASSERT_UNREACHABLE: "
"notification excluded in AddProgressListener(...)" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 5904); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "notification excluded in AddProgressListener(...)"
")"); do { MOZ_CrashSequence(__null, 5904); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5905 return NS_OK;
5906}
5907
5908already_AddRefed<nsIWebProgressListener> nsDocShell::BCWebProgressListener() {
5909 // If this BrowsingContext has been replaced, we should discard any
5910 // notifications which would otherwise be delivered in-process.
5911 if (XRE_IsParentProcess() && mBrowsingContext->Canonical()->IsReplaced()) {
5912 return nullptr;
5913 }
5914
5915 // Create a nsBrowserStatusFilter to perform some throttling of
5916 // OnProgressChange and OnStatusChange notifications which are delivered to
5917 // our BCWebProgress listener. This reduces the amount of IPC traffic.
5918 if (!mBCWebProgressStatusFilter && !mIsBeingDestroyed) {
5919 nsCOMPtr<nsIWebProgressListener> innerListener;
5920 if (XRE_IsParentProcess()) {
5921 innerListener = mBrowsingContext->Canonical()->GetWebProgress();
5922 } else {
5923 innerListener = do_QueryReferent(mBrowserChild);
5924 }
5925 if (innerListener) {
5926 // NOTE: We need to disable filtering of StateChange events here, as
5927 // listeners on BrowsingContextWebProgress may depend on state change
5928 // notifications are otherwise filtered.
5929 // NOTE: Unlike other nsIWebProgress types, nsBrowserStatusFilter holds a
5930 // strong cycle-collected reference to the inner listener.
5931 mBCWebProgressStatusFilter =
5932 new nsBrowserStatusFilter(/* aDisableStateChangeFilters */ true);
5933 mBCWebProgressStatusFilter->AddProgressListener(
5934 innerListener, nsIWebProgress::NOTIFY_ALL);
5935 }
5936 }
5937
5938 return do_AddRef(mBCWebProgressStatusFilter);
5939}
5940
5941already_AddRefed<nsIURIFixupInfo> nsDocShell::KeywordToURI(
5942 const nsACString& aKeyword, bool aIsPrivateContext) {
5943 nsCOMPtr<nsIURIFixupInfo> info;
5944 if (!XRE_IsContentProcess()) {
5945 nsCOMPtr<nsIURIFixup> uriFixup = components::URIFixup::Service();
5946 if (uriFixup) {
5947 uriFixup->KeywordToURI(aKeyword, aIsPrivateContext, getter_AddRefs(info));
5948 }
5949 }
5950 return info.forget();
5951}
5952
5953/* static */
5954already_AddRefed<nsIURI> nsDocShell::MaybeFixBadCertDomainErrorURI(
5955 nsIChannel* aChannel, nsIURI* aUrl) {
5956 if (!aChannel) {
5957 return nullptr;
5958 }
5959
5960 nsresult rv = NS_OK;
5961 nsAutoCString host;
5962 rv = aUrl->GetAsciiHost(host);
5963 if (NS_WARN_IF(NS_FAILED(rv))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(rv
)), 0))), "NS_FAILED(rv)", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 5963)
) {
5964 return nullptr;
5965 }
5966
5967 // Return if fixup enable pref is turned off.
5968 if (!mozilla::StaticPrefs::security_bad_cert_domain_error_url_fix_enabled()) {
5969 return nullptr;
5970 }
5971
5972 // Return if scheme is not HTTPS.
5973 if (!aUrl->SchemeIs("https")) {
5974 return nullptr;
5975 }
5976
5977 nsCOMPtr<nsILoadInfo> info = aChannel->LoadInfo();
5978 if (!info) {
5979 return nullptr;
5980 }
5981
5982 // Skip doing the fixup if our channel was redirected, because we
5983 // shouldn't be guessing things about the post-redirect URI.
5984 if (!info->RedirectChain().IsEmpty()) {
5985 return nullptr;
5986 }
5987
5988 int32_t port = 0;
5989 rv = aUrl->GetPort(&port);
5990 if (NS_WARN_IF(NS_FAILED(rv))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(rv
)), 0))), "NS_FAILED(rv)", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 5990)
) {
5991 return nullptr;
5992 }
5993
5994 // Don't fix up hosts with ports.
5995 if (port != -1) {
5996 return nullptr;
5997 }
5998
5999 // Don't fix up localhost url.
6000 if (host == "localhost") {
6001 return nullptr;
6002 }
6003
6004 // Don't fix up hostnames with IP address.
6005 if (net_IsValidIPv4Addr(host) || net_IsValidIPv6Addr(host)) {
6006 return nullptr;
6007 }
6008
6009 nsAutoCString userPass;
6010 rv = aUrl->GetUserPass(userPass);
6011 if (NS_WARN_IF(NS_FAILED(rv))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(rv
)), 0))), "NS_FAILED(rv)", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 6011)
) {
6012 return nullptr;
6013 }
6014
6015 // Security - URLs with user / password info should NOT be modified.
6016 if (!userPass.IsEmpty()) {
6017 return nullptr;
6018 }
6019
6020 nsCOMPtr<nsITransportSecurityInfo> tsi;
6021 rv = aChannel->GetSecurityInfo(getter_AddRefs(tsi));
6022 if (NS_WARN_IF(NS_FAILED(rv))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(rv
)), 0))), "NS_FAILED(rv)", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 6022)
) {
6023 return nullptr;
6024 }
6025
6026 if (NS_WARN_IF(!tsi)NS_warn_if_impl(!tsi, "!tsi", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 6026)
) {
6027 return nullptr;
6028 }
6029
6030 nsCOMPtr<nsIX509Cert> cert;
6031 rv = tsi->GetServerCert(getter_AddRefs(cert));
6032 if (NS_WARN_IF(NS_FAILED(rv) || !cert)NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(rv
)), 0))) || !cert, "NS_FAILED(rv) || !cert", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 6032)
) {
6033 return nullptr;
6034 }
6035
6036 nsTArray<uint8_t> certBytes;
6037 rv = cert->GetRawDER(certBytes);
6038 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
6039 return nullptr;
6040 }
6041
6042 mozilla::pkix::Input serverCertInput;
6043 mozilla::pkix::Result result =
6044 serverCertInput.Init(certBytes.Elements(), certBytes.Length());
6045 if (result != mozilla::pkix::Success) {
6046 return nullptr;
6047 }
6048
6049 constexpr auto wwwPrefix = "www."_ns;
6050 nsAutoCString newHost;
6051 if (StringBeginsWith(host, wwwPrefix)) {
6052 // Try www.example.com -> example.com
6053 newHost.Assign(Substring(host, wwwPrefix.Length()));
6054 } else {
6055 // Try example.com -> www.example.com
6056 newHost.Assign(wwwPrefix);
6057 newHost.Append(host);
6058 }
6059
6060 mozilla::pkix::Input newHostInput;
6061 result = newHostInput.Init(
6062 BitwiseCast<const uint8_t*, const char*>(newHost.BeginReading()),
6063 newHost.Length());
6064 if (result != mozilla::pkix::Success) {
6065 return nullptr;
6066 }
6067
6068 // Because certificate verification returned Result::ERROR_BAD_CERT_DOMAIN /
6069 // SSL_ERROR_BAD_CERT_DOMAIN, a chain was built and we know whether or not
6070 // the root was a built-in.
6071 bool rootIsBuiltIn;
6072 if (NS_FAILED(tsi->GetIsBuiltCertChainRootBuiltInRoot(&rootIsBuiltIn))((bool)(__builtin_expect(!!(NS_FAILED_impl(tsi->GetIsBuiltCertChainRootBuiltInRoot
(&rootIsBuiltIn))), 0)))
) {
6073 return nullptr;
6074 }
6075 mozilla::psm::SkipInvalidSANsForNonBuiltInRootsPolicy nameMatchingPolicy(
6076 rootIsBuiltIn);
6077
6078 // Check if the certificate is valid for the new hostname.
6079 result = mozilla::pkix::CheckCertHostname(serverCertInput, newHostInput,
6080 nameMatchingPolicy);
6081 if (result != mozilla::pkix::Success) {
6082 return nullptr;
6083 }
6084
6085 nsCOMPtr<nsIURI> newURI;
6086 Unused << NS_MutateURI(aUrl).SetHost(newHost).Finalize(
6087 getter_AddRefs(newURI));
6088
6089 return newURI.forget();
6090}
6091
6092/* static */
6093already_AddRefed<nsIURI> nsDocShell::AttemptURIFixup(
6094 nsIChannel* aChannel, nsresult aStatus,
6095 const mozilla::Maybe<nsCString>& aOriginalURIString, uint32_t aLoadType,
6096 bool aIsTopFrame, bool aAllowKeywordFixup, bool aUsePrivateBrowsing,
6097 bool aNotifyKeywordSearchLoading, nsIInputStream** aNewPostData,
6098 nsILoadInfo::SchemelessInputType* outSchemelessInput) {
6099 if (aStatus != NS_ERROR_UNKNOWN_HOST && aStatus != NS_ERROR_NET_RESET &&
6100 aStatus != NS_ERROR_CONNECTION_REFUSED &&
6101 aStatus !=
6102 mozilla::psm::GetXPCOMFromNSSError(SSL_ERROR_BAD_CERT_DOMAIN)) {
6103 return nullptr;
6104 }
6105
6106 if (!(aLoadType == LOAD_NORMAL && aIsTopFrame) && !aAllowKeywordFixup) {
6107 return nullptr;
6108 }
6109
6110 nsCOMPtr<nsIURI> url;
6111 nsresult rv = aChannel->GetURI(getter_AddRefs(url));
6112 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
6113 return nullptr;
6114 }
6115
6116 //
6117 // Try and make an alternative URI from the old one
6118 //
6119 nsCOMPtr<nsIURI> newURI;
6120 nsCOMPtr<nsIInputStream> newPostData;
6121
6122 nsAutoCString oldSpec;
6123 url->GetSpec(oldSpec);
6124
6125 //
6126 // First try keyword fixup
6127 //
6128 nsAutoString keywordProviderName, keywordAsSent;
6129 if (aStatus == NS_ERROR_UNKNOWN_HOST && aAllowKeywordFixup) {
6130 // we should only perform a keyword search under the following
6131 // conditions:
6132 // (0) Pref keyword.enabled is true
6133 // (1) the url scheme is http (or https)
6134 // (2) the url does not have a protocol scheme
6135 // If we don't enforce such a policy, then we end up doing
6136 // keyword searchs on urls we don't intend like imap, file,
6137 // mailbox, etc. This could lead to a security problem where we
6138 // send data to the keyword server that we shouldn't be.
6139 // Someone needs to clean up keywords in general so we can
6140 // determine on a per url basis if we want keywords
6141 // enabled...this is just a bandaid...
6142 if (Preferences::GetBool("keyword.enabled", false) &&
6143 net::SchemeIsHttpOrHttps(url)) {
6144 bool attemptFixup = false;
6145 nsAutoCString host;
6146 Unused << url->GetHost(host);
6147 if (host.FindChar('.') == kNotFound) {
6148 attemptFixup = true;
6149 } else {
6150 // For domains with dots, we check the public suffix validity.
6151 nsCOMPtr<nsIEffectiveTLDService> tldService =
6152 do_GetService(NS_EFFECTIVETLDSERVICE_CONTRACTID"@mozilla.org/network/effective-tld-service;1");
6153 if (tldService) {
6154 nsAutoCString suffix;
6155 attemptFixup =
6156 NS_SUCCEEDED(tldService->GetKnownPublicSuffix(url, suffix))((bool)(__builtin_expect(!!(!NS_FAILED_impl(tldService->GetKnownPublicSuffix
(url, suffix))), 1)))
&&
6157 suffix.IsEmpty();
6158 }
6159 }
6160 if (attemptFixup) {
6161 nsCOMPtr<nsIURIFixupInfo> info;
6162 // only send non-qualified hosts to the keyword server
6163 if (aOriginalURIString && !aOriginalURIString->IsEmpty()) {
6164 info = KeywordToURI(*aOriginalURIString, aUsePrivateBrowsing);
6165 } else {
6166 //
6167 // If this string was passed through nsStandardURL by
6168 // chance, then it may have been converted from UTF-8 to
6169 // Punycode, which would result in a completely bogus keyword
6170 // query. Here we try to recover the original Unicode
6171 // value, but this is not 100% correct since the value may
6172 // have been normalized per the IDN normalization rules.
6173 //
6174 // Since we don't have access to the exact original string
6175 // that was entered by the user, this will just have to do.
6176 nsAutoCString utf8Host;
6177 mozilla_net_recover_keyword_from_punycode(&host, &utf8Host);
6178 info = KeywordToURI(utf8Host, aUsePrivateBrowsing);
6179 }
6180 if (info) {
6181 info->GetPreferredURI(getter_AddRefs(newURI));
6182 info->GetSchemelessInput(outSchemelessInput);
6183 if (newURI) {
6184 info->GetKeywordAsSent(keywordAsSent);
6185 info->GetKeywordProviderName(keywordProviderName);
6186 info->GetPostData(getter_AddRefs(newPostData));
6187 }
6188 }
6189 }
6190 }
6191 }
6192
6193 //
6194 // Now try change the address, e.g. turn http://foo into
6195 // http://www.foo.com, and if that doesn't work try https with
6196 // https://foo and https://www.foo.com.
6197 //
6198 if (aStatus == NS_ERROR_UNKNOWN_HOST || aStatus == NS_ERROR_NET_RESET) {
6199 // Skip fixup for anything except a normal document load
6200 // operation on the topframe.
6201 bool doCreateAlternate = aLoadType == LOAD_NORMAL && aIsTopFrame;
6202
6203 if (doCreateAlternate) {
6204 nsCOMPtr<nsILoadInfo> loadInfo = aChannel->LoadInfo();
6205 nsIPrincipal* principal = loadInfo->TriggeringPrincipal();
6206 // Only do this if our channel was loaded directly by the user from the
6207 // URL bar or similar (system principal) and not redirected, because we
6208 // shouldn't be guessing things about links from other sites, or a
6209 // post-redirect URI.
6210 doCreateAlternate = principal && principal->IsSystemPrincipal() &&
6211 loadInfo->RedirectChain().IsEmpty();
6212 }
6213 // Test if keyword lookup produced a new URI or not
6214 if (doCreateAlternate && newURI) {
6215 bool sameURI = false;
6216 url->Equals(newURI, &sameURI);
6217 if (!sameURI) {
6218 // Keyword lookup made a new URI so no need to try
6219 // an alternate one.
6220 doCreateAlternate = false;
6221 }
6222 }
6223 if (doCreateAlternate) {
6224 newURI = nullptr;
6225 newPostData = nullptr;
6226 keywordProviderName.Truncate();
6227 keywordAsSent.Truncate();
6228 nsCOMPtr<nsIURIFixup> uriFixup = components::URIFixup::Service();
6229 if (uriFixup) {
6230 nsCOMPtr<nsIURIFixupInfo> fixupInfo;
6231 uriFixup->GetFixupURIInfo(oldSpec, nsIURIFixup::FIXUP_FLAG_NONE,
6232 getter_AddRefs(fixupInfo));
6233 if (fixupInfo) {
6234 fixupInfo->GetPreferredURI(getter_AddRefs(newURI));
6235 }
6236 }
6237 }
6238 } else if (aStatus == NS_ERROR_CONNECTION_REFUSED &&
6239 Preferences::GetBool("browser.fixup.fallback-to-https", false)) {
6240 // Try HTTPS, since http didn't work
6241 if (url->SchemeIs("http")) {
6242 int32_t port = 0;
6243 url->GetPort(&port);
6244
6245 // Fall back to HTTPS only if port is default
6246 if (port == -1) {
6247 newURI = nullptr;
6248 newPostData = nullptr;
6249 Unused << NS_MutateURI(url)
6250 .SetScheme("https"_ns)
6251 .Finalize(getter_AddRefs(newURI));
6252 }
6253 }
6254 }
6255
6256 // If we have a SSL_ERROR_BAD_CERT_DOMAIN error, try adding or removing
6257 // "www." to/from the beginning of the domain name to see if we can avoid
6258 // showing the cert error page. For example, https://example.com ->
6259 // https://www.example.com or https://www.example.com -> https://example.com.
6260 if (aStatus ==
6261 mozilla::psm::GetXPCOMFromNSSError(SSL_ERROR_BAD_CERT_DOMAIN)) {
6262 newPostData = nullptr;
6263 newURI = MaybeFixBadCertDomainErrorURI(aChannel, url);
6264 }
6265
6266 // Did we make a new URI that is different to the old one? If so
6267 // load it.
6268 //
6269 if (newURI) {
6270 // Make sure the new URI is different from the old one,
6271 // otherwise there's little point trying to load it again.
6272 bool sameURI = false;
6273 url->Equals(newURI, &sameURI);
6274 if (!sameURI) {
6275 if (aNewPostData) {
6276 newPostData.forget(aNewPostData);
6277 }
6278 if (aNotifyKeywordSearchLoading) {
6279 // This notification is meant for Firefox Health Report so it
6280 // can increment counts from the search engine
6281 MaybeNotifyKeywordSearchLoading(keywordProviderName, keywordAsSent);
6282 }
6283 return newURI.forget();
6284 }
6285 }
6286
6287 return nullptr;
6288}
6289
6290nsresult nsDocShell::FilterStatusForErrorPage(
6291 nsresult aStatus, nsIChannel* aChannel, uint32_t aLoadType,
6292 bool aIsTopFrame, bool aUseErrorPages,
6293 bool* aSkippedUnknownProtocolNavigation) {
6294 // Errors to be shown only on top-level frames
6295 if ((aStatus == NS_ERROR_UNKNOWN_HOST ||
6296 aStatus == NS_ERROR_CONNECTION_REFUSED ||
6297 aStatus == NS_ERROR_UNKNOWN_PROXY_HOST ||
6298 aStatus == NS_ERROR_PROXY_CONNECTION_REFUSED ||
6299 aStatus == NS_ERROR_PROXY_FORBIDDEN ||
6300 aStatus == NS_ERROR_PROXY_NOT_IMPLEMENTED ||
6301 aStatus == NS_ERROR_PROXY_AUTHENTICATION_FAILED ||
6302 aStatus == NS_ERROR_PROXY_TOO_MANY_REQUESTS ||
6303 aStatus == NS_ERROR_MALFORMED_URI ||
6304 aStatus == NS_ERROR_BLOCKED_BY_POLICY ||
6305 aStatus == NS_ERROR_DOM_COOP_FAILED ||
6306 aStatus == NS_ERROR_DOM_COEP_FAILED ||
6307 aStatus == NS_ERROR_DOM_INVALID_HEADER_VALUE) &&
6308 (aIsTopFrame || aUseErrorPages)) {
6309 return aStatus;
6310 }
6311
6312 if (aStatus == NS_ERROR_NET_TIMEOUT ||
6313 aStatus == NS_ERROR_NET_TIMEOUT_EXTERNAL ||
6314 aStatus == NS_ERROR_NET_EMPTY_RESPONSE ||
6315 aStatus == NS_ERROR_NET_ERROR_RESPONSE ||
6316 aStatus == NS_ERROR_PROXY_GATEWAY_TIMEOUT ||
6317 aStatus == NS_ERROR_REDIRECT_LOOP ||
6318 aStatus == NS_ERROR_UNKNOWN_SOCKET_TYPE ||
6319 aStatus == NS_ERROR_NET_INTERRUPT || aStatus == NS_ERROR_NET_RESET ||
6320 aStatus == NS_ERROR_PROXY_BAD_GATEWAY || aStatus == NS_ERROR_OFFLINE ||
6321 aStatus == NS_ERROR_MALWARE_URI || aStatus == NS_ERROR_PHISHING_URI ||
6322 aStatus == NS_ERROR_UNWANTED_URI || aStatus == NS_ERROR_HARMFUL_URI ||
6323 aStatus == NS_ERROR_UNSAFE_CONTENT_TYPE ||
6324 aStatus == NS_ERROR_INTERCEPTION_FAILED ||
6325 aStatus == NS_ERROR_NET_INADEQUATE_SECURITY ||
6326 aStatus == NS_ERROR_NET_HTTP2_SENT_GOAWAY ||
6327 aStatus == NS_ERROR_NET_HTTP3_PROTOCOL_ERROR ||
6328 aStatus == NS_ERROR_BASIC_HTTP_AUTH_DISABLED ||
6329 aStatus == NS_ERROR_DOM_BAD_URI || aStatus == NS_ERROR_FILE_NOT_FOUND ||
6330 aStatus == NS_ERROR_FILE_ACCESS_DENIED ||
6331 aStatus == NS_ERROR_CORRUPTED_CONTENT ||
6332 aStatus == NS_ERROR_INVALID_CONTENT_ENCODING ||
6333 NS_ERROR_GET_MODULE(aStatus) == NS_ERROR_MODULE_SECURITY21) {
6334 // Errors to be shown for any frame
6335 return aStatus;
6336 }
6337
6338 if (aStatus == NS_ERROR_UNKNOWN_PROTOCOL) {
6339 // For unknown protocols we only display an error if the load is triggered
6340 // by the browser itself. Showing the error for page-triggered navigations
6341 // causes annoying behavior for users when a page tries to open an external
6342 // app which has not been installed, see bug 1528305. A missing WebExtension
6343 // protocol handlers will however always load the error page, as it is not
6344 // expected to be opened externally, see bug 1921426.
6345 nsCOMPtr<nsILoadInfo> info = aChannel->LoadInfo();
6346 if (!info->TriggeringPrincipal()->IsSystemPrincipal() &&
6347 !BasePrincipal::Cast(info->TriggeringPrincipal())->AddonPolicy()) {
6348 if (aSkippedUnknownProtocolNavigation) {
6349 *aSkippedUnknownProtocolNavigation = true;
6350 }
6351 return NS_OK;
6352 }
6353 return aStatus;
6354 }
6355
6356 if (aStatus == NS_ERROR_DOCUMENT_NOT_CACHED) {
6357 // Non-caching channels will simply return NS_ERROR_OFFLINE.
6358 // Caching channels would have to look at their flags to work
6359 // out which error to return. Or we can fix up the error here.
6360 if (!(aLoadType & LOAD_CMD_HISTORY)) {
6361 return NS_ERROR_OFFLINE;
6362 }
6363 return aStatus;
6364 }
6365
6366 return NS_OK;
6367}
6368
6369nsresult nsDocShell::EndPageLoad(nsIWebProgress* aProgress,
6370 nsIChannel* aChannel, nsresult aStatus) {
6371 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)
6372 ("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)
6373 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)
;
6374 if (!aChannel) {
6375 return NS_ERROR_NULL_POINTER;
6376 }
6377
6378 // Make sure to discard the initial client if we never created the initial
6379 // about:blank document. Do this before possibly returning from the method
6380 // due to an error.
6381 mInitialClientSource.reset();
6382
6383 nsCOMPtr<nsIConsoleReportCollector> reporter = do_QueryInterface(aChannel);
6384 if (reporter) {
6385 nsCOMPtr<nsILoadGroup> loadGroup;
6386 aChannel->GetLoadGroup(getter_AddRefs(loadGroup));
6387 if (loadGroup) {
6388 reporter->FlushConsoleReports(loadGroup);
6389 } else {
6390 reporter->FlushConsoleReports(GetDocument());
6391 }
6392 }
6393
6394 nsCOMPtr<nsIURI> url;
6395 nsresult rv = aChannel->GetURI(getter_AddRefs(url));
6396 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
6397 return rv;
6398 }
6399
6400 nsCOMPtr<nsITimedChannel> timingChannel = do_QueryInterface(aChannel);
6401 if (timingChannel) {
6402 TimeStamp channelCreationTime;
6403 rv = timingChannel->GetChannelCreation(&channelCreationTime);
6404 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && !channelCreationTime.IsNull()) {
6405 glean::performance_page::total_content_page_load.AccumulateRawDuration(
6406 TimeStamp::Now() - channelCreationTime);
6407 }
6408 }
6409
6410 // Timing is picked up by the window, we don't need it anymore
6411 mTiming = nullptr;
6412
6413 // clean up reload state for meta charset
6414 if (eCharsetReloadRequested == mCharsetReloadState) {
6415 mCharsetReloadState = eCharsetReloadStopOrigional;
6416 } else {
6417 mCharsetReloadState = eCharsetReloadInit;
6418 }
6419
6420 // Save a pointer to the currently-loading history entry.
6421 // nsDocShell::EndPageLoad will clear mLSHE, but we may need this history
6422 // entry further down in this method.
6423 nsCOMPtr<nsISHEntry> loadingSHE = mLSHE;
6424 mozilla::Unused << loadingSHE; // XXX: Not sure if we need this anymore
6425
6426 //
6427 // one of many safeguards that prevent death and destruction if
6428 // someone is so very very rude as to bring this window down
6429 // during this load handler.
6430 //
6431 nsCOMPtr<nsIDocShell> kungFuDeathGrip(this);
6432
6433 // Notify the DocumentViewer that the Document has finished loading. This
6434 // will cause any OnLoad(...) and PopState(...) handlers to fire.
6435 if (!mEODForCurrentDocument && mDocumentViewer) {
6436 mIsExecutingOnLoadHandler = true;
6437 nsCOMPtr<nsIDocumentViewer> viewer = mDocumentViewer;
6438 viewer->LoadComplete(aStatus);
6439 mIsExecutingOnLoadHandler = false;
6440
6441 mEODForCurrentDocument = true;
6442 }
6443 /* Check if the httpChannel has any cache-control related response headers,
6444 * like no-store, no-cache. If so, update SHEntry so that
6445 * when a user goes back/forward to this page, we appropriately do
6446 * form value restoration or load from server.
6447 */
6448 nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(aChannel));
6449 if (!httpChannel) {
6450 // HttpChannel could be hiding underneath a Multipart channel.
6451 GetHttpChannel(aChannel, getter_AddRefs(httpChannel));
6452 }
6453
6454 if (httpChannel) {
6455 // figure out if SH should be saving layout state.
6456 bool discardLayoutState = ShouldDiscardLayoutState(httpChannel);
6457 if (mLSHE && discardLayoutState && (mLoadType & LOAD_CMD_NORMAL) &&
6458 (mLoadType != LOAD_BYPASS_HISTORY) && (mLoadType != LOAD_ERROR_PAGE)) {
6459 mLSHE->SetSaveLayoutStateFlag(false);
6460 }
6461 }
6462
6463 // Clear mLSHE after calling the onLoadHandlers. This way, if the
6464 // onLoadHandler tries to load something different in
6465 // itself or one of its children, we can deal with it appropriately.
6466 if (mLSHE) {
6467 mLSHE->SetLoadType(LOAD_HISTORY);
6468
6469 // Clear the mLSHE reference to indicate document loading is done one
6470 // way or another.
6471 SetHistoryEntryAndUpdateBC(Some(nullptr), Nothing());
6472 }
6473 mActiveEntryIsLoadingFromSessionHistory = false;
6474
6475 // if there's a refresh header in the channel, this method
6476 // will set it up for us.
6477 if (mBrowsingContext->IsActive() || !mDisableMetaRefreshWhenInactive)
6478 RefreshURIFromQueue();
6479
6480 // Test whether this is the top frame or a subframe
6481 bool isTopFrame = mBrowsingContext->IsTop();
6482
6483 bool hadErrorStatus = false;
6484 // If status code indicates an error it means that DocumentChannel already
6485 // tried to fixup the uri and failed. Throw an error dialog box here.
6486 if (NS_FAILED(aStatus)((bool)(__builtin_expect(!!(NS_FAILED_impl(aStatus)), 0)))) {
6487 // If we got CONTENT_BLOCKED from EndPageLoad, then we need to fire
6488 // the error event to our embedder, since tests are relying on this.
6489 // The error event is usually fired by the caller of InternalLoad, but
6490 // this particular error can happen asynchronously.
6491 // Bug 1629201 is filed for having much clearer decision making around
6492 // which cases need error events.
6493 bool fireFrameErrorEvent = (aStatus == NS_ERROR_CONTENT_BLOCKED_SHOW_ALT ||
6494 aStatus == NS_ERROR_CONTENT_BLOCKED);
6495 UnblockEmbedderLoadEventForFailure(fireFrameErrorEvent);
6496
6497 bool skippedUnknownProtocolNavigation = false;
6498 aStatus = FilterStatusForErrorPage(aStatus, aChannel, mLoadType, isTopFrame,
6499 mBrowsingContext->GetUseErrorPages(),
6500 &skippedUnknownProtocolNavigation);
6501 hadErrorStatus = true;
6502 if (NS_FAILED(aStatus)((bool)(__builtin_expect(!!(NS_FAILED_impl(aStatus)), 0)))) {
6503 if (!mIsBeingDestroyed) {
6504 DisplayLoadError(aStatus, url, nullptr, aChannel);
6505 }
6506 } else if (skippedUnknownProtocolNavigation) {
6507 nsAutoCString sanitized;
6508 nsTArray<nsString> params;
6509 if (NS_SUCCEEDED(NS_GetSanitizedURIStringFromURI(url, sanitized))((bool)(__builtin_expect(!!(!NS_FAILED_impl(NS_GetSanitizedURIStringFromURI
(url, sanitized))), 1)))
) {
6510 params.AppendElement(NS_ConvertUTF8toUTF16(sanitized));
6511 } else {
6512 params.AppendElement(u"(unknown uri)"_ns);
6513 }
6514 nsContentUtils::ReportToConsole(
6515 nsIScriptError::warningFlag, "DOM"_ns, GetExtantDocument(),
6516 nsContentUtils::eDOM_PROPERTIES, "UnknownProtocolNavigationPrevented",
6517 params);
6518 }
6519 } else {
6520 // If we have a host
6521 nsCOMPtr<nsILoadInfo> loadInfo = aChannel->LoadInfo();
6522 PredictorLearnRedirect(url, aChannel, loadInfo->GetOriginAttributes());
6523 }
6524
6525 if (hadErrorStatus) {
6526 // Don't send session store updates if the reason EndPageLoad was called is
6527 // because we are process switching. Sometimes the update takes too long and
6528 // incorrectly overrides session store data from the following load.
6529 return NS_OK;
6530 }
6531 if (SessionStorePlatformCollection()) {
6532 if (WindowContext* windowContext =
6533 mBrowsingContext->GetCurrentWindowContext()) {
6534 using Change = SessionStoreChangeListener::Change;
6535
6536 // We've finished loading the page and now we want to collect all the
6537 // session store state that the page is initialized with.
6538 SessionStoreChangeListener::CollectSessionStoreData(
6539 windowContext,
6540 EnumSet<Change>(Change::Input, Change::Scroll, Change::SessionHistory,
6541 Change::WireFrame));
6542 }
6543 }
6544
6545 return NS_OK;
6546}
6547
6548//*****************************************************************************
6549// nsDocShell: Content Viewer Management
6550//*****************************************************************************
6551
6552nsresult nsDocShell::EnsureDocumentViewer() {
6553 if (mDocumentViewer) {
6554 return NS_OK;
6555 }
6556 if (mIsBeingDestroyed) {
6557 return NS_ERROR_FAILURE;
6558 }
6559
6560 nsCOMPtr<nsIContentSecurityPolicy> cspToInheritForAboutBlank;
6561 nsCOMPtr<nsIURI> baseURI;
6562 nsIPrincipal* principal = GetInheritedPrincipal(false);
6563 nsIPrincipal* partitionedPrincipal = GetInheritedPrincipal(false, true);
6564
6565 nsCOMPtr<nsIDocShellTreeItem> parentItem;
6566 GetInProcessSameTypeParent(getter_AddRefs(parentItem));
6567 if (parentItem) {
6568 if (nsCOMPtr<nsPIDOMWindowOuter> domWin = GetWindow()) {
6569 nsCOMPtr<Element> parentElement = domWin->GetFrameElementInternal();
6570 if (parentElement) {
6571 baseURI = parentElement->GetBaseURI();
6572 cspToInheritForAboutBlank = parentElement->GetCsp();
6573 }
6574 }
6575 }
6576
6577 nsresult rv = CreateAboutBlankDocumentViewer(
6578 principal, partitionedPrincipal, cspToInheritForAboutBlank, baseURI,
6579 /* aIsInitialDocument */ true);
6580
6581 NS_ENSURE_STATE(mDocumentViewer)do { if ((__builtin_expect(!!(!(mDocumentViewer)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "mDocumentViewer" ") failed"
, nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 6581); return NS_ERROR_UNEXPECTED; } } while (false)
;
6582
6583 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
6584 RefPtr<Document> doc(GetDocument());
6585 MOZ_ASSERT(doc,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(doc)>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(doc))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("doc" " (" "Should have doc if CreateAboutBlankDocumentViewer "
"succeeded!" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 6587); AnnotateMozCrashReason("MOZ_ASSERT" "(" "doc" ") (" "Should have doc if CreateAboutBlankDocumentViewer "
"succeeded!" ")"); do { MOZ_CrashSequence(__null, 6587); __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
6586 "Should have doc if CreateAboutBlankDocumentViewer "do { static_assert( mozilla::detail::AssertionConditionType<
decltype(doc)>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(doc))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("doc" " (" "Should have doc if CreateAboutBlankDocumentViewer "
"succeeded!" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 6587); AnnotateMozCrashReason("MOZ_ASSERT" "(" "doc" ") (" "Should have doc if CreateAboutBlankDocumentViewer "
"succeeded!" ")"); do { MOZ_CrashSequence(__null, 6587); __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
6587 "succeeded!")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(doc)>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(doc))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("doc" " (" "Should have doc if CreateAboutBlankDocumentViewer "
"succeeded!" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 6587); AnnotateMozCrashReason("MOZ_ASSERT" "(" "doc" ") (" "Should have doc if CreateAboutBlankDocumentViewer "
"succeeded!" ")"); do { MOZ_CrashSequence(__null, 6587); __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
;
6588 MOZ_ASSERT(doc->IsInitialDocument(), "Document should be initial document")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(doc->IsInitialDocument())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(doc->IsInitialDocument())
)), 0))) { do { } while (false); MOZ_ReportAssertionFailure("doc->IsInitialDocument()"
" (" "Document should be initial document" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 6588); AnnotateMozCrashReason("MOZ_ASSERT" "(" "doc->IsInitialDocument()"
") (" "Document should be initial document" ")"); do { MOZ_CrashSequence
(__null, 6588); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
6589
6590 // Documents created using EnsureDocumentViewer may be transient
6591 // placeholders created by framescripts before content has a
6592 // chance to load. In some cases, window.open(..., "noopener")
6593 // will create such a document and then synchronously tear it
6594 // down, firing a "pagehide" event. Doing so violates our
6595 // assertions about DocGroups. It's easier to silence the
6596 // assertion here than to avoid creating the extra document.
6597 doc->IgnoreDocGroupMismatches();
6598 }
6599
6600 return rv;
6601}
6602
6603nsresult nsDocShell::CreateAboutBlankDocumentViewer(
6604 nsIPrincipal* aPrincipal, nsIPrincipal* aPartitionedPrincipal,
6605 nsIContentSecurityPolicy* aCSP, nsIURI* aBaseURI, bool aIsInitialDocument,
6606 const Maybe<nsILoadInfo::CrossOriginEmbedderPolicy>& aCOEP,
6607 bool aTryToSaveOldPresentation, bool aCheckPermitUnload,
6608 WindowGlobalChild* aActor) {
6609 RefPtr<Document> blankDoc;
6610 nsCOMPtr<nsIDocumentViewer> viewer;
6611 nsresult rv = NS_ERROR_FAILURE;
6612
6613 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
)
6614 MarkerStack::Capture())do { ; do { if (profiler_is_collecting_markers()) { ::profiler_add_marker_impl
("CreateAboutBlankDocumentViewer", ::geckoprofiler::category::
DOM, MarkerStack::Capture()); } } while (false); } while (false
)
;
6615
6616 MOZ_ASSERT_IF(aActor, aActor->DocumentPrincipal() == aPrincipal)do { if (aActor) { do { static_assert( mozilla::detail::AssertionConditionType
<decltype(aActor->DocumentPrincipal() == aPrincipal)>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(aActor->DocumentPrincipal() == aPrincipal))), 0))
) { do { } while (false); MOZ_ReportAssertionFailure("aActor->DocumentPrincipal() == aPrincipal"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 6616); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aActor->DocumentPrincipal() == aPrincipal"
")"); do { MOZ_CrashSequence(__null, 6616); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
6617
6618 /* mCreatingDocument should never be true at this point. However, it's
6619 a theoretical possibility. We want to know about it and make it stop,
6620 and this sounds like a job for an assertion. */
6621 NS_ASSERTION(!mCreatingDocument,do { if (!(!mCreatingDocument)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "infinite(?) loop creating document averted", "!mCreatingDocument"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 6622); MOZ_PretendNoReturn
(); } } while (0)
6622 "infinite(?) loop creating document averted")do { if (!(!mCreatingDocument)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "infinite(?) loop creating document averted", "!mCreatingDocument"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 6622); MOZ_PretendNoReturn
(); } } while (0)
;
6623 if (mCreatingDocument) {
6624 return NS_ERROR_FAILURE;
6625 }
6626
6627 if (!mBrowsingContext->AncestorsAreCurrent() ||
6628 (mozilla::SessionHistoryInParent() && mBrowsingContext->IsInBFCache())) {
6629 mBrowsingContext->RemoveRootFromBFCacheSync();
6630 return NS_ERROR_NOT_AVAILABLE;
6631 }
6632
6633 // mDocumentViewer->PermitUnload may release |this| docshell.
6634 nsCOMPtr<nsIDocShell> kungFuDeathGrip(this);
6635
6636 // Ensure that UsesOriginAgentCluster has been initialized for this
6637 // BrowsingContextGroup/principal pair before creating the document.
6638 if (aPrincipal) {
6639 mBrowsingContext->Group()->EnsureUsesOriginAgentClusterInitialized(
6640 aPrincipal);
6641 }
6642
6643 AutoRestore<bool> creatingDocument(mCreatingDocument);
6644 mCreatingDocument = true;
6645
6646 if (aPrincipal && !aPrincipal->IsSystemPrincipal() &&
6647 mItemType != typeChrome) {
6648 MOZ_ASSERT(aPrincipal->OriginAttributesRef() ==do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aPrincipal->OriginAttributesRef() == mBrowsingContext
->OriginAttributesRef())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aPrincipal->OriginAttributesRef
() == mBrowsingContext->OriginAttributesRef()))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("aPrincipal->OriginAttributesRef() == mBrowsingContext->OriginAttributesRef()"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 6649); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aPrincipal->OriginAttributesRef() == mBrowsingContext->OriginAttributesRef()"
")"); do { MOZ_CrashSequence(__null, 6649); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6649 mBrowsingContext->OriginAttributesRef())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aPrincipal->OriginAttributesRef() == mBrowsingContext
->OriginAttributesRef())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aPrincipal->OriginAttributesRef
() == mBrowsingContext->OriginAttributesRef()))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("aPrincipal->OriginAttributesRef() == mBrowsingContext->OriginAttributesRef()"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 6649); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aPrincipal->OriginAttributesRef() == mBrowsingContext->OriginAttributesRef()"
")"); do { MOZ_CrashSequence(__null, 6649); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6650 }
6651
6652 // Make sure timing is created. But first record whether we had it
6653 // already, so we don't clobber the timing for an in-progress load.
6654 bool hadTiming = mTiming;
6655 bool toBeReset = MaybeInitTiming();
6656 if (mDocumentViewer) {
6657 if (aCheckPermitUnload) {
6658 // We've got a content viewer already. Make sure the user
6659 // permits us to discard the current document and replace it
6660 // with about:blank. And also ensure we fire the unload events
6661 // in the current document.
6662
6663 // Unload gets fired first for
6664 // document loaded from the session history.
6665 mTiming->NotifyBeforeUnload();
6666
6667 bool okToUnload;
6668 rv = mDocumentViewer->PermitUnload(&okToUnload);
6669
6670 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && !okToUnload) {
6671 // The user chose not to unload the page, interrupt the load.
6672 MaybeResetInitTiming(toBeReset);
6673 return NS_ERROR_FAILURE;
6674 }
6675 if (mTiming) {
6676 mTiming->NotifyUnloadAccepted(mCurrentURI);
6677 }
6678 }
6679
6680 mSavingOldViewer =
6681 aTryToSaveOldPresentation &&
6682 CanSavePresentation(LOAD_NORMAL, nullptr, nullptr,
6683 /* aReportBFCacheComboTelemetry */ true);
6684
6685 // Make sure to blow away our mLoadingURI just in case. No loads
6686 // from inside this pagehide.
6687 mLoadingURI = nullptr;
6688
6689 // Stop any in-progress loading, so that we don't accidentally trigger any
6690 // PageShow notifications from Embed() interrupting our loading below.
6691 Stop();
6692
6693 // Notify the current document that it is about to be unloaded!!
6694 //
6695 // It is important to fire the unload() notification *before* any state
6696 // is changed within the DocShell - otherwise, javascript will get the
6697 // wrong information :-(
6698 //
6699 (void)FirePageHideNotification(!mSavingOldViewer);
6700 // pagehide notification might destroy this docshell.
6701 if (mIsBeingDestroyed) {
6702 return NS_ERROR_DOCSHELL_DYING;
6703 }
6704 }
6705
6706 // Now make sure we don't think we're in the middle of firing unload after
6707 // this point. This will make us fire unload when the about:blank document
6708 // unloads... but that's ok, more or less. Would be nice if it fired load
6709 // too, of course.
6710 mFiredUnloadEvent = false;
6711
6712 nsCOMPtr<nsIDocumentLoaderFactory> docFactory =
6713 nsContentUtils::FindInternalDocumentViewer("text/html"_ns);
6714
6715 if (docFactory) {
6716 nsCOMPtr<nsIPrincipal> principal, partitionedPrincipal;
6717 const uint32_t sandboxFlags =
6718 mBrowsingContext->GetHasLoadedNonInitialDocument()
6719 ? mBrowsingContext->GetSandboxFlags()
6720 : mBrowsingContext->GetInitialSandboxFlags();
6721 // If we're sandboxed, then create a new null principal. We skip
6722 // this if we're being created from WindowGlobalChild, since in
6723 // that case we already have a null principal if required.
6724 // We can't compare againt the BrowsingContext sandbox flag, since
6725 // the value was taken when the load initiated and may have since
6726 // changed.
6727 if ((sandboxFlags & SANDBOXED_ORIGIN) && !aActor) {
6728 if (aPrincipal) {
6729 principal = NullPrincipal::CreateWithInheritedAttributes(aPrincipal);
6730 } else {
6731 principal = NullPrincipal::Create(GetOriginAttributes());
6732 }
6733 partitionedPrincipal = principal;
6734 } else {
6735 principal = aPrincipal;
6736 partitionedPrincipal = aPartitionedPrincipal;
6737 }
6738
6739 // We cannot get the foreign partitioned prinicpal for the initial
6740 // about:blank page. So, we change to check if we need to use the
6741 // partitioned principal for the service worker here.
6742 MaybeCreateInitialClientSource(
6743 StoragePrincipalHelper::ShouldUsePartitionPrincipalForServiceWorker(
6744 this)
6745 ? partitionedPrincipal
6746 : principal);
6747
6748 // generate (about:blank) document to load
6749 blankDoc = nsContentDLF::CreateBlankDocument(mLoadGroup, principal,
6750 partitionedPrincipal, this);
6751 if (blankDoc) {
6752 // Hack: manually set the CSP for the new document
6753 // Please create an actual copy of the CSP (do not share the same
6754 // reference) otherwise appending a new policy within the new
6755 // document will be incorrectly propagated to the opening doc.
6756 if (aCSP) {
6757 RefPtr<nsCSPContext> cspToInherit = new nsCSPContext();
6758 cspToInherit->InitFromOther(static_cast<nsCSPContext*>(aCSP));
6759 blankDoc->SetCsp(cspToInherit);
6760 }
6761
6762 blankDoc->SetIsInitialDocument(aIsInitialDocument);
6763
6764 blankDoc->SetEmbedderPolicy(aCOEP);
6765
6766 // Hack: set the base URI manually, since this document never
6767 // got Reset() with a channel.
6768 blankDoc->SetBaseURI(aBaseURI);
6769
6770 // Copy our sandbox flags to the document. These are immutable
6771 // after being set here.
6772 blankDoc->SetSandboxFlags(sandboxFlags);
6773
6774 // We inherit the classification flags from the parent document if the
6775 // principal matches.
6776 nsCOMPtr<nsIDocShellTreeItem> parentItem;
6777 GetInProcessSameTypeParent(getter_AddRefs(parentItem));
6778 if (parentItem) {
6779 RefPtr<Document> parentDocument = parentItem->GetDocument();
6780 if (parentDocument && principal &&
6781 principal->Equals(parentDocument->NodePrincipal())) {
6782 blankDoc->SetClassificationFlags(
6783 parentDocument->GetClassificationFlags());
6784 }
6785 }
6786
6787 // create a content viewer for us and the new document
6788 docFactory->CreateInstanceForDocument(
6789 NS_ISUPPORTS_CAST(nsIDocShell*, this)static_cast<nsISupports*>(static_cast<nsIDocShell*>
(this))
, blankDoc, "view",
6790 getter_AddRefs(viewer));
6791
6792 // hook 'em up
6793 if (viewer) {
6794 viewer->SetContainer(this);
6795 if (mLoadingEntry && mBrowsingContext->IsTop()) {
6796 mLoadingEntry->mInfo.SetTransient();
6797 }
6798 rv = Embed(viewer, aActor, true, nullptr, mCurrentURI);
6799 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 6799); return rv; } } while (false)
;
6800
6801 SetCurrentURI(blankDoc->GetDocumentURI(), nullptr,
6802 /* aFireLocationChange */ true,
6803 /* aIsInitialAboutBlank */ true,
6804 /* aLocationFlags */ 0);
6805 rv = mIsBeingDestroyed ? NS_ERROR_NOT_AVAILABLE : NS_OK;
6806 }
6807
6808 if (Element* embedderElement = blankDoc->GetEmbedderElement()) {
6809 blankDoc->InitFeaturePolicy(AsVariant(embedderElement));
6810 } else {
6811 blankDoc->InitFeaturePolicy(AsVariant(Nothing{}));
6812 }
6813 }
6814 }
6815
6816 // The transient about:blank viewer doesn't have a session history entry.
6817 SetHistoryEntryAndUpdateBC(Nothing(), Some(nullptr));
6818
6819 // Clear out our mTiming like we would in EndPageLoad, if we didn't
6820 // have one before entering this function.
6821 if (!hadTiming) {
6822 mTiming = nullptr;
6823 mBlankTiming = true;
6824 }
6825
6826 return rv;
6827}
6828
6829NS_IMETHODIMPnsresult
6830nsDocShell::CreateAboutBlankDocumentViewer(nsIPrincipal* aPrincipal,
6831 nsIPrincipal* aPartitionedPrincipal,
6832 nsIContentSecurityPolicy* aCSP) {
6833 return CreateAboutBlankDocumentViewer(aPrincipal, aPartitionedPrincipal, aCSP,
6834 nullptr,
6835 /* aIsInitialDocument */ false);
6836}
6837
6838nsresult nsDocShell::CreateDocumentViewerForActor(
6839 WindowGlobalChild* aWindowActor) {
6840 MOZ_ASSERT(aWindowActor)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aWindowActor)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aWindowActor))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("aWindowActor", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 6840); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aWindowActor"
")"); do { MOZ_CrashSequence(__null, 6840); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6841
6842 // FIXME: WindowGlobalChild should provide the PartitionedPrincipal.
6843 // FIXME: We may want to support non-initial documents here.
6844 nsresult rv = CreateAboutBlankDocumentViewer(
6845 aWindowActor->DocumentPrincipal(), aWindowActor->DocumentPrincipal(),
6846 /* aCsp */ nullptr,
6847 /* aBaseURI */ nullptr,
6848 /* aIsInitialDocument */ true,
6849 /* aCOEP */ Nothing(),
6850 /* aTryToSaveOldPresentation */ true,
6851 /* aCheckPermitUnload */ true, aWindowActor);
6852#ifdef DEBUG1
6853 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
6854 RefPtr<Document> doc(GetDocument());
6855 MOZ_ASSERT(do { static_assert( mozilla::detail::AssertionConditionType<
decltype(doc)>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(doc))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("doc" " (" "Should have a document if CreateAboutBlankDocumentViewer succeeded"
")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 6857
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "doc" ") (" "Should have a document if CreateAboutBlankDocumentViewer succeeded"
")"); do { MOZ_CrashSequence(__null, 6857); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6856 doc,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(doc)>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(doc))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("doc" " (" "Should have a document if CreateAboutBlankDocumentViewer succeeded"
")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 6857
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "doc" ") (" "Should have a document if CreateAboutBlankDocumentViewer succeeded"
")"); do { MOZ_CrashSequence(__null, 6857); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6857 "Should have a document if CreateAboutBlankDocumentViewer succeeded")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(doc)>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(doc))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("doc" " (" "Should have a document if CreateAboutBlankDocumentViewer succeeded"
")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 6857
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "doc" ") (" "Should have a document if CreateAboutBlankDocumentViewer succeeded"
")"); do { MOZ_CrashSequence(__null, 6857); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6858 MOZ_ASSERT(doc->GetOwnerGlobal() == aWindowActor->GetWindowGlobal(),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(doc->GetOwnerGlobal() == aWindowActor->GetWindowGlobal
())>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(doc->GetOwnerGlobal() == aWindowActor->GetWindowGlobal
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("doc->GetOwnerGlobal() == aWindowActor->GetWindowGlobal()"
" (" "New document should be in the same global as our actor"
")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 6859
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "doc->GetOwnerGlobal() == aWindowActor->GetWindowGlobal()"
") (" "New document should be in the same global as our actor"
")"); do { MOZ_CrashSequence(__null, 6859); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6859 "New document should be in the same global as our actor")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(doc->GetOwnerGlobal() == aWindowActor->GetWindowGlobal
())>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(doc->GetOwnerGlobal() == aWindowActor->GetWindowGlobal
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("doc->GetOwnerGlobal() == aWindowActor->GetWindowGlobal()"
" (" "New document should be in the same global as our actor"
")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 6859
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "doc->GetOwnerGlobal() == aWindowActor->GetWindowGlobal()"
") (" "New document should be in the same global as our actor"
")"); do { MOZ_CrashSequence(__null, 6859); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6860 MOZ_ASSERT(doc->IsInitialDocument(),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(doc->IsInitialDocument())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(doc->IsInitialDocument())
)), 0))) { do { } while (false); MOZ_ReportAssertionFailure("doc->IsInitialDocument()"
" (" "New document should be an initial document" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 6861); AnnotateMozCrashReason("MOZ_ASSERT" "(" "doc->IsInitialDocument()"
") (" "New document should be an initial document" ")"); do {
MOZ_CrashSequence(__null, 6861); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
6861 "New document should be an initial document")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(doc->IsInitialDocument())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(doc->IsInitialDocument())
)), 0))) { do { } while (false); MOZ_ReportAssertionFailure("doc->IsInitialDocument()"
" (" "New document should be an initial document" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 6861); AnnotateMozCrashReason("MOZ_ASSERT" "(" "doc->IsInitialDocument()"
") (" "New document should be an initial document" ")"); do {
MOZ_CrashSequence(__null, 6861); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
6862 }
6863#endif
6864
6865 return rv;
6866}
6867
6868bool nsDocShell::CanSavePresentation(uint32_t aLoadType,
6869 nsIRequest* aNewRequest,
6870 Document* aNewDocument,
6871 bool aReportBFCacheComboTelemetry) {
6872 if (!mOSHE) {
6873 return false; // no entry to save into
6874 }
6875
6876 MOZ_ASSERT(!mozilla::SessionHistoryInParent(),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mozilla::SessionHistoryInParent())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mozilla::SessionHistoryInParent
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!mozilla::SessionHistoryInParent()" " (" "mOSHE cannot be non-null with SHIP"
")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 6877
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mozilla::SessionHistoryInParent()"
") (" "mOSHE cannot be non-null with SHIP" ")"); do { MOZ_CrashSequence
(__null, 6877); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
6877 "mOSHE cannot be non-null with SHIP")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mozilla::SessionHistoryInParent())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mozilla::SessionHistoryInParent
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!mozilla::SessionHistoryInParent()" " (" "mOSHE cannot be non-null with SHIP"
")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 6877
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mozilla::SessionHistoryInParent()"
") (" "mOSHE cannot be non-null with SHIP" ")"); do { MOZ_CrashSequence
(__null, 6877); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
6878 nsCOMPtr<nsIDocumentViewer> viewer = mOSHE->GetDocumentViewer();
6879 if (viewer) {
6880 NS_WARNING("mOSHE already has a content viewer!")NS_DebugBreak(NS_DEBUG_WARNING, "mOSHE already has a content viewer!"
, nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 6880)
;
6881 return false;
6882 }
6883
6884 // Only save presentation for "normal" loads and link loads. Anything else
6885 // probably wants to refetch the page, so caching the old presentation
6886 // would be incorrect.
6887 if (aLoadType != LOAD_NORMAL && aLoadType != LOAD_HISTORY &&
6888 aLoadType != LOAD_LINK && aLoadType != LOAD_STOP_CONTENT &&
6889 aLoadType != LOAD_STOP_CONTENT_AND_REPLACE &&
6890 aLoadType != LOAD_ERROR_PAGE) {
6891 return false;
6892 }
6893
6894 // If the session history entry has the saveLayoutState flag set to false,
6895 // then we should not cache the presentation.
6896 if (!mOSHE->GetSaveLayoutStateFlag()) {
6897 return false;
6898 }
6899
6900 // If the document is not done loading, don't cache it.
6901 if (!mScriptGlobal || mScriptGlobal->IsLoading()) {
6902 MOZ_LOG(gPageCacheLog, mozilla::LogLevel::Verbose,do { const ::mozilla::LogModule* moz_real_module = gPageCacheLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Verbose)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Verbose, "Blocked due to document still loading"
); } } while (0)
6903 ("Blocked due to document still loading"))do { const ::mozilla::LogModule* moz_real_module = gPageCacheLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, mozilla::LogLevel::Verbose)), 0))) { mozilla::detail::log_print
(moz_real_module, mozilla::LogLevel::Verbose, "Blocked due to document still loading"
); } } while (0)
;
6904 return false;
6905 }
6906
6907 if (mScriptGlobal->WouldReuseInnerWindow(aNewDocument)) {
6908 return false;
6909 }
6910
6911 // Avoid doing the work of saving the presentation state in the case where
6912 // the content viewer cache is disabled.
6913 if (nsSHistory::GetMaxTotalViewers() == 0) {
6914 return false;
6915 }
6916
6917 // Don't cache the content viewer if we're in a subframe.
6918 if (mBrowsingContext->GetParent()) {
6919 return false; // this is a subframe load
6920 }
6921
6922 // If the document does not want its presentation cached, then don't.
6923 RefPtr<Document> doc = mScriptGlobal->GetExtantDoc();
6924
6925 uint32_t bfCacheCombo = 0;
6926 bool canSavePresentation =
6927 doc->CanSavePresentation(aNewRequest, bfCacheCombo, true);
6928 MOZ_ASSERT_IF(canSavePresentation, bfCacheCombo == 0)do { if (canSavePresentation) { do { static_assert( mozilla::
detail::AssertionConditionType<decltype(bfCacheCombo == 0)
>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(bfCacheCombo == 0))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("bfCacheCombo == 0", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 6928); AnnotateMozCrashReason("MOZ_ASSERT" "(" "bfCacheCombo == 0"
")"); do { MOZ_CrashSequence(__null, 6928); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
6929 if (canSavePresentation && doc->IsTopLevelContentDocument()) {
6930 auto* browsingContextGroup = mBrowsingContext->Group();
6931 nsTArray<RefPtr<BrowsingContext>>& topLevelContext =
6932 browsingContextGroup->Toplevels();
6933
6934 for (const auto& browsingContext : topLevelContext) {
6935 if (browsingContext != mBrowsingContext) {
6936 if (StaticPrefs::docshell_shistory_bfcache_require_no_opener()) {
6937 canSavePresentation = false;
6938 }
6939 bfCacheCombo |= BFCacheStatus::NOT_ONLY_TOPLEVEL_IN_BCG;
6940 break;
6941 }
6942 }
6943 }
6944
6945 if (aReportBFCacheComboTelemetry) {
6946 ReportBFCacheComboTelemetry(bfCacheCombo);
6947 }
6948 return doc && canSavePresentation;
6949}
6950
6951/* static */
6952void nsDocShell::ReportBFCacheComboTelemetry(uint32_t aCombo) {
6953 // There are 11 possible reasons to make a request fails to use BFCache
6954 // (see BFCacheStatus in dom/base/Document.h), and we'd like to record
6955 // the common combinations for reasons which make requests fail to use
6956 // BFCache. These combinations are generated based on some local browsings,
6957 // we need to adjust them when necessary.
6958 enum BFCacheStatusCombo : uint32_t {
6959 BFCACHE_SUCCESS,
6960 NOT_ONLY_TOPLEVEL = mozilla::dom::BFCacheStatus::NOT_ONLY_TOPLEVEL_IN_BCG,
6961 // If both unload and beforeunload listeners are presented, it'll be
6962 // recorded as unload
6963 UNLOAD = mozilla::dom::BFCacheStatus::UNLOAD_LISTENER,
6964 UNLOAD_REQUEST = mozilla::dom::BFCacheStatus::UNLOAD_LISTENER |
6965 mozilla::dom::BFCacheStatus::REQUEST,
6966 REQUEST = mozilla::dom::BFCacheStatus::REQUEST,
6967 UNLOAD_REQUEST_PEER = mozilla::dom::BFCacheStatus::UNLOAD_LISTENER |
6968 mozilla::dom::BFCacheStatus::REQUEST |
6969 mozilla::dom::BFCacheStatus::ACTIVE_PEER_CONNECTION,
6970 UNLOAD_REQUEST_PEER_MSE =
6971 mozilla::dom::BFCacheStatus::UNLOAD_LISTENER |
6972 mozilla::dom::BFCacheStatus::REQUEST |
6973 mozilla::dom::BFCacheStatus::ACTIVE_PEER_CONNECTION |
6974 mozilla::dom::BFCacheStatus::CONTAINS_MSE_CONTENT,
6975 UNLOAD_REQUEST_MSE = mozilla::dom::BFCacheStatus::UNLOAD_LISTENER |
6976 mozilla::dom::BFCacheStatus::REQUEST |
6977 mozilla::dom::BFCacheStatus::CONTAINS_MSE_CONTENT,
6978 SUSPENDED_UNLOAD_REQUEST_PEER =
6979 mozilla::dom::BFCacheStatus::SUSPENDED |
6980 mozilla::dom::BFCacheStatus::UNLOAD_LISTENER |
6981 mozilla::dom::BFCacheStatus::REQUEST |
6982 mozilla::dom::BFCacheStatus::ACTIVE_PEER_CONNECTION,
6983 REMOTE_SUBFRAMES = mozilla::dom::BFCacheStatus::CONTAINS_REMOTE_SUBFRAMES,
6984 BEFOREUNLOAD = mozilla::dom::BFCacheStatus::BEFOREUNLOAD_LISTENER,
6985 };
6986
6987 // Beforeunload is recorded as a blocker only if it is the only one to block
6988 // bfcache.
6989 if (aCombo != mozilla::dom::BFCacheStatus::BEFOREUNLOAD_LISTENER) {
6990 aCombo &= ~mozilla::dom::BFCacheStatus::BEFOREUNLOAD_LISTENER;
6991 }
6992 switch (aCombo) {
6993 case BFCACHE_SUCCESS:
6994 glean::bfcache::combo.EnumGet(glean::bfcache::ComboLabel::eBfcacheSuccess)
6995 .Add();
6996 break;
6997 case NOT_ONLY_TOPLEVEL:
6998 if (StaticPrefs::docshell_shistory_bfcache_require_no_opener()) {
6999 glean::bfcache::combo.EnumGet(glean::bfcache::ComboLabel::eOther).Add();
7000 break;
7001 }
7002 glean::bfcache::combo.EnumGet(glean::bfcache::ComboLabel::eBfcacheSuccess)
7003 .Add();
7004 glean::bfcache::combo
7005 .EnumGet(glean::bfcache::ComboLabel::eSuccessNotToplevel)
7006 .Add();
7007 break;
7008 case UNLOAD:
7009 glean::bfcache::combo.EnumGet(glean::bfcache::ComboLabel::eUnload).Add();
7010 break;
7011 case BEFOREUNLOAD:
7012 glean::bfcache::combo.EnumGet(glean::bfcache::ComboLabel::eBeforeunload)
7013 .Add();
7014 break;
7015 case UNLOAD_REQUEST:
7016 glean::bfcache::combo.EnumGet(glean::bfcache::ComboLabel::eUnloadReq)
7017 .Add();
7018 break;
7019 case REQUEST:
7020 glean::bfcache::combo.EnumGet(glean::bfcache::ComboLabel::eReq).Add();
7021 break;
7022 case UNLOAD_REQUEST_PEER:
7023 glean::bfcache::combo.EnumGet(glean::bfcache::ComboLabel::eUnloadReqPeer)
7024 .Add();
7025 break;
7026 case UNLOAD_REQUEST_PEER_MSE:
7027 glean::bfcache::combo
7028 .EnumGet(glean::bfcache::ComboLabel::eUnloadReqPeerMse)
7029 .Add();
7030 break;
7031 case UNLOAD_REQUEST_MSE:
7032 glean::bfcache::combo.EnumGet(glean::bfcache::ComboLabel::eUnloadReqMse)
7033 .Add();
7034 break;
7035 case SUSPENDED_UNLOAD_REQUEST_PEER:
7036 glean::bfcache::combo
7037 .EnumGet(glean::bfcache::ComboLabel::eSpdUnloadReqPeer)
7038 .Add();
7039 break;
7040 case REMOTE_SUBFRAMES:
7041 glean::bfcache::combo
7042 .EnumGet(glean::bfcache::ComboLabel::eRemoteSubframes)
7043 .Add();
7044 break;
7045 default:
7046 glean::bfcache::combo.EnumGet(glean::bfcache::ComboLabel::eOther).Add();
7047 break;
7048 }
7049};
7050
7051void nsDocShell::ReattachEditorToWindow(nsISHEntry* aSHEntry) {
7052 MOZ_ASSERT(!mozilla::SessionHistoryInParent())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mozilla::SessionHistoryInParent())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mozilla::SessionHistoryInParent
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!mozilla::SessionHistoryInParent()", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 7052); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mozilla::SessionHistoryInParent()"
")"); do { MOZ_CrashSequence(__null, 7052); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7053 MOZ_ASSERT(!mIsBeingDestroyed)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mIsBeingDestroyed)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mIsBeingDestroyed))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("!mIsBeingDestroyed"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 7053); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!mIsBeingDestroyed" ")"); do { MOZ_CrashSequence
(__null, 7053); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
7054
7055 NS_ASSERTION(!mEditorData,do { if (!(!mEditorData)) { NS_DebugBreak(NS_DEBUG_ASSERTION,
"Why reattach an editor when we already have one?", "!mEditorData"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 7056); MOZ_PretendNoReturn
(); } } while (0)
7056 "Why reattach an editor when we already have one?")do { if (!(!mEditorData)) { NS_DebugBreak(NS_DEBUG_ASSERTION,
"Why reattach an editor when we already have one?", "!mEditorData"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 7056); MOZ_PretendNoReturn
(); } } while (0)
;
7057 NS_ASSERTION(aSHEntry && aSHEntry->HasDetachedEditor(),do { if (!(aSHEntry && aSHEntry->HasDetachedEditor
())) { NS_DebugBreak(NS_DEBUG_ASSERTION, "Reattaching when there's not a detached editor."
, "aSHEntry && aSHEntry->HasDetachedEditor()", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 7058); MOZ_PretendNoReturn(); } } while (0)
7058 "Reattaching when there's not a detached editor.")do { if (!(aSHEntry && aSHEntry->HasDetachedEditor
())) { NS_DebugBreak(NS_DEBUG_ASSERTION, "Reattaching when there's not a detached editor."
, "aSHEntry && aSHEntry->HasDetachedEditor()", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 7058); MOZ_PretendNoReturn(); } } while (0)
;
7059
7060 if (mEditorData || !aSHEntry) {
7061 return;
7062 }
7063
7064 mEditorData = WrapUnique(aSHEntry->ForgetEditorData());
7065 if (mEditorData) {
7066#ifdef DEBUG1
7067 nsresult rv =
7068#endif
7069 mEditorData->ReattachToWindow(this);
7070 NS_ASSERTION(NS_SUCCEEDED(rv), "Failed to reattach editing session")do { if (!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1
))))) { NS_DebugBreak(NS_DEBUG_ASSERTION, "Failed to reattach editing session"
, "NS_SUCCEEDED(rv)", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 7070); MOZ_PretendNoReturn(); } } while (0)
;
7071 }
7072}
7073
7074void nsDocShell::DetachEditorFromWindow() {
7075 if (!mEditorData || mEditorData->WaitingForLoad()) {
7076 // If there's nothing to detach, or if the editor data is actually set
7077 // up for the _new_ page that's coming in, don't detach.
7078 return;
7079 }
7080
7081 NS_ASSERTION(!mOSHE || !mOSHE->HasDetachedEditor(),do { if (!(!mOSHE || !mOSHE->HasDetachedEditor())) { NS_DebugBreak
(NS_DEBUG_ASSERTION, "Detaching editor when it's already detached."
, "!mOSHE || !mOSHE->HasDetachedEditor()", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 7082); MOZ_PretendNoReturn(); } } while (0)
7082 "Detaching editor when it's already detached.")do { if (!(!mOSHE || !mOSHE->HasDetachedEditor())) { NS_DebugBreak
(NS_DEBUG_ASSERTION, "Detaching editor when it's already detached."
, "!mOSHE || !mOSHE->HasDetachedEditor()", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 7082); MOZ_PretendNoReturn(); } } while (0)
;
7083
7084 nsresult res = mEditorData->DetachFromWindow();
7085 NS_ASSERTION(NS_SUCCEEDED(res), "Failed to detach editor")do { if (!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(res)),
1))))) { NS_DebugBreak(NS_DEBUG_ASSERTION, "Failed to detach editor"
, "NS_SUCCEEDED(res)", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 7085); MOZ_PretendNoReturn(); } } while (0)
;
7086
7087 if (NS_SUCCEEDED(res)((bool)(__builtin_expect(!!(!NS_FAILED_impl(res)), 1)))) {
7088 // Make mOSHE hold the owning ref to the editor data.
7089 if (mOSHE) {
7090 MOZ_ASSERT(!mIsBeingDestroyed || !mOSHE->HasDetachedEditor(),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mIsBeingDestroyed || !mOSHE->HasDetachedEditor()
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!mIsBeingDestroyed || !mOSHE->HasDetachedEditor()
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"!mIsBeingDestroyed || !mOSHE->HasDetachedEditor()" " (" "We should not set the editor data again once after we "
"detached the editor data during destroying this docshell" ")"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 7092); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!mIsBeingDestroyed || !mOSHE->HasDetachedEditor()"
") (" "We should not set the editor data again once after we "
"detached the editor data during destroying this docshell" ")"
); do { MOZ_CrashSequence(__null, 7092); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
7091 "We should not set the editor data again once after we "do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mIsBeingDestroyed || !mOSHE->HasDetachedEditor()
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!mIsBeingDestroyed || !mOSHE->HasDetachedEditor()
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"!mIsBeingDestroyed || !mOSHE->HasDetachedEditor()" " (" "We should not set the editor data again once after we "
"detached the editor data during destroying this docshell" ")"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 7092); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!mIsBeingDestroyed || !mOSHE->HasDetachedEditor()"
") (" "We should not set the editor data again once after we "
"detached the editor data during destroying this docshell" ")"
); do { MOZ_CrashSequence(__null, 7092); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
7092 "detached the editor data during destroying this docshell")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mIsBeingDestroyed || !mOSHE->HasDetachedEditor()
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!mIsBeingDestroyed || !mOSHE->HasDetachedEditor()
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"!mIsBeingDestroyed || !mOSHE->HasDetachedEditor()" " (" "We should not set the editor data again once after we "
"detached the editor data during destroying this docshell" ")"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 7092); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!mIsBeingDestroyed || !mOSHE->HasDetachedEditor()"
") (" "We should not set the editor data again once after we "
"detached the editor data during destroying this docshell" ")"
); do { MOZ_CrashSequence(__null, 7092); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7093 mOSHE->SetEditorData(mEditorData.release());
7094 } else {
7095 mEditorData = nullptr;
7096 }
7097 }
7098
7099#ifdef DEBUG1
7100 {
7101 bool isEditable;
7102 GetEditable(&isEditable);
7103 NS_ASSERTION(!isEditable,do { if (!(!isEditable)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "Window is still editable after detaching editor."
, "!isEditable", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 7104); MOZ_PretendNoReturn(); } } while (0)
7104 "Window is still editable after detaching editor.")do { if (!(!isEditable)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "Window is still editable after detaching editor."
, "!isEditable", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 7104); MOZ_PretendNoReturn(); } } while (0)
;
7105 }
7106#endif // DEBUG
7107}
7108
7109nsresult nsDocShell::CaptureState() {
7110 MOZ_ASSERT(!mozilla::SessionHistoryInParent())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mozilla::SessionHistoryInParent())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mozilla::SessionHistoryInParent
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!mozilla::SessionHistoryInParent()", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 7110); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mozilla::SessionHistoryInParent()"
")"); do { MOZ_CrashSequence(__null, 7110); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7111
7112 if (!mOSHE || mOSHE == mLSHE) {
7113 // No entry to save into, or we're replacing the existing entry.
7114 return NS_ERROR_FAILURE;
7115 }
7116
7117 if (!mScriptGlobal) {
7118 return NS_ERROR_FAILURE;
7119 }
7120
7121 nsCOMPtr<nsISupports> windowState = mScriptGlobal->SaveWindowState();
7122 NS_ENSURE_TRUE(windowState, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(windowState)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "windowState" ") failed"
, nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 7122); return NS_ERROR_FAILURE; } } while (false)
;
7123
7124 if (MOZ_UNLIKELY(MOZ_LOG_TEST(gPageCacheLog, LogLevel::Debug))(__builtin_expect(!!((__builtin_expect(!!(mozilla::detail::log_test
(gPageCacheLog, LogLevel::Debug)), 0))), 0))
) {
7125 nsAutoCString spec;
7126 nsCOMPtr<nsIURI> uri = mOSHE->GetURI();
7127 if (uri) {
7128 uri->GetSpec(spec);
7129 }
7130 MOZ_LOG(gPageCacheLog, LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = gPageCacheLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "Saving presentation into session history, URI: %s"
, spec.get()); } } while (0)
7131 ("Saving presentation into session history, URI: %s", spec.get()))do { const ::mozilla::LogModule* moz_real_module = gPageCacheLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "Saving presentation into session history, URI: %s"
, spec.get()); } } while (0)
;
7132 }
7133
7134 mOSHE->SetWindowState(windowState);
7135
7136 // Suspend refresh URIs and save off the timer queue
7137 mOSHE->SetRefreshURIList(mSavedRefreshURIList);
7138
7139 // Capture the current content viewer bounds.
7140 if (mDocumentViewer) {
7141 LayoutDeviceIntRect bounds;
7142 mDocumentViewer->GetBounds(bounds);
7143 mOSHE->SetViewerBounds(bounds.ToUnknownRect());
7144 }
7145
7146 // Capture the docshell hierarchy.
7147 mOSHE->ClearChildShells();
7148
7149 uint32_t childCount = mChildList.Length();
7150 for (uint32_t i = 0; i < childCount; ++i) {
7151 nsCOMPtr<nsIDocShellTreeItem> childShell = do_QueryInterface(ChildAt(i));
7152 NS_ASSERTION(childShell, "null child shell")do { if (!(childShell)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "null child shell"
, "childShell", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 7152); MOZ_PretendNoReturn(); } } while (0)
;
7153
7154 mOSHE->AddChildShell(childShell);
7155 }
7156
7157 return NS_OK;
7158}
7159
7160NS_IMETHODIMPnsresult
7161nsDocShell::RestorePresentationEvent::Run() {
7162 MOZ_ASSERT(!mozilla::SessionHistoryInParent())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mozilla::SessionHistoryInParent())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mozilla::SessionHistoryInParent
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!mozilla::SessionHistoryInParent()", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 7162); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mozilla::SessionHistoryInParent()"
")"); do { MOZ_CrashSequence(__null, 7162); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7163
7164 if (mDocShell && NS_FAILED(mDocShell->RestoreFromHistory())((bool)(__builtin_expect(!!(NS_FAILED_impl(mDocShell->RestoreFromHistory
())), 0)))
) {
7165 NS_WARNING("RestoreFromHistory failed")NS_DebugBreak(NS_DEBUG_WARNING, "RestoreFromHistory failed", nullptr
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 7165)
;
7166 }
7167 return NS_OK;
7168}
7169
7170NS_IMETHODIMPnsresult
7171nsDocShell::BeginRestore(nsIDocumentViewer* aDocumentViewer, bool aTop) {
7172 MOZ_ASSERT(!mozilla::SessionHistoryInParent())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mozilla::SessionHistoryInParent())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mozilla::SessionHistoryInParent
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!mozilla::SessionHistoryInParent()", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 7172); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mozilla::SessionHistoryInParent()"
")"); do { MOZ_CrashSequence(__null, 7172); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7173
7174 nsresult rv;
7175 if (!aDocumentViewer) {
7176 rv = EnsureDocumentViewer();
7177 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 7177); return rv; } } while (false)
;
7178
7179 aDocumentViewer = mDocumentViewer;
7180 }
7181
7182 // Dispatch events for restoring the presentation. We try to simulate
7183 // the progress notifications loading the document would cause, so we add
7184 // the document's channel to the loadgroup to initiate stateChange
7185 // notifications.
7186
7187 RefPtr<Document> doc = aDocumentViewer->GetDocument();
7188 if (doc) {
7189 nsIChannel* channel = doc->GetChannel();
7190 if (channel) {
7191 mEODForCurrentDocument = false;
7192 mIsRestoringDocument = true;
7193 mLoadGroup->AddRequest(channel, nullptr);
7194 mIsRestoringDocument = false;
7195 }
7196 }
7197
7198 if (!aTop) {
7199 // This point corresponds to us having gotten OnStartRequest or
7200 // STATE_START, so do the same thing that CreateDocumentViewer does at
7201 // this point to ensure that unload/pagehide events for this document
7202 // will fire when it's unloaded again.
7203 mFiredUnloadEvent = false;
7204
7205 // For non-top frames, there is no notion of making sure that the
7206 // previous document is in the domwindow when STATE_START notifications
7207 // happen. We can just call BeginRestore for all of the child shells
7208 // now.
7209 rv = BeginRestoreChildren();
7210 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 7210); return rv; } } while (false)
;
7211 }
7212
7213 return NS_OK;
7214}
7215
7216nsresult nsDocShell::BeginRestoreChildren() {
7217 MOZ_ASSERT(!mozilla::SessionHistoryInParent())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mozilla::SessionHistoryInParent())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mozilla::SessionHistoryInParent
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!mozilla::SessionHistoryInParent()", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 7217); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mozilla::SessionHistoryInParent()"
")"); do { MOZ_CrashSequence(__null, 7217); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7218
7219 for (auto* childDocLoader : mChildList.ForwardRange()) {
7220 nsCOMPtr<nsIDocShell> child = do_QueryObject(childDocLoader);
7221 if (child) {
7222 nsresult rv = child->BeginRestore(nullptr, false);
7223 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 7223); return rv; } } while (false)
;
7224 }
7225 }
7226 return NS_OK;
7227}
7228
7229NS_IMETHODIMPnsresult
7230nsDocShell::FinishRestore() {
7231 MOZ_ASSERT(!mozilla::SessionHistoryInParent())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mozilla::SessionHistoryInParent())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mozilla::SessionHistoryInParent
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!mozilla::SessionHistoryInParent()", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 7231); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mozilla::SessionHistoryInParent()"
")"); do { MOZ_CrashSequence(__null, 7231); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7232
7233 // First we call finishRestore() on our children. In the simulated load,
7234 // all of the child frames finish loading before the main document.
7235
7236 for (auto* childDocLoader : mChildList.ForwardRange()) {
7237 nsCOMPtr<nsIDocShell> child = do_QueryObject(childDocLoader);
7238 if (child) {
7239 child->FinishRestore();
7240 }
7241 }
7242
7243 if (mOSHE && mOSHE->HasDetachedEditor()) {
7244 ReattachEditorToWindow(mOSHE);
7245 }
7246
7247 RefPtr<Document> doc = GetDocument();
7248 if (doc) {
7249 // Finally, we remove the request from the loadgroup. This will
7250 // cause onStateChange(STATE_STOP) to fire, which will fire the
7251 // pageshow event to the chrome.
7252
7253 nsIChannel* channel = doc->GetChannel();
7254 if (channel) {
7255 mIsRestoringDocument = true;
7256 mLoadGroup->RemoveRequest(channel, nullptr, NS_OK);
7257 mIsRestoringDocument = false;
7258 }
7259 }
7260
7261 return NS_OK;
7262}
7263
7264NS_IMETHODIMPnsresult
7265nsDocShell::GetRestoringDocument(bool* aRestoring) {
7266 *aRestoring = mIsRestoringDocument;
7267 return NS_OK;
7268}
7269
7270nsresult nsDocShell::RestorePresentation(nsISHEntry* aSHEntry,
7271 bool* aRestoring) {
7272 MOZ_ASSERT(!mozilla::SessionHistoryInParent())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mozilla::SessionHistoryInParent())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mozilla::SessionHistoryInParent
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!mozilla::SessionHistoryInParent()", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 7272); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mozilla::SessionHistoryInParent()"
")"); do { MOZ_CrashSequence(__null, 7272); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7273 MOZ_ASSERT(!mIsBeingDestroyed)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mIsBeingDestroyed)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mIsBeingDestroyed))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("!mIsBeingDestroyed"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 7273); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!mIsBeingDestroyed" ")"); do { MOZ_CrashSequence
(__null, 7273); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
7274
7275 NS_ASSERTION(mLoadType & LOAD_CMD_HISTORY,do { if (!(mLoadType & LOAD_CMD_HISTORY)) { NS_DebugBreak
(NS_DEBUG_ASSERTION, "RestorePresentation should only be called for history loads"
, "mLoadType & LOAD_CMD_HISTORY", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 7276); MOZ_PretendNoReturn(); } } while (0)
7276 "RestorePresentation should only be called for history loads")do { if (!(mLoadType & LOAD_CMD_HISTORY)) { NS_DebugBreak
(NS_DEBUG_ASSERTION, "RestorePresentation should only be called for history loads"
, "mLoadType & LOAD_CMD_HISTORY", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 7276); MOZ_PretendNoReturn(); } } while (0)
;
7277
7278 nsCOMPtr<nsIDocumentViewer> viewer = aSHEntry->GetDocumentViewer();
7279
7280 nsAutoCString spec;
7281 if (MOZ_UNLIKELY(MOZ_LOG_TEST(gPageCacheLog, LogLevel::Debug))(__builtin_expect(!!((__builtin_expect(!!(mozilla::detail::log_test
(gPageCacheLog, LogLevel::Debug)), 0))), 0))
) {
7282 nsCOMPtr<nsIURI> uri = aSHEntry->GetURI();
7283 if (uri) {
7284 uri->GetSpec(spec);
7285 }
7286 }
7287
7288 *aRestoring = false;
7289
7290 if (!viewer) {
7291 MOZ_LOG(gPageCacheLog, LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = gPageCacheLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "no saved presentation for uri: %s", spec.
get()); } } while (0)
7292 ("no saved presentation for uri: %s", spec.get()))do { const ::mozilla::LogModule* moz_real_module = gPageCacheLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "no saved presentation for uri: %s", spec.
get()); } } while (0)
;
7293 return NS_OK;
7294 }
7295
7296 // We need to make sure the content viewer's container is this docshell.
7297 // In subframe navigation, it's possible for the docshell that the
7298 // content viewer was originally loaded into to be replaced with a
7299 // different one. We don't currently support restoring the presentation
7300 // in that case.
7301
7302 nsCOMPtr<nsIDocShell> container;
7303 viewer->GetContainer(getter_AddRefs(container));
7304 if (!::SameCOMIdentity(container, GetAsSupports(this))) {
7305 MOZ_LOG(gPageCacheLog, LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = gPageCacheLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "No valid container, clearing presentation"
); } } while (0)
7306 ("No valid container, clearing presentation"))do { const ::mozilla::LogModule* moz_real_module = gPageCacheLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "No valid container, clearing presentation"
); } } while (0)
;
7307 aSHEntry->SetDocumentViewer(nullptr);
7308 return NS_ERROR_FAILURE;
7309 }
7310
7311 NS_ASSERTION(mDocumentViewer != viewer, "Restoring existing presentation")do { if (!(mDocumentViewer != viewer)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "Restoring existing presentation", "mDocumentViewer != viewer"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 7311); MOZ_PretendNoReturn
(); } } while (0)
;
7312
7313 MOZ_LOG(gPageCacheLog, LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = gPageCacheLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "restoring presentation from session history: %s"
, spec.get()); } } while (0)
7314 ("restoring presentation from session history: %s", spec.get()))do { const ::mozilla::LogModule* moz_real_module = gPageCacheLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "restoring presentation from session history: %s"
, spec.get()); } } while (0)
;
7315
7316 SetHistoryEntryAndUpdateBC(Some(aSHEntry), Nothing());
7317
7318 // Post an event that will remove the request after we've returned
7319 // to the event loop. This mimics the way it is called by nsIChannel
7320 // implementations.
7321
7322 // Revoke any pending restore (just in case).
7323 NS_ASSERTION(!mRestorePresentationEvent.IsPending(),do { if (!(!mRestorePresentationEvent.IsPending())) { NS_DebugBreak
(NS_DEBUG_ASSERTION, "should only have one RestorePresentationEvent"
, "!mRestorePresentationEvent.IsPending()", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 7324); MOZ_PretendNoReturn(); } } while (0)
7324 "should only have one RestorePresentationEvent")do { if (!(!mRestorePresentationEvent.IsPending())) { NS_DebugBreak
(NS_DEBUG_ASSERTION, "should only have one RestorePresentationEvent"
, "!mRestorePresentationEvent.IsPending()", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 7324); MOZ_PretendNoReturn(); } } while (0)
;
7325 mRestorePresentationEvent.Revoke();
7326
7327 RefPtr<RestorePresentationEvent> evt = new RestorePresentationEvent(this);
7328 nsresult rv = Dispatch(do_AddRef(evt));
7329 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
7330 mRestorePresentationEvent = evt.get();
7331 // The rest of the restore processing will happen on our event
7332 // callback.
7333 *aRestoring = true;
7334 }
7335
7336 return rv;
7337}
7338
7339namespace {
7340class MOZ_STACK_CLASS PresentationEventForgetter {
7341 public:
7342 explicit PresentationEventForgetter(
7343 nsRevocableEventPtr<nsDocShell::RestorePresentationEvent>&
7344 aRestorePresentationEvent)
7345 : mRestorePresentationEvent(aRestorePresentationEvent),
7346 mEvent(aRestorePresentationEvent.get()) {}
7347
7348 ~PresentationEventForgetter() { Forget(); }
7349
7350 void Forget() {
7351 if (mRestorePresentationEvent.get() == mEvent) {
7352 mRestorePresentationEvent.Forget();
7353 mEvent = nullptr;
7354 }
7355 }
7356
7357 private:
7358 nsRevocableEventPtr<nsDocShell::RestorePresentationEvent>&
7359 mRestorePresentationEvent;
7360 RefPtr<nsDocShell::RestorePresentationEvent> mEvent;
7361};
7362
7363} // namespace
7364
7365bool nsDocShell::SandboxFlagsImplyCookies(const uint32_t& aSandboxFlags) {
7366 return (aSandboxFlags & (SANDBOXED_ORIGIN | SANDBOXED_SCRIPTS)) == 0;
7367}
7368
7369nsresult nsDocShell::RestoreFromHistory() {
7370 MOZ_ASSERT(!mozilla::SessionHistoryInParent())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mozilla::SessionHistoryInParent())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mozilla::SessionHistoryInParent
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!mozilla::SessionHistoryInParent()", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 7370); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mozilla::SessionHistoryInParent()"
")"); do { MOZ_CrashSequence(__null, 7370); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7371 MOZ_ASSERT(mRestorePresentationEvent.IsPending())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mRestorePresentationEvent.IsPending())>::isValid,
"invalid assertion condition"); if ((__builtin_expect(!!(!(!
!(mRestorePresentationEvent.IsPending()))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("mRestorePresentationEvent.IsPending()"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 7371); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "mRestorePresentationEvent.IsPending()" ")"
); do { MOZ_CrashSequence(__null, 7371); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7372 PresentationEventForgetter forgetter(mRestorePresentationEvent);
7373
7374 // This section of code follows the same ordering as CreateDocumentViewer.
7375 if (!mLSHE) {
7376 return NS_ERROR_FAILURE;
7377 }
7378
7379 nsCOMPtr<nsIDocumentViewer> viewer = mLSHE->GetDocumentViewer();
7380 if (!viewer) {
7381 return NS_ERROR_FAILURE;
7382 }
7383
7384 if (mSavingOldViewer) {
7385 // We determined that it was safe to cache the document presentation
7386 // at the time we initiated the new load. We need to check whether
7387 // it's still safe to do so, since there may have been DOM mutations
7388 // or new requests initiated.
7389 RefPtr<Document> doc = viewer->GetDocument();
7390 nsIRequest* request = nullptr;
7391 if (doc) {
7392 request = doc->GetChannel();
7393 }
7394 mSavingOldViewer = CanSavePresentation(
7395 mLoadType, request, doc, /* aReportBFCacheComboTelemetry */ false);
7396 }
7397
7398 // Protect against mLSHE going away via a load triggered from
7399 // pagehide or unload.
7400 nsCOMPtr<nsISHEntry> origLSHE = mLSHE;
7401
7402 // Make sure to blow away our mLoadingURI just in case. No loads
7403 // from inside this pagehide.
7404 mLoadingURI = nullptr;
7405
7406 // Notify the old content viewer that it's being hidden.
7407 FirePageHideNotification(!mSavingOldViewer);
7408 // pagehide notification might destroy this docshell.
7409 if (mIsBeingDestroyed) {
7410 return NS_ERROR_DOCSHELL_DYING;
7411 }
7412
7413 // If mLSHE was changed as a result of the pagehide event, then
7414 // something else was loaded. Don't finish restoring.
7415 if (mLSHE != origLSHE) {
7416 return NS_OK;
7417 }
7418
7419 // Add the request to our load group. We do this before swapping out
7420 // the content viewers so that consumers of STATE_START can access
7421 // the old document. We only deal with the toplevel load at this time --
7422 // to be consistent with normal document loading, subframes cannot start
7423 // loading until after data arrives, which is after STATE_START completes.
7424
7425 RefPtr<RestorePresentationEvent> currentPresentationRestoration =
7426 mRestorePresentationEvent.get();
7427 Stop();
7428 // Make sure we're still restoring the same presentation.
7429 // If we aren't, docshell is in process doing another load already.
7430 NS_ENSURE_STATE(currentPresentationRestoration ==do { if ((__builtin_expect(!!(!(currentPresentationRestoration
== mRestorePresentationEvent.get())), 0))) { NS_DebugBreak(NS_DEBUG_WARNING
, "NS_ENSURE_TRUE(" "currentPresentationRestoration == mRestorePresentationEvent.get()"
") failed", nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 7431); return NS_ERROR_UNEXPECTED; } } while (false)
7431 mRestorePresentationEvent.get())do { if ((__builtin_expect(!!(!(currentPresentationRestoration
== mRestorePresentationEvent.get())), 0))) { NS_DebugBreak(NS_DEBUG_WARNING
, "NS_ENSURE_TRUE(" "currentPresentationRestoration == mRestorePresentationEvent.get()"
") failed", nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 7431); return NS_ERROR_UNEXPECTED; } } while (false)
;
7432 BeginRestore(viewer, true);
7433 NS_ENSURE_STATE(currentPresentationRestoration ==do { if ((__builtin_expect(!!(!(currentPresentationRestoration
== mRestorePresentationEvent.get())), 0))) { NS_DebugBreak(NS_DEBUG_WARNING
, "NS_ENSURE_TRUE(" "currentPresentationRestoration == mRestorePresentationEvent.get()"
") failed", nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 7434); return NS_ERROR_UNEXPECTED; } } while (false)
7434 mRestorePresentationEvent.get())do { if ((__builtin_expect(!!(!(currentPresentationRestoration
== mRestorePresentationEvent.get())), 0))) { NS_DebugBreak(NS_DEBUG_WARNING
, "NS_ENSURE_TRUE(" "currentPresentationRestoration == mRestorePresentationEvent.get()"
") failed", nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 7434); return NS_ERROR_UNEXPECTED; } } while (false)
;
7435 forgetter.Forget();
7436
7437 // Set mFiredUnloadEvent = false so that the unload handler for the
7438 // *new* document will fire.
7439 mFiredUnloadEvent = false;
7440
7441 mURIResultedInDocument = true;
7442 RefPtr<ChildSHistory> rootSH = GetRootSessionHistory();
7443 if (rootSH) {
7444 mPreviousEntryIndex = rootSH->Index();
7445 rootSH->LegacySHistory()->UpdateIndex();
7446 mLoadedEntryIndex = rootSH->Index();
7447 MOZ_LOG(gPageCacheLog, LogLevel::Verbose,do { const ::mozilla::LogModule* moz_real_module = gPageCacheLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Verbose)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Verbose, "Previous index: %d, Loaded index: %d", mPreviousEntryIndex
, mLoadedEntryIndex); } } while (0)
7448 ("Previous index: %d, Loaded index: %d", mPreviousEntryIndex,do { const ::mozilla::LogModule* moz_real_module = gPageCacheLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Verbose)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Verbose, "Previous index: %d, Loaded index: %d", mPreviousEntryIndex
, mLoadedEntryIndex); } } while (0)
7449 mLoadedEntryIndex))do { const ::mozilla::LogModule* moz_real_module = gPageCacheLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Verbose)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Verbose, "Previous index: %d, Loaded index: %d", mPreviousEntryIndex
, mLoadedEntryIndex); } } while (0)
;
7450 }
7451
7452 // Rather than call Embed(), we will retrieve the viewer from the session
7453 // history entry and swap it in.
7454 // XXX can we refactor this so that we can just call Embed()?
7455 PersistLayoutHistoryState();
7456 nsresult rv;
7457 if (mDocumentViewer) {
7458 if (mSavingOldViewer && NS_FAILED(CaptureState())((bool)(__builtin_expect(!!(NS_FAILED_impl(CaptureState())), 0
)))
) {
7459 if (mOSHE) {
7460 mOSHE->SyncPresentationState();
7461 }
7462 mSavingOldViewer = false;
7463 }
7464 }
7465
7466 mSavedRefreshURIList = nullptr;
7467
7468 // In cases where we use a transient about:blank viewer between loads,
7469 // we never show the transient viewer, so _its_ previous viewer is never
7470 // unhooked from the view hierarchy. Destroy any such previous viewer now,
7471 // before we grab the root view sibling, so that we don't grab a view
7472 // that's about to go away.
7473
7474 if (mDocumentViewer) {
7475 // Make sure to hold a strong ref to previousViewer here while we
7476 // drop the reference to it from mDocumentViewer.
7477 nsCOMPtr<nsIDocumentViewer> previousViewer =
7478 mDocumentViewer->GetPreviousViewer();
7479 if (previousViewer) {
7480 mDocumentViewer->SetPreviousViewer(nullptr);
7481 previousViewer->Destroy();
7482 }
7483 }
7484
7485 // Save off the root view's parent and sibling so that we can insert the
7486 // new content viewer's root view at the same position. Also save the
7487 // bounds of the root view's widget.
7488
7489 nsView* rootViewSibling = nullptr;
7490 nsView* rootViewParent = nullptr;
7491 LayoutDeviceIntRect newBounds(0, 0, 0, 0);
7492
7493 PresShell* oldPresShell = GetPresShell();
7494 if (oldPresShell) {
7495 nsViewManager* vm = oldPresShell->GetViewManager();
7496 if (vm) {
7497 nsView* oldRootView = vm->GetRootView();
7498
7499 if (oldRootView) {
7500 rootViewSibling = oldRootView->GetNextSibling();
7501 rootViewParent = oldRootView->GetParent();
7502
7503 mDocumentViewer->GetBounds(newBounds);
7504 }
7505 }
7506 }
7507
7508 nsCOMPtr<nsIContent> container;
7509 RefPtr<Document> sibling;
7510 if (rootViewParent && rootViewParent->GetParent()) {
7511 nsIFrame* frame = rootViewParent->GetParent()->GetFrame();
7512 container = frame ? frame->GetContent() : nullptr;
7513 }
7514 if (rootViewSibling) {
7515 nsIFrame* frame = rootViewSibling->GetFrame();
7516 sibling = frame ? frame->PresShell()->GetDocument() : nullptr;
7517 }
7518
7519 // Transfer ownership to mDocumentViewer. By ensuring that either the
7520 // docshell or the session history, but not both, have references to the
7521 // content viewer, we prevent the viewer from being torn down after
7522 // Destroy() is called.
7523
7524 if (mDocumentViewer) {
7525 mDocumentViewer->Close(mSavingOldViewer ? mOSHE.get() : nullptr);
7526 viewer->SetPreviousViewer(mDocumentViewer);
7527 }
7528 if (mOSHE && (!mDocumentViewer || !mSavingOldViewer)) {
7529 // We don't plan to save a viewer in mOSHE; tell it to drop
7530 // any other state it's holding.
7531 mOSHE->SyncPresentationState();
7532 }
7533
7534 // Order the mDocumentViewer setup just like Embed does.
7535 mDocumentViewer = nullptr;
7536
7537 // Now that we're about to switch documents, forget all of our children.
7538 // Note that we cached them as needed up in CaptureState above.
7539 DestroyChildren();
7540
7541 mDocumentViewer.swap(viewer);
7542
7543 // Grab all of the related presentation from the SHEntry now.
7544 // Clearing the viewer from the SHEntry will clear all of this state.
7545 nsCOMPtr<nsISupports> windowState = mLSHE->GetWindowState();
7546 mLSHE->SetWindowState(nullptr);
7547
7548 bool sticky = mLSHE->GetSticky();
7549
7550 RefPtr<Document> document = mDocumentViewer->GetDocument();
7551
7552 nsCOMArray<nsIDocShellTreeItem> childShells;
7553 int32_t i = 0;
7554 nsCOMPtr<nsIDocShellTreeItem> child;
7555 while (NS_SUCCEEDED(mLSHE->ChildShellAt(i++, getter_AddRefs(child)))((bool)(__builtin_expect(!!(!NS_FAILED_impl(mLSHE->ChildShellAt
(i++, getter_AddRefs(child)))), 1)))
&&
7556 child) {
7557 childShells.AppendObject(child);
7558 }
7559
7560 // get the previous content viewer size
7561 nsIntRect oldBounds(0, 0, 0, 0);
7562 mLSHE->GetViewerBounds(oldBounds);
7563
7564 // Restore the refresh URI list. The refresh timers will be restarted
7565 // when EndPageLoad() is called.
7566 nsCOMPtr<nsIMutableArray> refreshURIList = mLSHE->GetRefreshURIList();
7567
7568 // Reattach to the window object.
7569 mIsRestoringDocument = true; // for MediaDocument::BecomeInteractive
7570 rv = mDocumentViewer->Open(windowState, mLSHE);
7571 mIsRestoringDocument = false;
7572
7573 // Hack to keep nsDocShellEditorData alive across the
7574 // SetDocumentViewer(nullptr) call below.
7575 UniquePtr<nsDocShellEditorData> data(mLSHE->ForgetEditorData());
7576
7577 // Now remove it from the cached presentation.
7578 mLSHE->SetDocumentViewer(nullptr);
7579 mEODForCurrentDocument = false;
7580
7581 mLSHE->SetEditorData(data.release());
7582
7583#ifdef DEBUG1
7584 {
7585 nsCOMPtr<nsIMutableArray> refreshURIs = mLSHE->GetRefreshURIList();
7586 nsCOMPtr<nsIDocShellTreeItem> childShell;
7587 mLSHE->ChildShellAt(0, getter_AddRefs(childShell));
7588 NS_ASSERTION(!refreshURIs && !childShell,do { if (!(!refreshURIs && !childShell)) { NS_DebugBreak
(NS_DEBUG_ASSERTION, "SHEntry should have cleared presentation state"
, "!refreshURIs && !childShell", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 7589); MOZ_PretendNoReturn(); } } while (0)
7589 "SHEntry should have cleared presentation state")do { if (!(!refreshURIs && !childShell)) { NS_DebugBreak
(NS_DEBUG_ASSERTION, "SHEntry should have cleared presentation state"
, "!refreshURIs && !childShell", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 7589); MOZ_PretendNoReturn(); } } while (0)
;
7590 }
7591#endif
7592
7593 // Restore the sticky state of the viewer. The viewer has set this state
7594 // on the history entry in Destroy() just before marking itself non-sticky,
7595 // to avoid teardown of the presentation.
7596 mDocumentViewer->SetSticky(sticky);
7597
7598 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 7598); return rv; } } while (false)
;
7599
7600 // mLSHE is now our currently-loaded document.
7601 SetHistoryEntryAndUpdateBC(Nothing(), Some<nsISHEntry*>(mLSHE));
7602
7603 // We aren't going to restore any items from the LayoutHistoryState,
7604 // but we don't want them to stay around in case the page is reloaded.
7605 SetLayoutHistoryState(nullptr);
7606
7607 // This is the end of our Embed() replacement
7608
7609 mSavingOldViewer = false;
7610 mEODForCurrentDocument = false;
7611
7612 if (document) {
7613 RefPtr<nsDocShell> parent = GetInProcessParentDocshell();
7614 if (parent) {
7615 RefPtr<Document> d = parent->GetDocument();
7616 if (d) {
7617 if (d->EventHandlingSuppressed()) {
7618 document->SuppressEventHandling(d->EventHandlingSuppressed());
7619 }
7620 }
7621 }
7622
7623 // Use the uri from the mLSHE we had when we entered this function
7624 // (which need not match the document's URI if anchors are involved),
7625 // since that's the history entry we're loading. Note that if we use
7626 // origLSHE we don't have to worry about whether the entry in question
7627 // is still mLSHE or whether it's now mOSHE.
7628 nsCOMPtr<nsIURI> uri = origLSHE->GetURI();
7629 SetCurrentURI(uri, document->GetChannel(), /* aFireLocationChange */ true,
7630 /* aIsInitialAboutBlank */ false,
7631 /* aLocationFlags */ 0);
7632 }
7633
7634 // This is the end of our CreateDocumentViewer() replacement.
7635 // Now we simulate a load. First, we restore the state of the javascript
7636 // window object.
7637 nsCOMPtr<nsPIDOMWindowOuter> privWin = GetWindow();
7638 NS_ASSERTION(privWin, "could not get nsPIDOMWindow interface")do { if (!(privWin)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "could not get nsPIDOMWindow interface"
, "privWin", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 7638); MOZ_PretendNoReturn(); } } while (0)
;
7639
7640 // Now, dispatch a title change event which would happen as the
7641 // <head> is parsed.
7642 document->NotifyPossibleTitleChange(false);
7643
7644 // Now we simulate appending child docshells for subframes.
7645 for (i = 0; i < childShells.Count(); ++i) {
7646 nsIDocShellTreeItem* childItem = childShells.ObjectAt(i);
7647 nsCOMPtr<nsIDocShell> childShell = do_QueryInterface(childItem);
7648
7649 // Make sure to not clobber the state of the child. Since AddChild
7650 // always clobbers it, save it off first.
7651 bool allowRedirects;
7652 childShell->GetAllowMetaRedirects(&allowRedirects);
7653
7654 bool allowSubframes;
7655 childShell->GetAllowSubframes(&allowSubframes);
7656
7657 bool allowImages;
7658 childShell->GetAllowImages(&allowImages);
7659
7660 bool allowMedia = childShell->GetAllowMedia();
7661
7662 bool allowDNSPrefetch;
7663 childShell->GetAllowDNSPrefetch(&allowDNSPrefetch);
7664
7665 bool allowContentRetargeting = childShell->GetAllowContentRetargeting();
7666 bool allowContentRetargetingOnChildren =
7667 childShell->GetAllowContentRetargetingOnChildren();
7668
7669 // this.AddChild(child) calls child.SetDocLoaderParent(this), meaning that
7670 // the child inherits our state. Among other things, this means that the
7671 // child inherits our mPrivateBrowsingId, which is what we want.
7672 AddChild(childItem);
7673
7674 childShell->SetAllowMetaRedirects(allowRedirects);
7675 childShell->SetAllowSubframes(allowSubframes);
7676 childShell->SetAllowImages(allowImages);
7677 childShell->SetAllowMedia(allowMedia);
7678 childShell->SetAllowDNSPrefetch(allowDNSPrefetch);
7679 childShell->SetAllowContentRetargeting(allowContentRetargeting);
7680 childShell->SetAllowContentRetargetingOnChildren(
7681 allowContentRetargetingOnChildren);
7682
7683 rv = childShell->BeginRestore(nullptr, false);
7684 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 7684); return rv; } } while (false)
;
7685 }
7686
7687 // Make sure to restore the window state after adding the child shells back
7688 // to the tree. This is necessary for Thaw() and Resume() to propagate
7689 // properly.
7690 rv = privWin->RestoreWindowState(windowState);
7691 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 7691); return rv; } } while (false)
;
7692
7693 RefPtr<PresShell> presShell = GetPresShell();
7694
7695 // We may be displayed on a different monitor (or in a different
7696 // HiDPI mode) than when we got into the history list. So we need
7697 // to check if this has happened. See bug 838239.
7698
7699 // Because the prescontext normally handles resolution changes via
7700 // a runnable (see nsPresContext::UIResolutionChanged), its device
7701 // context won't be -immediately- updated as a result of calling
7702 // presShell->BackingScaleFactorChanged().
7703
7704 // But we depend on that device context when adjusting the view size
7705 // via mDocumentViewer->SetBounds(newBounds) below. So we need to
7706 // explicitly tell it to check for changed resolution here.
7707 if (presShell) {
7708 RefPtr<nsPresContext> pc = presShell->GetPresContext();
7709 if (pc->DeviceContext()->CheckDPIChange()) {
7710 presShell->BackingScaleFactorChanged();
7711 }
7712 // Recompute zoom and text-zoom and such.
7713 pc->RecomputeBrowsingContextDependentData();
7714 }
7715
7716 nsViewManager* newVM = presShell ? presShell->GetViewManager() : nullptr;
7717 nsView* newRootView = newVM ? newVM->GetRootView() : nullptr;
7718
7719 // Insert the new root view at the correct location in the view tree.
7720 if (container) {
7721 nsSubDocumentFrame* subDocFrame =
7722 do_QueryFrame(container->GetPrimaryFrame());
7723 rootViewParent = subDocFrame ? subDocFrame->EnsureInnerView() : nullptr;
7724 } else {
7725 rootViewParent = nullptr;
7726 }
7727 if (sibling && sibling->GetPresShell() &&
7728 sibling->GetPresShell()->GetViewManager()) {
7729 rootViewSibling = sibling->GetPresShell()->GetViewManager()->GetRootView();
7730 } else {
7731 rootViewSibling = nullptr;
7732 }
7733 if (rootViewParent && newRootView &&
7734 newRootView->GetParent() != rootViewParent) {
7735 nsViewManager* parentVM = rootViewParent->GetViewManager();
7736 if (parentVM) {
7737 // InsertChild(parent, child, sib, true) inserts the child after
7738 // sib in content order, which is before sib in view order. BUT
7739 // when sib is null it inserts at the end of the the document
7740 // order, i.e., first in view order. But when oldRootSibling is
7741 // null, the old root as at the end of the view list --- last in
7742 // content order --- and we want to call InsertChild(parent, child,
7743 // nullptr, false) in that case.
7744 parentVM->InsertChild(rootViewParent, newRootView, rootViewSibling,
7745 rootViewSibling ? true : false);
7746
7747 NS_ASSERTION(newRootView->GetNextSibling() == rootViewSibling,do { if (!(newRootView->GetNextSibling() == rootViewSibling
)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "error in InsertChild"
, "newRootView->GetNextSibling() == rootViewSibling", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 7748); MOZ_PretendNoReturn(); } } while (0)
7748 "error in InsertChild")do { if (!(newRootView->GetNextSibling() == rootViewSibling
)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "error in InsertChild"
, "newRootView->GetNextSibling() == rootViewSibling", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 7748); MOZ_PretendNoReturn(); } } while (0)
;
7749 }
7750 }
7751
7752 nsCOMPtr<nsPIDOMWindowInner> privWinInner = privWin->GetCurrentInnerWindow();
7753
7754 // If parent is suspended, increase suspension count.
7755 // This can't be done as early as event suppression since this
7756 // depends on docshell tree.
7757 privWinInner->SyncStateFromParentWindow();
7758
7759 // Now that all of the child docshells have been put into place, we can
7760 // restart the timers for the window and all of the child frames.
7761 privWinInner->Resume();
7762
7763 // Now that we have found the inner window of the page restored
7764 // from the history, we have to make sure that
7765 // performance.navigation.type is 2.
7766 Performance* performance = privWinInner->GetPerformance();
7767 if (performance) {
7768 performance->GetDOMTiming()->NotifyRestoreStart();
7769 }
7770
7771 // Restore the refresh URI list. The refresh timers will be restarted
7772 // when EndPageLoad() is called.
7773 mRefreshURIList = refreshURIList;
7774
7775 // Meta-refresh timers have been restarted for this shell, but not
7776 // for our children. Walk the child shells and restart their timers.
7777 for (auto* childDocLoader : mChildList.ForwardRange()) {
7778 nsCOMPtr<nsIDocShell> child = do_QueryObject(childDocLoader);
7779 if (child) {
7780 child->ResumeRefreshURIs();
7781 }
7782 }
7783
7784 // Make sure this presentation is the same size as the previous
7785 // presentation. If this is not the same size we showed it at last time,
7786 // then we need to resize the widget.
7787
7788 // XXXbryner This interacts poorly with Firefox's infobar. If the old
7789 // presentation had the infobar visible, then we will resize the new
7790 // presentation to that smaller size. However, firing the locationchanged
7791 // event will hide the infobar, which will immediately resize the window
7792 // back to the larger size. A future optimization might be to restore
7793 // the presentation at the "wrong" size, then fire the locationchanged
7794 // event and check whether the docshell's new size is the same as the
7795 // cached viewer size (skipping the resize if they are equal).
7796
7797 if (newRootView) {
7798 if (!newBounds.IsEmpty() &&
7799 !newBounds.ToUnknownRect().IsEqualEdges(oldBounds)) {
7800 MOZ_LOG(gPageCacheLog, LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = gPageCacheLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "resize widget(%d, %d, %d, %d)", newBounds
.x, newBounds.y, newBounds.width, newBounds.height); } } while
(0)
7801 ("resize widget(%d, %d, %d, %d)", newBounds.x, newBounds.y,do { const ::mozilla::LogModule* moz_real_module = gPageCacheLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "resize widget(%d, %d, %d, %d)", newBounds
.x, newBounds.y, newBounds.width, newBounds.height); } } while
(0)
7802 newBounds.width, newBounds.height))do { const ::mozilla::LogModule* moz_real_module = gPageCacheLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "resize widget(%d, %d, %d, %d)", newBounds
.x, newBounds.y, newBounds.width, newBounds.height); } } while
(0)
;
7803 mDocumentViewer->SetBounds(newBounds);
7804 } else if (ScrollContainerFrame* sf =
7805 presShell->GetRootScrollContainerFrame()) {
7806 sf->PostScrolledAreaEventForCurrentArea();
7807 }
7808 }
7809
7810 // The FinishRestore call below can kill these, null them out so we don't
7811 // have invalid pointer lying around.
7812 newRootView = rootViewSibling = rootViewParent = nullptr;
7813 newVM = nullptr;
7814
7815 // If the IsUnderHiddenEmbedderElement() state has been changed, we need to
7816 // update it.
7817 if (oldPresShell && presShell &&
7818 presShell->IsUnderHiddenEmbedderElement() !=
7819 oldPresShell->IsUnderHiddenEmbedderElement()) {
7820 presShell->SetIsUnderHiddenEmbedderElement(
7821 oldPresShell->IsUnderHiddenEmbedderElement());
7822 }
7823
7824 // Simulate the completion of the load.
7825 nsDocShell::FinishRestore();
7826
7827 // Restart plugins, and paint the content.
7828 if (presShell) {
7829 presShell->Thaw();
7830 }
7831
7832 return privWin->FireDelayedDOMEvents(true);
7833}
7834
7835nsresult nsDocShell::CreateDocumentViewer(const nsACString& aContentType,
7836 nsIRequest* aRequest,
7837 nsIStreamListener** aContentHandler) {
7838 *aContentHandler = nullptr;
7839
7840 if (!mTreeOwner || mIsBeingDestroyed) {
7841 // If we don't have a tree owner, then we're in the process of being
7842 // destroyed. Rather than continue trying to load something, just give up.
7843 return NS_ERROR_DOCSHELL_DYING;
7844 }
7845
7846 if (!mBrowsingContext->AncestorsAreCurrent() ||
7847 mBrowsingContext->IsInBFCache()) {
7848 mBrowsingContext->RemoveRootFromBFCacheSync();
7849 return NS_ERROR_NOT_AVAILABLE;
7850 }
7851
7852 // Can we check the content type of the current content viewer
7853 // and reuse it without destroying it and re-creating it?
7854
7855 NS_ASSERTION(mLoadGroup, "Someone ignored return from Init()?")do { if (!(mLoadGroup)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "Someone ignored return from Init()?"
, "mLoadGroup", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 7855); MOZ_PretendNoReturn(); } } while (0)
;
7856
7857 // Instantiate the content viewer object
7858 nsCOMPtr<nsIDocumentViewer> viewer;
7859 nsresult rv = NewDocumentViewerObj(aContentType, aRequest, mLoadGroup,
7860 aContentHandler, getter_AddRefs(viewer));
7861
7862 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
7863 return rv;
7864 }
7865
7866 // Notify the current document that it is about to be unloaded!!
7867 //
7868 // It is important to fire the unload() notification *before* any state
7869 // is changed within the DocShell - otherwise, javascript will get the
7870 // wrong information :-(
7871 //
7872
7873 if (mSavingOldViewer) {
7874 // We determined that it was safe to cache the document presentation
7875 // at the time we initiated the new load. We need to check whether
7876 // it's still safe to do so, since there may have been DOM mutations
7877 // or new requests initiated.
7878 RefPtr<Document> doc = viewer->GetDocument();
7879 mSavingOldViewer = CanSavePresentation(
7880 mLoadType, aRequest, doc, /* aReportBFCacheComboTelemetry */ false);
7881 }
7882
7883 NS_ASSERTION(!mLoadingURI, "Re-entering unload?")do { if (!(!mLoadingURI)) { NS_DebugBreak(NS_DEBUG_ASSERTION,
"Re-entering unload?", "!mLoadingURI", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 7883); MOZ_PretendNoReturn(); } } while (0)
;
7884
7885 nsCOMPtr<nsIChannel> aOpenedChannel = do_QueryInterface(aRequest);
7886 if (aOpenedChannel) {
7887 aOpenedChannel->GetURI(getter_AddRefs(mLoadingURI));
7888 }
7889
7890 // Grab the current URI, we need to pass it to Embed, and OnNewURI will reset
7891 // it before we do call Embed.
7892 nsCOMPtr<nsIURI> previousURI = mCurrentURI;
7893
7894 FirePageHideNotification(!mSavingOldViewer);
7895 if (mIsBeingDestroyed) {
7896 // Force to stop the newly created orphaned viewer.
7897 viewer->Stop();
7898 return NS_ERROR_DOCSHELL_DYING;
7899 }
7900 mLoadingURI = nullptr;
7901
7902 // Set mFiredUnloadEvent = false so that the unload handler for the
7903 // *new* document will fire.
7904 mFiredUnloadEvent = false;
7905
7906 // we've created a new document so go ahead and call
7907 // OnNewURI(), but don't fire OnLocationChange()
7908 // notifications before we've called Embed(). See bug 284993.
7909 mURIResultedInDocument = true;
7910 bool errorOnLocationChangeNeeded = false;
7911 nsCOMPtr<nsIChannel> failedChannel = mFailedChannel;
7912 nsCOMPtr<nsIURI> failedURI;
7913
7914 if (mLoadType == LOAD_ERROR_PAGE) {
7915 // We need to set the SH entry and our current URI here and not
7916 // at the moment we load the page. We want the same behavior
7917 // of Stop() as for a normal page load. See bug 514232 for details.
7918
7919 // Revert mLoadType to load type to state the page load failed,
7920 // following function calls need it.
7921 mLoadType = mFailedLoadType;
7922
7923 Document* doc = viewer->GetDocument();
7924 if (doc) {
7925 doc->SetFailedChannel(failedChannel);
7926 }
7927
7928 nsCOMPtr<nsIPrincipal> triggeringPrincipal;
7929 if (failedChannel) {
7930 // Make sure we have a URI to set currentURI.
7931 NS_GetFinalChannelURI(failedChannel, getter_AddRefs(failedURI));
7932 } else {
7933 // if there is no failed channel we have to explicitly provide
7934 // a triggeringPrincipal for the history entry.
7935 triggeringPrincipal = nsContentUtils::GetSystemPrincipal();
7936 }
7937
7938 if (!failedURI) {
7939 failedURI = mFailedURI;
7940 }
7941 if (!failedURI) {
7942 // We need a URI object to store a session history entry, so make up a URI
7943 NS_NewURI(getter_AddRefs(failedURI), "about:blank");
7944 }
7945
7946 // When we don't have failedURI, something wrong will happen. See
7947 // bug 291876.
7948 MOZ_ASSERT(failedURI, "We don't have a URI for history APIs.")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(failedURI)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(failedURI))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("failedURI" " (" "We don't have a URI for history APIs."
")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 7948
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "failedURI" ") (" "We don't have a URI for history APIs."
")"); do { MOZ_CrashSequence(__null, 7948); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7949
7950 mFailedChannel = nullptr;
7951 mFailedURI = nullptr;
7952
7953 // Create an shistory entry for the old load.
7954 if (failedURI) {
7955 errorOnLocationChangeNeeded =
7956 OnNewURI(failedURI, failedChannel, triggeringPrincipal, nullptr,
7957 nullptr, nullptr, false, false);
7958 }
7959
7960 // Be sure to have a correct mLSHE, it may have been cleared by
7961 // EndPageLoad. See bug 302115.
7962 ChildSHistory* shistory = GetSessionHistory();
7963 if (!mozilla::SessionHistoryInParent() && shistory && !mLSHE) {
7964 int32_t idx = shistory->LegacySHistory()->GetRequestedIndex();
7965 if (idx == -1) {
7966 idx = shistory->Index();
7967 }
7968 shistory->LegacySHistory()->GetEntryAtIndex(idx, getter_AddRefs(mLSHE));
7969 }
7970
7971 mLoadType = LOAD_ERROR_PAGE;
7972 }
7973
7974 nsCOMPtr<nsIURI> finalURI;
7975 // If this a redirect, use the final url (uri)
7976 // else use the original url
7977 //
7978 // Note that this should match what documents do (see Document::Reset).
7979 NS_GetFinalChannelURI(aOpenedChannel, getter_AddRefs(finalURI));
7980
7981 bool onLocationChangeNeeded = false;
7982 if (finalURI) {
7983 // Pass false for aCloneSHChildren, since we're loading a new page here.
7984 onLocationChangeNeeded = OnNewURI(finalURI, aOpenedChannel, nullptr,
7985 nullptr, nullptr, nullptr, true, false);
7986 }
7987
7988 // We inherit the classification flags from the parent document if the
7989 // document is about:blank and the principal matches.
7990 nsCOMPtr<nsIDocShellTreeItem> parentItem;
7991 GetInProcessSameTypeParent(getter_AddRefs(parentItem));
7992 if (parentItem && finalURI && NS_IsAboutBlank(finalURI)) {
7993 RefPtr<Document> doc = viewer->GetDocument();
7994 RefPtr<Document> parentDocument = parentItem->GetDocument();
7995 if (parentDocument && doc &&
7996 doc->NodePrincipal()->Equals(parentDocument->NodePrincipal())) {
7997 doc->SetClassificationFlags(parentDocument->GetClassificationFlags());
7998 }
7999 }
8000
8001 // let's try resetting the load group if we need to...
8002 nsCOMPtr<nsILoadGroup> currentLoadGroup;
8003 NS_ENSURE_SUCCESS(do { nsresult __rv = aOpenedChannel->GetLoadGroup(getter_AddRefs
(currentLoadGroup)); if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "aOpenedChannel->GetLoadGroup(getter_AddRefs(currentLoadGroup))"
, "NS_ERROR_FAILURE", static_cast<uint32_t>(__rv), name
? " (" : "", name ? name : "", name ? ")" : ""); NS_DebugBreak
(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 8005); return NS_ERROR_FAILURE; } } while (false)
8004 aOpenedChannel->GetLoadGroup(getter_AddRefs(currentLoadGroup)),do { nsresult __rv = aOpenedChannel->GetLoadGroup(getter_AddRefs
(currentLoadGroup)); if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "aOpenedChannel->GetLoadGroup(getter_AddRefs(currentLoadGroup))"
, "NS_ERROR_FAILURE", static_cast<uint32_t>(__rv), name
? " (" : "", name ? name : "", name ? ")" : ""); NS_DebugBreak
(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 8005); return NS_ERROR_FAILURE; } } while (false)
8005 NS_ERROR_FAILURE)do { nsresult __rv = aOpenedChannel->GetLoadGroup(getter_AddRefs
(currentLoadGroup)); if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "aOpenedChannel->GetLoadGroup(getter_AddRefs(currentLoadGroup))"
, "NS_ERROR_FAILURE", static_cast<uint32_t>(__rv), name
? " (" : "", name ? name : "", name ? ")" : ""); NS_DebugBreak
(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 8005); return NS_ERROR_FAILURE; } } while (false)
;
8006
8007 if (currentLoadGroup != mLoadGroup) {
8008 nsLoadFlags loadFlags = 0;
8009
8010 // Cancel any URIs that are currently loading...
8011 // XXX: Need to do this eventually Stop();
8012 //
8013 // Retarget the document to this loadgroup...
8014 //
8015 /* First attach the channel to the right loadgroup
8016 * and then remove from the old loadgroup. This
8017 * puts the notifications in the right order and
8018 * we don't null-out mLSHE in OnStateChange() for
8019 * all redirected urls
8020 */
8021 aOpenedChannel->SetLoadGroup(mLoadGroup);
8022
8023 // Mark the channel as being a document URI...
8024 aOpenedChannel->GetLoadFlags(&loadFlags);
8025 loadFlags |= nsIChannel::LOAD_DOCUMENT_URI;
8026 nsCOMPtr<nsILoadInfo> loadInfo = aOpenedChannel->LoadInfo();
8027 if (SandboxFlagsImplyCookies(loadInfo->GetSandboxFlags())) {
8028 loadFlags |= nsIRequest::LOAD_DOCUMENT_NEEDS_COOKIE;
8029 }
8030
8031 aOpenedChannel->SetLoadFlags(loadFlags);
8032
8033 mLoadGroup->AddRequest(aRequest, nullptr);
8034 if (currentLoadGroup) {
8035 currentLoadGroup->RemoveRequest(aRequest, nullptr, NS_BINDING_RETARGETED);
8036 }
8037
8038 // Update the notification callbacks, so that progress and
8039 // status information are sent to the right docshell...
8040 aOpenedChannel->SetNotificationCallbacks(this);
8041 }
8042
8043 if (mLoadingEntry && mBrowsingContext->IsTop() &&
8044 !ShouldAddToSessionHistory(finalURI, aOpenedChannel)) {
8045 mLoadingEntry->mInfo.SetTransient();
8046 }
8047 NS_ENSURE_SUCCESS(Embed(viewer, nullptr, false, aOpenedChannel, previousURI),do { nsresult __rv = Embed(viewer, nullptr, false, aOpenedChannel
, previousURI); if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "Embed(viewer, nullptr, false, aOpenedChannel, previousURI)"
, "NS_ERROR_FAILURE", static_cast<uint32_t>(__rv), name
? " (" : "", name ? name : "", name ? ")" : ""); NS_DebugBreak
(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 8048); return NS_ERROR_FAILURE; } } while (false)
8048 NS_ERROR_FAILURE)do { nsresult __rv = Embed(viewer, nullptr, false, aOpenedChannel
, previousURI); if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "Embed(viewer, nullptr, false, aOpenedChannel, previousURI)"
, "NS_ERROR_FAILURE", static_cast<uint32_t>(__rv), name
? " (" : "", name ? name : "", name ? ")" : ""); NS_DebugBreak
(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 8048); return NS_ERROR_FAILURE; } } while (false)
;
8049
8050 if (!mBrowsingContext->GetHasLoadedNonInitialDocument()) {
8051 MOZ_ALWAYS_SUCCEEDS(mBrowsingContext->SetHasLoadedNonInitialDocument(true))do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(mBrowsingContext->SetHasLoadedNonInitialDocument(true))),
1)))), 1))) { } else { do { do { } while (false); MOZ_ReportCrash
("" "NS_SUCCEEDED(mBrowsingContext->SetHasLoadedNonInitialDocument(true))"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 8051); AnnotateMozCrashReason
("MOZ_CRASH(" "NS_SUCCEEDED(mBrowsingContext->SetHasLoadedNonInitialDocument(true))"
")"); do { MOZ_CrashSequence(__null, 8051); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
;
8052 }
8053
8054 mSavedRefreshURIList = nullptr;
8055 mSavingOldViewer = false;
8056 mEODForCurrentDocument = false;
8057
8058 // if this document is part of a multipart document,
8059 // the ID can be used to distinguish it from the other parts.
8060 nsCOMPtr<nsIMultiPartChannel> multiPartChannel(do_QueryInterface(aRequest));
8061 if (multiPartChannel) {
8062 if (PresShell* presShell = GetPresShell()) {
8063 if (Document* doc = presShell->GetDocument()) {
8064 uint32_t partID;
8065 multiPartChannel->GetPartID(&partID);
8066 doc->SetPartID(partID);
8067 }
8068 }
8069 }
8070
8071 if (errorOnLocationChangeNeeded) {
8072 FireOnLocationChange(this, failedChannel, failedURI,
8073 LOCATION_CHANGE_ERROR_PAGE);
8074 } else if (onLocationChangeNeeded) {
8075 uint32_t locationFlags =
8076 (mLoadType & LOAD_CMD_RELOAD) ? uint32_t(LOCATION_CHANGE_RELOAD) : 0;
8077 FireOnLocationChange(this, aRequest, mCurrentURI, locationFlags);
8078 }
8079
8080 return NS_OK;
8081}
8082
8083nsresult nsDocShell::NewDocumentViewerObj(const nsACString& aContentType,
8084 nsIRequest* aRequest,
8085 nsILoadGroup* aLoadGroup,
8086 nsIStreamListener** aContentHandler,
8087 nsIDocumentViewer** aViewer) {
8088 nsCOMPtr<nsIChannel> aOpenedChannel = do_QueryInterface(aRequest);
8089
8090 nsCOMPtr<nsIDocumentLoaderFactory> docLoaderFactory =
8091 nsContentUtils::FindInternalDocumentViewer(aContentType);
8092 if (!docLoaderFactory) {
8093 return NS_ERROR_FAILURE;
8094 }
8095
8096 // Now create an instance of the content viewer nsLayoutDLF makes the
8097 // determination if it should be a "view-source" instead of "view"
8098 nsresult rv = docLoaderFactory->CreateInstance(
8099 "view", aOpenedChannel, aLoadGroup, aContentType, this, nullptr,
8100 aContentHandler, aViewer);
8101 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 8101); return rv; } } while (false)
;
8102
8103 (*aViewer)->SetContainer(this);
8104 return NS_OK;
8105}
8106
8107nsresult nsDocShell::SetupNewViewer(nsIDocumentViewer* aNewViewer,
8108 WindowGlobalChild* aWindowActor) {
8109 MOZ_ASSERT(!mIsBeingDestroyed)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mIsBeingDestroyed)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mIsBeingDestroyed))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("!mIsBeingDestroyed"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 8109); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!mIsBeingDestroyed" ")"); do { MOZ_CrashSequence
(__null, 8109); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
8110
8111 //
8112 // Copy content viewer state from previous or parent content viewer.
8113 //
8114 // The following logic is mirrored in nsHTMLDocument::StartDocumentLoad!
8115 //
8116 // Do NOT to maintain a reference to the old content viewer outside
8117 // of this "copying" block, or it will not be destroyed until the end of
8118 // this routine and all <SCRIPT>s and event handlers fail! (bug 20315)
8119 //
8120 // In this block of code, if we get an error result, we return it
8121 // but if we get a null pointer, that's perfectly legal for parent
8122 // and parentDocumentViewer.
8123 //
8124
8125 int32_t x = 0;
8126 int32_t y = 0;
8127 int32_t cx = 0;
8128 int32_t cy = 0;
8129
8130 // This will get the size from the current content viewer or from the
8131 // Init settings
8132 DoGetPositionAndSize(&x, &y, &cx, &cy);
8133
8134 nsCOMPtr<nsIDocShellTreeItem> parentAsItem;
8135 NS_ENSURE_SUCCESS(GetInProcessSameTypeParent(getter_AddRefs(parentAsItem)),do { nsresult __rv = GetInProcessSameTypeParent(getter_AddRefs
(parentAsItem)); if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "GetInProcessSameTypeParent(getter_AddRefs(parentAsItem))"
, "NS_ERROR_FAILURE", static_cast<uint32_t>(__rv), name
? " (" : "", name ? name : "", name ? ")" : ""); NS_DebugBreak
(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 8136); return NS_ERROR_FAILURE; } } while (false)
8136 NS_ERROR_FAILURE)do { nsresult __rv = GetInProcessSameTypeParent(getter_AddRefs
(parentAsItem)); if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "GetInProcessSameTypeParent(getter_AddRefs(parentAsItem))"
, "NS_ERROR_FAILURE", static_cast<uint32_t>(__rv), name
? " (" : "", name ? name : "", name ? ")" : ""); NS_DebugBreak
(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 8136); return NS_ERROR_FAILURE; } } while (false)
;
8137 nsCOMPtr<nsIDocShell> parent(do_QueryInterface(parentAsItem));
8138
8139 const Encoding* reloadEncoding = nullptr;
8140 int32_t reloadEncodingSource = kCharsetUninitialized;
8141 // |newMUDV| also serves as a flag to set the data from the above vars
8142 nsCOMPtr<nsIDocumentViewer> newViewer;
8143
8144 if (mDocumentViewer || parent) {
8145 nsCOMPtr<nsIDocumentViewer> oldViewer;
8146 if (mDocumentViewer) {
8147 // Get any interesting state from old content viewer
8148 // XXX: it would be far better to just reuse the document viewer ,
8149 // since we know we're just displaying the same document as before
8150 oldViewer = mDocumentViewer;
8151
8152 // Tell the old content viewer to hibernate in session history when
8153 // it is destroyed.
8154
8155 if (mSavingOldViewer && NS_FAILED(CaptureState())((bool)(__builtin_expect(!!(NS_FAILED_impl(CaptureState())), 0
)))
) {
8156 if (mOSHE) {
8157 mOSHE->SyncPresentationState();
8158 }
8159 mSavingOldViewer = false;
8160 }
8161 } else {
8162 // No old content viewer, so get state from parent's content viewer
8163 parent->GetDocViewer(getter_AddRefs(oldViewer));
8164 }
8165
8166 if (oldViewer) {
8167 newViewer = aNewViewer;
8168 if (newViewer) {
8169 reloadEncoding =
8170 oldViewer->GetReloadEncodingAndSource(&reloadEncodingSource);
8171 }
8172 }
8173 }
8174
8175 SingleCanvasBackground canvasBg = {};
8176 bool isUnderHiddenEmbedderElement = false;
8177 // Ensure that the content viewer is destroyed *after* the GC - bug 71515
8178 nsCOMPtr<nsIDocumentViewer> viewer = mDocumentViewer;
8179 if (viewer) {
8180 // Stop any activity that may be happening in the old document before
8181 // releasing it...
8182 viewer->Stop();
8183
8184 // Try to extract the canvas background color from the old
8185 // presentation shell, so we can use it for the next document.
8186 if (PresShell* presShell = viewer->GetPresShell()) {
8187 canvasBg = presShell->GetViewportCanvasBackground();
8188 isUnderHiddenEmbedderElement = presShell->IsUnderHiddenEmbedderElement();
8189 }
8190
8191 viewer->Close(mSavingOldViewer ? mOSHE.get() : nullptr);
8192 aNewViewer->SetPreviousViewer(viewer);
8193 }
8194 if (mOSHE && (!mDocumentViewer || !mSavingOldViewer)) {
8195 // We don't plan to save a viewer in mOSHE; tell it to drop
8196 // any other state it's holding.
8197 mOSHE->SyncPresentationState();
8198 }
8199
8200 mDocumentViewer = nullptr;
8201
8202 // Now that we're about to switch documents, forget all of our children.
8203 // Note that we cached them as needed up in CaptureState above.
8204 DestroyChildren();
8205
8206 mDocumentViewer = aNewViewer;
8207
8208 nsCOMPtr<nsIWidget> widget;
8209 NS_ENSURE_SUCCESS(GetMainWidget(getter_AddRefs(widget)), NS_ERROR_FAILURE)do { nsresult __rv = GetMainWidget(getter_AddRefs(widget)); if
(((bool)(__builtin_expect(!!(NS_FAILED_impl(__rv)), 0)))) { const
char* name = mozilla::GetStaticErrorName(__rv); mozilla::SmprintfPointer
msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "GetMainWidget(getter_AddRefs(widget))"
, "NS_ERROR_FAILURE", static_cast<uint32_t>(__rv), name
? " (" : "", name ? name : "", name ? ")" : ""); NS_DebugBreak
(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 8209); return NS_ERROR_FAILURE; } } while (false)
;
8210
8211 LayoutDeviceIntRect bounds(x, y, cx, cy);
8212
8213 mDocumentViewer->SetNavigationTiming(mTiming);
8214
8215 if (NS_FAILED(mDocumentViewer->Init(widget, bounds, aWindowActor))((bool)(__builtin_expect(!!(NS_FAILED_impl(mDocumentViewer->
Init(widget, bounds, aWindowActor))), 0)))
) {
8216 nsCOMPtr<nsIDocumentViewer> viewer = mDocumentViewer;
8217 viewer->Close(nullptr);
8218 viewer->Destroy();
8219 mDocumentViewer = nullptr;
8220 SetCurrentURIInternal(nullptr);
8221 NS_WARNING("DocumentViewer Initialization failed")NS_DebugBreak(NS_DEBUG_WARNING, "DocumentViewer Initialization failed"
, nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 8221)
;
8222 return NS_ERROR_FAILURE;
8223 }
8224
8225 // If we have old state to copy, set the old state onto the new content
8226 // viewer
8227 if (newViewer) {
8228 newViewer->SetReloadEncodingAndSource(reloadEncoding, reloadEncodingSource);
8229 }
8230
8231 NS_ENSURE_TRUE(mDocumentViewer, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(mDocumentViewer)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "mDocumentViewer" ") failed"
, nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 8231); return NS_ERROR_FAILURE; } } while (false)
;
8232
8233 // Stuff the bgcolor from the old pres shell into the new
8234 // pres shell. This improves page load continuity.
8235 if (RefPtr<PresShell> presShell = mDocumentViewer->GetPresShell()) {
8236 presShell->SetViewportCanvasBackground(canvasBg);
8237 presShell->ActivenessMaybeChanged();
8238 if (isUnderHiddenEmbedderElement) {
8239 presShell->SetIsUnderHiddenEmbedderElement(isUnderHiddenEmbedderElement);
8240 }
8241 }
8242
8243 // XXX: It looks like the LayoutState gets restored again in Embed()
8244 // right after the call to SetupNewViewer(...)
8245
8246 // We don't show the mDocumentViewer yet, since we want to draw the old page
8247 // until we have enough of the new page to show. Just return with the new
8248 // viewer still set to hidden.
8249
8250 return NS_OK;
8251}
8252
8253void nsDocShell::SetDocCurrentStateObj(nsISHEntry* aShEntry,
8254 SessionHistoryInfo* aInfo) {
8255 NS_ENSURE_TRUE_VOID(mDocumentViewer)do { if ((__builtin_expect(!!(!(mDocumentViewer)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "mDocumentViewer" ") failed"
, nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 8255); return; } } while (false)
;
8256
8257 RefPtr<Document> document = GetDocument();
8258 NS_ENSURE_TRUE_VOID(document)do { if ((__builtin_expect(!!(!(document)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "document" ") failed", nullptr
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 8258); return
; } } while (false)
;
8259
8260 nsCOMPtr<nsIStructuredCloneContainer> scContainer;
8261 if (mozilla::SessionHistoryInParent()) {
8262 // If aInfo is null, just set the document's state object to null.
8263 if (aInfo) {
8264 scContainer = aInfo->GetStateData();
8265 }
8266 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)
8267 ("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)
;
8268 } else {
8269 if (aShEntry) {
8270 scContainer = aShEntry->GetStateData();
8271
8272 // If aShEntry is null, just set the document's state object to null.
8273 }
8274 }
8275
8276 // It's OK for scContainer too be null here; that just means there's no
8277 // state data associated with this history entry.
8278 document->SetStateObject(scContainer);
8279}
8280
8281nsresult nsDocShell::CheckLoadingPermissions() {
8282 // This method checks whether the caller may load content into
8283 // this docshell. Even though we've done our best to hide windows
8284 // from code that doesn't have the right to access them, it's
8285 // still possible for an evil site to open a window and access
8286 // frames in the new window through window.frames[] (which is
8287 // allAccess for historic reasons), so we still need to do this
8288 // check on load.
8289 nsresult rv = NS_OK;
8290
8291 if (!IsSubframe()) {
8292 // We're not a frame. Permit all loads.
8293 return rv;
8294 }
8295
8296 // Note - The check for a current JSContext here isn't necessarily sensical.
8297 // It's just designed to preserve the old semantics during a mass-conversion
8298 // patch.
8299 if (!nsContentUtils::GetCurrentJSContext()) {
8300 return NS_OK;
8301 }
8302
8303 // Check if the caller is from the same origin as this docshell,
8304 // or any of its ancestors.
8305 nsIPrincipal* subjectPrincipal = nsContentUtils::SubjectPrincipal();
8306 for (RefPtr<BrowsingContext> bc = mBrowsingContext; bc;
8307 bc = bc->GetParent()) {
8308 // If the BrowsingContext is not in process, then it
8309 // is true by construction that its principal will not
8310 // subsume the current docshell principal.
8311 if (!bc->IsInProcess()) {
8312 continue;
8313 }
8314
8315 nsCOMPtr<nsIScriptGlobalObject> sgo =
8316 bc->GetDocShell()->GetScriptGlobalObject();
8317 nsCOMPtr<nsIScriptObjectPrincipal> sop(do_QueryInterface(sgo));
8318
8319 nsIPrincipal* p;
8320 if (!sop || !(p = sop->GetPrincipal())) {
8321 return NS_ERROR_UNEXPECTED;
8322 }
8323
8324 // file: URIs are considered the same domain for the purpose of frame
8325 // navigation by clicking a targeted link, regardless of script
8326 // accessibility (bug 1934807).
8327 if (subjectPrincipal->Subsumes(p) ||
8328 (subjectPrincipal->SchemeIs("file") && p->SchemeIs("file"))) {
8329 // Same origin, permit load
8330 return NS_OK;
8331 }
8332 }
8333
8334 return NS_ERROR_DOM_PROP_ACCESS_DENIED;
8335}
8336
8337//*****************************************************************************
8338// nsDocShell: Site Loading
8339//*****************************************************************************
8340
8341void nsDocShell::CopyFavicon(nsIURI* aOldURI, nsIURI* aNewURI,
8342 bool aInPrivateBrowsing) {
8343 if (XRE_IsContentProcess()) {
8344 dom::ContentChild* contentChild = dom::ContentChild::GetSingleton();
8345 if (contentChild) {
8346 contentChild->SendCopyFavicon(aOldURI, aNewURI, aInPrivateBrowsing);
8347 }
8348 return;
8349 }
8350
8351#ifdef MOZ_PLACES1
8352 auto* faviconService = nsFaviconService::GetFaviconService();
8353 if (faviconService) {
8354 faviconService->AsyncTryCopyFavicons(
8355 aOldURI, aNewURI,
8356 aInPrivateBrowsing ? nsIFaviconService::FAVICON_LOAD_PRIVATE
8357 : nsIFaviconService::FAVICON_LOAD_NON_PRIVATE);
8358 }
8359#endif
8360}
8361
8362class InternalLoadEvent : public Runnable {
8363 public:
8364 InternalLoadEvent(nsDocShell* aDocShell, nsDocShellLoadState* aLoadState)
8365 : mozilla::Runnable("InternalLoadEvent"),
8366 mDocShell(aDocShell),
8367 mLoadState(aLoadState) {
8368 // For events, both target and filename should be the version of "null" they
8369 // expect. By the time the event is fired, both window targeting and file
8370 // downloading have been handled, so we should never have an internal load
8371 // event that retargets or had a download.
8372 mLoadState->SetTarget(u""_ns);
8373 mLoadState->SetFileName(VoidString());
8374 }
8375
8376 NS_IMETHODvirtual nsresult
8377 Run() override {
8378#ifndef ANDROID
8379 MOZ_ASSERT(mLoadState->TriggeringPrincipal(),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mLoadState->TriggeringPrincipal())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mLoadState->TriggeringPrincipal
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("mLoadState->TriggeringPrincipal()" " (" "InternalLoadEvent: Should always have a principal here"
")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 8380
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mLoadState->TriggeringPrincipal()"
") (" "InternalLoadEvent: Should always have a principal here"
")"); do { MOZ_CrashSequence(__null, 8380); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
8380 "InternalLoadEvent: Should always have a principal here")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mLoadState->TriggeringPrincipal())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mLoadState->TriggeringPrincipal
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("mLoadState->TriggeringPrincipal()" " (" "InternalLoadEvent: Should always have a principal here"
")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 8380
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mLoadState->TriggeringPrincipal()"
") (" "InternalLoadEvent: Should always have a principal here"
")"); do { MOZ_CrashSequence(__null, 8380); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8381#endif
8382 return mDocShell->InternalLoad(mLoadState);
8383 }
8384
8385 private:
8386 RefPtr<nsDocShell> mDocShell;
8387 RefPtr<nsDocShellLoadState> mLoadState;
8388};
8389
8390/**
8391 * Returns true if we started an asynchronous load (i.e., from the network), but
8392 * the document we're loading there hasn't yet become this docshell's active
8393 * document.
8394 *
8395 * When JustStartedNetworkLoad is true, you should be careful about modifying
8396 * mLoadType and mLSHE. These are both set when the asynchronous load first
8397 * starts, and the load expects that, when it eventually runs InternalLoad,
8398 * mLoadType and mLSHE will have their original values.
8399 */
8400bool nsDocShell::JustStartedNetworkLoad() {
8401 return mDocumentRequest && mDocumentRequest != GetCurrentDocChannel();
8402}
8403
8404// The contentType will be INTERNAL_(I)FRAME if this docshell is for a
8405// non-toplevel browsing context in spec terms. (frame, iframe, <object>,
8406// <embed>, etc)
8407//
8408// This return value will be used when we call NS_CheckContentLoadPolicy, and
8409// later when we call DoURILoad.
8410nsContentPolicyType nsDocShell::DetermineContentType() {
8411 if (!IsSubframe()) {
8412 return nsIContentPolicy::TYPE_DOCUMENT;
8413 }
8414
8415 const auto& maybeEmbedderElementType =
8416 GetBrowsingContext()->GetEmbedderElementType();
8417 if (!maybeEmbedderElementType) {
8418 // If the EmbedderElementType hasn't been set yet, just assume we're
8419 // an iframe since that's more common.
8420 return nsIContentPolicy::TYPE_INTERNAL_IFRAME;
8421 }
8422
8423 return maybeEmbedderElementType->EqualsLiteral("iframe")
8424 ? nsIContentPolicy::TYPE_INTERNAL_IFRAME
8425 : nsIContentPolicy::TYPE_INTERNAL_FRAME;
8426}
8427
8428bool nsDocShell::NoopenerForceEnabled() {
8429 // If current's top-level browsing context's active document's
8430 // cross-origin-opener-policy is "same-origin" or "same-origin + COEP" then
8431 // if currentDoc's origin is not same origin with currentDoc's top-level
8432 // origin, noopener is force enabled, and name is cleared to "_blank".
8433 auto topPolicy = mBrowsingContext->Top()->GetOpenerPolicy();
8434 return (topPolicy == nsILoadInfo::OPENER_POLICY_SAME_ORIGIN ||
8435 topPolicy ==
8436 nsILoadInfo::
8437 OPENER_POLICY_SAME_ORIGIN_EMBEDDER_POLICY_REQUIRE_CORP) &&
8438 !mBrowsingContext->SameOriginWithTop();
8439}
8440
8441nsresult nsDocShell::PerformRetargeting(nsDocShellLoadState* aLoadState) {
8442 MOZ_ASSERT(aLoadState, "need a load state!")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aLoadState)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aLoadState))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("aLoadState" " (" "need a load state!"
")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 8442
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState" ") ("
"need a load state!" ")"); do { MOZ_CrashSequence(__null, 8442
); __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
;
8443 MOZ_ASSERT(!aLoadState->Target().IsEmpty(), "should have a target here!")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aLoadState->Target().IsEmpty())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!aLoadState->Target().IsEmpty
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!aLoadState->Target().IsEmpty()" " (" "should have a target here!"
")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 8443
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aLoadState->Target().IsEmpty()"
") (" "should have a target here!" ")"); do { MOZ_CrashSequence
(__null, 8443); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
8444 MOZ_ASSERT(aLoadState->TargetBrowsingContext().IsNull(),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aLoadState->TargetBrowsingContext().IsNull())>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(aLoadState->TargetBrowsingContext().IsNull()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("aLoadState->TargetBrowsingContext().IsNull()"
" (" "should not have picked target yet" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 8445); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->TargetBrowsingContext().IsNull()"
") (" "should not have picked target yet" ")"); do { MOZ_CrashSequence
(__null, 8445); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
8445 "should not have picked target yet")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aLoadState->TargetBrowsingContext().IsNull())>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(aLoadState->TargetBrowsingContext().IsNull()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("aLoadState->TargetBrowsingContext().IsNull()"
" (" "should not have picked target yet" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 8445); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->TargetBrowsingContext().IsNull()"
") (" "should not have picked target yet" ")"); do { MOZ_CrashSequence
(__null, 8445); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
8446
8447 nsresult rv = NS_OK;
8448 RefPtr<BrowsingContext> targetContext;
8449
8450 // Only _self, _parent, and _top are supported in noopener case. But we
8451 // have to be careful to not apply that to the noreferrer case. See bug
8452 // 1358469.
8453 bool allowNamedTarget =
8454 !aLoadState->HasInternalLoadFlags(INTERNAL_LOAD_FLAGS_NO_OPENER) ||
8455 aLoadState->HasInternalLoadFlags(INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER);
8456 if (allowNamedTarget ||
8457 aLoadState->Target().LowerCaseEqualsLiteral("_self") ||
8458 aLoadState->Target().LowerCaseEqualsLiteral("_parent") ||
8459 aLoadState->Target().LowerCaseEqualsLiteral("_top")) {
8460 Document* document = GetDocument();
8461 NS_ENSURE_TRUE(document, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(document)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "document" ") failed", nullptr
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 8461); return
NS_ERROR_FAILURE; } } while (false)
;
8462 WindowGlobalChild* wgc = document->GetWindowGlobalChild();
8463 NS_ENSURE_TRUE(wgc, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(wgc)), 0))) { NS_DebugBreak(NS_DEBUG_WARNING
, "NS_ENSURE_TRUE(" "wgc" ") failed", nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 8463); return NS_ERROR_FAILURE; } } while (false)
;
8464 targetContext = wgc->FindBrowsingContextWithName(
8465 aLoadState->Target(), /* aUseEntryGlobalForAccessCheck */ false);
8466 }
8467
8468 if (!targetContext) {
8469 // If the targetContext doesn't exist, then this is a new docShell and we
8470 // should consider this a TYPE_DOCUMENT load
8471 //
8472 // For example, when target="_blank"
8473
8474 // If there's no targetContext, that means we are about to create a new
8475 // window. Perform a content policy check before creating the window. Please
8476 // note for all other docshell loads content policy checks are performed
8477 // within the contentSecurityManager when the channel is about to be
8478 // openend.
8479 nsISupports* requestingContext = nullptr;
8480 if (XRE_IsContentProcess()) {
8481 // In e10s the child process doesn't have access to the element that
8482 // contains the browsing context (because that element is in the chrome
8483 // process). So we just pass mScriptGlobal.
8484 requestingContext = ToSupports(mScriptGlobal);
8485 } else {
8486 // This is for loading non-e10s tabs and toplevel windows of various
8487 // sorts.
8488 // For the toplevel window cases, requestingElement will be null.
8489 nsCOMPtr<Element> requestingElement =
8490 mScriptGlobal->GetFrameElementInternal();
8491 requestingContext = requestingElement;
8492 }
8493
8494 // Ideally we should use the same loadinfo as within DoURILoad which
8495 // should match this one when both are applicable.
8496 nsCOMPtr<nsILoadInfo> secCheckLoadInfo =
8497 new LoadInfo(mScriptGlobal, aLoadState->URI(),
8498 aLoadState->TriggeringPrincipal(), requestingContext,
8499 nsILoadInfo::SEC_ONLY_FOR_EXPLICIT_CONTENTSEC_CHECK, 0);
8500
8501 // Since Content Policy checks are performed within docShell as well as
8502 // the ContentSecurityManager we need a reliable way to let certain
8503 // nsIContentPolicy consumers ignore duplicate calls.
8504 secCheckLoadInfo->SetSkipContentPolicyCheckForWebRequest(true);
8505
8506 int16_t shouldLoad = nsIContentPolicy::ACCEPT;
8507 rv = NS_CheckContentLoadPolicy(aLoadState->URI(), secCheckLoadInfo,
8508 &shouldLoad);
8509
8510 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) || NS_CP_REJECTED(shouldLoad)((shouldLoad) != nsIContentPolicy::ACCEPT)) {
8511 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
8512 if (shouldLoad == nsIContentPolicy::REJECT_TYPE) {
8513 return NS_ERROR_CONTENT_BLOCKED_SHOW_ALT;
8514 }
8515 if (shouldLoad == nsIContentPolicy::REJECT_POLICY) {
8516 return NS_ERROR_BLOCKED_BY_POLICY;
8517 }
8518 }
8519
8520 return NS_ERROR_CONTENT_BLOCKED;
8521 }
8522 }
8523
8524 //
8525 // Resolve the window target before going any further...
8526 // If the load has been targeted to another DocShell, then transfer the
8527 // load to it...
8528 //
8529
8530 // We've already done our owner-inheriting. Mask out that bit, so we
8531 // don't try inheriting an owner from the target window if we came up
8532 // with a null owner above.
8533 aLoadState->UnsetInternalLoadFlag(INTERNAL_LOAD_FLAGS_INHERIT_PRINCIPAL);
8534
8535 if (!targetContext) {
8536 // If the docshell's document is sandboxed, only open a new window
8537 // if the document's SANDBOXED_AUXILLARY_NAVIGATION flag is not set.
8538 // (i.e. if allow-popups is specified)
8539 NS_ENSURE_TRUE(mDocumentViewer, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(mDocumentViewer)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "mDocumentViewer" ") failed"
, nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 8539); return NS_ERROR_FAILURE; } } while (false)
;
8540 Document* doc = mDocumentViewer->GetDocument();
8541
8542 const bool isDocumentAuxSandboxed =
8543 doc && (doc->GetSandboxFlags() & SANDBOXED_AUXILIARY_NAVIGATION);
8544
8545 if (isDocumentAuxSandboxed) {
8546 return NS_ERROR_DOM_INVALID_ACCESS_ERR;
8547 }
8548
8549 nsCOMPtr<nsPIDOMWindowOuter> win = GetWindow();
8550 NS_ENSURE_TRUE(win, NS_ERROR_NOT_AVAILABLE)do { if ((__builtin_expect(!!(!(win)), 0))) { NS_DebugBreak(NS_DEBUG_WARNING
, "NS_ENSURE_TRUE(" "win" ") failed", nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 8550); return NS_ERROR_NOT_AVAILABLE; } } while (false)
;
8551
8552 RefPtr<BrowsingContext> newBC;
8553 nsAutoCString spec;
8554 aLoadState->URI()->GetSpec(spec);
8555
8556 // If we are a noopener load, we just hand the whole thing over to our
8557 // window.
8558 if (aLoadState->HasInternalLoadFlags(INTERNAL_LOAD_FLAGS_NO_OPENER) ||
8559 NoopenerForceEnabled()) {
8560 // Various asserts that we know to hold because NO_OPENER loads can only
8561 // happen for links.
8562 MOZ_ASSERT(!aLoadState->LoadReplace())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aLoadState->LoadReplace())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!aLoadState->LoadReplace(
)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!aLoadState->LoadReplace()", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 8562); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aLoadState->LoadReplace()"
")"); do { MOZ_CrashSequence(__null, 8562); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8563 MOZ_ASSERT(aLoadState->PrincipalToInherit() ==do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aLoadState->PrincipalToInherit() == aLoadState->
TriggeringPrincipal())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aLoadState->PrincipalToInherit
() == aLoadState->TriggeringPrincipal()))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aLoadState->PrincipalToInherit() == aLoadState->TriggeringPrincipal()"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 8564); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aLoadState->PrincipalToInherit() == aLoadState->TriggeringPrincipal()"
")"); do { MOZ_CrashSequence(__null, 8564); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
8564 aLoadState->TriggeringPrincipal())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aLoadState->PrincipalToInherit() == aLoadState->
TriggeringPrincipal())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aLoadState->PrincipalToInherit
() == aLoadState->TriggeringPrincipal()))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aLoadState->PrincipalToInherit() == aLoadState->TriggeringPrincipal()"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 8564); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aLoadState->PrincipalToInherit() == aLoadState->TriggeringPrincipal()"
")"); do { MOZ_CrashSequence(__null, 8564); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8565 MOZ_ASSERT(!(aLoadState->InternalLoadFlags() &do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!(aLoadState->InternalLoadFlags() & ~(INTERNAL_LOAD_FLAGS_NO_OPENER
| INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER)))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!(aLoadState->InternalLoadFlags
() & ~(INTERNAL_LOAD_FLAGS_NO_OPENER | INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER
))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!(aLoadState->InternalLoadFlags() & ~(INTERNAL_LOAD_FLAGS_NO_OPENER | INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER))"
" (" "Only INTERNAL_LOAD_FLAGS_NO_OPENER and " "INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER can be set"
")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 8569
); 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, 8569); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
8566 ~(INTERNAL_LOAD_FLAGS_NO_OPENER |do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!(aLoadState->InternalLoadFlags() & ~(INTERNAL_LOAD_FLAGS_NO_OPENER
| INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER)))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!(aLoadState->InternalLoadFlags
() & ~(INTERNAL_LOAD_FLAGS_NO_OPENER | INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER
))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!(aLoadState->InternalLoadFlags() & ~(INTERNAL_LOAD_FLAGS_NO_OPENER | INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER))"
" (" "Only INTERNAL_LOAD_FLAGS_NO_OPENER and " "INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER can be set"
")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 8569
); 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, 8569); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
8567 INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER)),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!(aLoadState->InternalLoadFlags() & ~(INTERNAL_LOAD_FLAGS_NO_OPENER
| INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER)))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!(aLoadState->InternalLoadFlags
() & ~(INTERNAL_LOAD_FLAGS_NO_OPENER | INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER
))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!(aLoadState->InternalLoadFlags() & ~(INTERNAL_LOAD_FLAGS_NO_OPENER | INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER))"
" (" "Only INTERNAL_LOAD_FLAGS_NO_OPENER and " "INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER can be set"
")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 8569
); 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, 8569); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
8568 "Only INTERNAL_LOAD_FLAGS_NO_OPENER and "do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!(aLoadState->InternalLoadFlags() & ~(INTERNAL_LOAD_FLAGS_NO_OPENER
| INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER)))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!(aLoadState->InternalLoadFlags
() & ~(INTERNAL_LOAD_FLAGS_NO_OPENER | INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER
))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!(aLoadState->InternalLoadFlags() & ~(INTERNAL_LOAD_FLAGS_NO_OPENER | INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER))"
" (" "Only INTERNAL_LOAD_FLAGS_NO_OPENER and " "INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER can be set"
")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 8569
); 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, 8569); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
8569 "INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER can be set")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!(aLoadState->InternalLoadFlags() & ~(INTERNAL_LOAD_FLAGS_NO_OPENER
| INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER)))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!(aLoadState->InternalLoadFlags
() & ~(INTERNAL_LOAD_FLAGS_NO_OPENER | INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER
))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!(aLoadState->InternalLoadFlags() & ~(INTERNAL_LOAD_FLAGS_NO_OPENER | INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER))"
" (" "Only INTERNAL_LOAD_FLAGS_NO_OPENER and " "INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER can be set"
")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 8569
); 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, 8569); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8570 MOZ_ASSERT_IF(aLoadState->PostDataStream(),do { if (aLoadState->PostDataStream()) { do { static_assert
( mozilla::detail::AssertionConditionType<decltype(aLoadState
->IsFormSubmission())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aLoadState->IsFormSubmission
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("aLoadState->IsFormSubmission()", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 8571); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->IsFormSubmission()"
")"); do { MOZ_CrashSequence(__null, 8571); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
8571 aLoadState->IsFormSubmission())do { if (aLoadState->PostDataStream()) { do { static_assert
( mozilla::detail::AssertionConditionType<decltype(aLoadState
->IsFormSubmission())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aLoadState->IsFormSubmission
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("aLoadState->IsFormSubmission()", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 8571); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->IsFormSubmission()"
")"); do { MOZ_CrashSequence(__null, 8571); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
8572 MOZ_ASSERT(!aLoadState->HeadersStream())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aLoadState->HeadersStream())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!aLoadState->HeadersStream
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!aLoadState->HeadersStream()", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 8572); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aLoadState->HeadersStream()"
")"); do { MOZ_CrashSequence(__null, 8572); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8573 // If OnLinkClickSync was invoked inside the onload handler, the load
8574 // type would be set to LOAD_NORMAL_REPLACE; otherwise it should be
8575 // LOAD_LINK.
8576 MOZ_ASSERT(aLoadState->LoadType() == LOAD_LINK ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aLoadState->LoadType() == LOAD_LINK || aLoadState
->LoadType() == LOAD_NORMAL_REPLACE)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aLoadState->LoadType() ==
LOAD_LINK || aLoadState->LoadType() == LOAD_NORMAL_REPLACE
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"aLoadState->LoadType() == LOAD_LINK || aLoadState->LoadType() == LOAD_NORMAL_REPLACE"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 8577); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aLoadState->LoadType() == LOAD_LINK || aLoadState->LoadType() == LOAD_NORMAL_REPLACE"
")"); do { MOZ_CrashSequence(__null, 8577); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
8577 aLoadState->LoadType() == LOAD_NORMAL_REPLACE)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aLoadState->LoadType() == LOAD_LINK || aLoadState
->LoadType() == LOAD_NORMAL_REPLACE)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aLoadState->LoadType() ==
LOAD_LINK || aLoadState->LoadType() == LOAD_NORMAL_REPLACE
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"aLoadState->LoadType() == LOAD_LINK || aLoadState->LoadType() == LOAD_NORMAL_REPLACE"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 8577); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aLoadState->LoadType() == LOAD_LINK || aLoadState->LoadType() == LOAD_NORMAL_REPLACE"
")"); do { MOZ_CrashSequence(__null, 8577); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8578 MOZ_ASSERT(!aLoadState->LoadIsFromSessionHistory())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aLoadState->LoadIsFromSessionHistory())>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(!aLoadState->LoadIsFromSessionHistory()))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("!aLoadState->LoadIsFromSessionHistory()"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 8578); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!aLoadState->LoadIsFromSessionHistory()"
")"); do { MOZ_CrashSequence(__null, 8578); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8579 MOZ_ASSERT(aLoadState->FirstParty())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aLoadState->FirstParty())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aLoadState->FirstParty())
)), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aLoadState->FirstParty()"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 8579); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aLoadState->FirstParty()" ")"); do { MOZ_CrashSequence
(__null, 8579); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
; // Windowwatcher will assume this.
8580
8581 RefPtr<nsDocShellLoadState> loadState =
8582 new nsDocShellLoadState(aLoadState->URI());
8583
8584 // Set up our loadinfo so it will do the load as much like we would have
8585 // as possible.
8586 loadState->SetReferrerInfo(aLoadState->GetReferrerInfo());
8587 loadState->SetOriginalURI(aLoadState->OriginalURI());
8588
8589 Maybe<nsCOMPtr<nsIURI>> resultPrincipalURI;
8590 aLoadState->GetMaybeResultPrincipalURI(resultPrincipalURI);
8591
8592 loadState->SetMaybeResultPrincipalURI(resultPrincipalURI);
8593 loadState->SetKeepResultPrincipalURIIfSet(
8594 aLoadState->KeepResultPrincipalURIIfSet());
8595 // LoadReplace will always be false due to asserts above, skip setting
8596 // it.
8597 loadState->SetTriggeringPrincipal(aLoadState->TriggeringPrincipal());
8598 loadState->SetTriggeringSandboxFlags(
8599 aLoadState->TriggeringSandboxFlags());
8600 loadState->SetTriggeringWindowId(aLoadState->TriggeringWindowId());
8601 loadState->SetTriggeringStorageAccess(
8602 aLoadState->TriggeringStorageAccess());
8603 loadState->SetTriggeringClassificationFlags(
8604 aLoadState->TriggeringClassificationFlags());
8605 loadState->SetCsp(aLoadState->Csp());
8606 loadState->SetInheritPrincipal(aLoadState->HasInternalLoadFlags(
8607 INTERNAL_LOAD_FLAGS_INHERIT_PRINCIPAL));
8608 // Explicit principal because we do not want any guesses as to what the
8609 // principal to inherit is: it should be aTriggeringPrincipal.
8610 loadState->SetPrincipalIsExplicit(true);
8611 loadState->SetLoadType(aLoadState->LoadType());
8612 loadState->SetForceAllowDataURI(aLoadState->HasInternalLoadFlags(
8613 INTERNAL_LOAD_FLAGS_FORCE_ALLOW_DATA_URI));
8614
8615 loadState->SetHasValidUserGestureActivation(
8616 aLoadState->HasValidUserGestureActivation());
8617
8618 loadState->SetTextDirectiveUserActivation(
8619 aLoadState->GetTextDirectiveUserActivation());
8620
8621 // Propagate POST data to the new load.
8622 loadState->SetPostDataStream(aLoadState->PostDataStream());
8623 loadState->SetIsFormSubmission(aLoadState->IsFormSubmission());
8624
8625 rv = win->Open(spec,
8626 aLoadState->Target(), // window name
8627 u""_ns, // Features
8628 loadState,
8629 true, // aForceNoOpener
8630 getter_AddRefs(newBC));
8631 MOZ_ASSERT(!newBC)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!newBC)>::isValid, "invalid assertion condition")
; if ((__builtin_expect(!!(!(!!(!newBC))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("!newBC", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 8631); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!newBC" ")"
); do { MOZ_CrashSequence(__null, 8631); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8632 return rv;
8633 }
8634
8635 rv = win->OpenNoNavigate(spec,
8636 aLoadState->Target(), // window name
8637 u""_ns, // Features
8638 getter_AddRefs(newBC));
8639
8640 // In some cases the Open call doesn't actually result in a new
8641 // window being opened. We can detect these cases by examining the
8642 // document in |newBC|, if any.
8643 nsCOMPtr<nsPIDOMWindowOuter> piNewWin =
8644 newBC ? newBC->GetDOMWindow() : nullptr;
8645 if (piNewWin) {
8646 RefPtr<Document> newDoc = piNewWin->GetExtantDoc();
8647 if (!newDoc || newDoc->IsInitialDocument()) {
8648 aLoadState->SetInternalLoadFlag(INTERNAL_LOAD_FLAGS_FIRST_LOAD);
8649 }
8650 }
8651
8652 if (newBC) {
8653 targetContext = newBC;
8654 }
8655 }
8656 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 8656); return rv; } } while (false)
;
8657 NS_ENSURE_TRUE(targetContext, rv)do { if ((__builtin_expect(!!(!(targetContext)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "targetContext" ") failed"
, nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 8657); return rv; } } while (false)
;
8658
8659 // If our target BrowsingContext is still pending initialization, ignore the
8660 // navigation request targeting it.
8661 if (NS_WARN_IF(targetContext->GetPendingInitialization())NS_warn_if_impl(targetContext->GetPendingInitialization(),
"targetContext->GetPendingInitialization()", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 8661)
) {
8662 return NS_OK;
8663 }
8664
8665 aLoadState->SetTargetBrowsingContext(targetContext);
8666 if (aLoadState->IsFormSubmission()) {
8667 aLoadState->SetLoadType(
8668 GetLoadTypeForFormSubmission(targetContext, aLoadState));
8669 }
8670
8671 //
8672 // Transfer the load to the target BrowsingContext... Clear the window target
8673 // name to the empty string to prevent recursive retargeting!
8674 //
8675 // No window target
8676 aLoadState->SetTarget(u""_ns);
8677 // No forced download
8678 aLoadState->SetFileName(VoidString());
8679 return targetContext->InternalLoad(aLoadState);
8680}
8681
8682static nsAutoCString RefMaybeNull(nsIURI* aURI) {
8683 nsAutoCString result;
8684 if (NS_FAILED(aURI->GetRef(result))((bool)(__builtin_expect(!!(NS_FAILED_impl(aURI->GetRef(result
))), 0)))
) {
8685 result.SetIsVoid(true);
8686 }
8687 return result;
8688}
8689
8690uint32_t nsDocShell::GetSameDocumentNavigationFlags(nsIURI* aNewURI) {
8691 uint32_t flags = LOCATION_CHANGE_SAME_DOCUMENT;
8692
8693 bool equal = false;
8694 if (mCurrentURI &&
8695 NS_SUCCEEDED(mCurrentURI->EqualsExceptRef(aNewURI, &equal))((bool)(__builtin_expect(!!(!NS_FAILED_impl(mCurrentURI->EqualsExceptRef
(aNewURI, &equal))), 1)))
&& equal &&
8696 RefMaybeNull(mCurrentURI) != RefMaybeNull(aNewURI)) {
8697 flags |= LOCATION_CHANGE_HASHCHANGE;
8698 }
8699
8700 return flags;
8701}
8702
8703struct SameDocumentNavigationState {
8704 nsAutoCString mCurrentHash;
8705 nsAutoCString mNewHash;
8706 nsTArray<TextDirective> mTextDirectives;
8707 bool mCurrentURIHasRef = false;
8708 bool mNewURIHasRef = false;
8709 bool mSameExceptHashes = false;
8710 bool mSecureUpgradeURI = false;
8711 bool mHistoryNavBetweenSameDoc = false;
8712};
8713
8714bool nsDocShell::IsSameDocumentNavigation(nsDocShellLoadState* aLoadState,
8715 SameDocumentNavigationState& aState) {
8716 MOZ_ASSERT(aLoadState)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aLoadState)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aLoadState))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("aLoadState", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 8716); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState"
")"); do { MOZ_CrashSequence(__null, 8716); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8717 if (!(aLoadState->LoadType() == LOAD_NORMAL ||
8718 aLoadState->LoadType() == LOAD_STOP_CONTENT ||
8719 LOAD_TYPE_HAS_FLAGS(aLoadState->LoadType(),((aLoadState->LoadType()) & ((LOAD_FLAGS_REPLACE_HISTORY
) << 16))
8720 LOAD_FLAGS_REPLACE_HISTORY)((aLoadState->LoadType()) & ((LOAD_FLAGS_REPLACE_HISTORY
) << 16))
||
8721 aLoadState->LoadType() == LOAD_HISTORY ||
8722 aLoadState->LoadType() == LOAD_LINK)) {
8723 return false;
8724 }
8725
8726 nsCOMPtr<nsIURI> currentURI = mCurrentURI;
8727
8728 nsresult rvURINew = aLoadState->URI()->GetRef(aState.mNewHash);
8729 if (NS_SUCCEEDED(rvURINew)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rvURINew)), 1)))) {
8730 rvURINew = aLoadState->URI()->GetHasRef(&aState.mNewURIHasRef);
8731 }
8732
8733 // A Fragment Directive must be removed from the new hash in order to allow
8734 // fallback element id scroll.
8735 FragmentDirective::ParseAndRemoveFragmentDirectiveFromFragmentString(
8736 aState.mNewHash, &aState.mTextDirectives, aLoadState->URI());
8737
8738 if (currentURI && NS_SUCCEEDED(rvURINew)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rvURINew)), 1)))) {
8739 nsresult rvURIOld = currentURI->GetRef(aState.mCurrentHash);
8740 if (NS_SUCCEEDED(rvURIOld)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rvURIOld)), 1)))) {
8741 rvURIOld = currentURI->GetHasRef(&aState.mCurrentURIHasRef);
8742 }
8743 if (NS_SUCCEEDED(rvURIOld)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rvURIOld)), 1)))) {
8744 if (NS_FAILED(currentURI->EqualsExceptRef(aLoadState->URI(),((bool)(__builtin_expect(!!(NS_FAILED_impl(currentURI->EqualsExceptRef
(aLoadState->URI(), &aState.mSameExceptHashes))), 0)))
8745 &aState.mSameExceptHashes))((bool)(__builtin_expect(!!(NS_FAILED_impl(currentURI->EqualsExceptRef
(aLoadState->URI(), &aState.mSameExceptHashes))), 0)))
) {
8746 aState.mSameExceptHashes = false;
8747 }
8748 }
8749 }
8750
8751 if (!aState.mSameExceptHashes && currentURI && NS_SUCCEEDED(rvURINew)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rvURINew)), 1)))) {
8752 // Maybe aLoadState->URI() came from the exposable form of currentURI?
8753 nsCOMPtr<nsIURI> currentExposableURI =
8754 nsIOService::CreateExposableURI(currentURI);
8755 nsresult rvURIOld = currentExposableURI->GetRef(aState.mCurrentHash);
8756 if (NS_SUCCEEDED(rvURIOld)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rvURIOld)), 1)))) {
8757 rvURIOld = currentExposableURI->GetHasRef(&aState.mCurrentURIHasRef);
8758 }
8759 if (NS_SUCCEEDED(rvURIOld)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rvURIOld)), 1)))) {
8760 if (NS_FAILED(currentExposableURI->EqualsExceptRef(((bool)(__builtin_expect(!!(NS_FAILED_impl(currentExposableURI
->EqualsExceptRef( aLoadState->URI(), &aState.mSameExceptHashes
))), 0)))
8761 aLoadState->URI(), &aState.mSameExceptHashes))((bool)(__builtin_expect(!!(NS_FAILED_impl(currentExposableURI
->EqualsExceptRef( aLoadState->URI(), &aState.mSameExceptHashes
))), 0)))
) {
8762 aState.mSameExceptHashes = false;
8763 }
8764 // HTTPS-Only Mode upgrades schemes from http to https in Necko, hence we
8765 // have to perform a special check here to avoid an actual navigation. If
8766 // HTTPS-Only Mode is enabled and the two URIs are same-origin (modulo the
8767 // fact that the new URI is currently http), then set mSameExceptHashes to
8768 // true and only perform a fragment navigation.
8769 if (!aState.mSameExceptHashes) {
8770 if (nsCOMPtr<nsIChannel> docChannel = GetCurrentDocChannel()) {
8771 nsCOMPtr<nsILoadInfo> docLoadInfo = docChannel->LoadInfo();
8772 nsHTTPSOnlyUtils::UpgradeMode upgradeMode =
8773 nsHTTPSOnlyUtils::GetUpgradeMode(docLoadInfo);
8774 if (!docLoadInfo->GetLoadErrorPage() &&
8775 (upgradeMode == nsHTTPSOnlyUtils::HTTPS_ONLY_MODE ||
8776 upgradeMode == nsHTTPSOnlyUtils::HTTPS_FIRST_MODE) &&
8777 nsHTTPSOnlyUtils::IsHttpDowngrade(currentExposableURI,
8778 aLoadState->URI())) {
8779 uint32_t status = docLoadInfo->GetHttpsOnlyStatus();
8780 if ((status &
8781 (nsILoadInfo::HTTPS_ONLY_UPGRADED_LISTENER_REGISTERED |
8782 nsILoadInfo::HTTPS_ONLY_UPGRADED_HTTPS_FIRST)) &&
8783 !(status & nsILoadInfo::HTTPS_ONLY_EXEMPT)) {
8784 // At this point the requested URI is for sure a fragment
8785 // navigation via HTTP and HTTPS-Only mode or HTTPS-First is
8786 // enabled. Also it is not interfering the upgrade order of
8787 // https://searchfox.org/mozilla-central/source/netwerk/base/nsNetUtil.cpp#2948-2953.
8788 // Since we are on an HTTPS site the fragment
8789 // navigation should also be an HTTPS.
8790 // For that reason we should upgrade the URI to HTTPS.
8791 aState.mSecureUpgradeURI = true;
8792 aState.mSameExceptHashes = true;
8793 }
8794 }
8795 }
8796 }
8797 }
8798 }
8799
8800 if (mozilla::SessionHistoryInParent()) {
8801 if (mActiveEntry && aLoadState->LoadIsFromSessionHistory()) {
8802 aState.mHistoryNavBetweenSameDoc = mActiveEntry->SharesDocumentWith(
8803 aLoadState->GetLoadingSessionHistoryInfo()->mInfo);
8804 }
8805 MOZ_LOG(gSHLog, LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = gSHLog; if
((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "nsDocShell::IsSameDocumentNavigation %p NavBetweenSameDoc=%d"
, this, aState.mHistoryNavBetweenSameDoc); } } while (0)
8806 ("nsDocShell::IsSameDocumentNavigation %p NavBetweenSameDoc=%d",do { const ::mozilla::LogModule* moz_real_module = gSHLog; if
((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "nsDocShell::IsSameDocumentNavigation %p NavBetweenSameDoc=%d"
, this, aState.mHistoryNavBetweenSameDoc); } } while (0)
8807 this, aState.mHistoryNavBetweenSameDoc))do { const ::mozilla::LogModule* moz_real_module = gSHLog; if
((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "nsDocShell::IsSameDocumentNavigation %p NavBetweenSameDoc=%d"
, this, aState.mHistoryNavBetweenSameDoc); } } while (0)
;
8808 } else {
8809 if (mOSHE && aLoadState->LoadIsFromSessionHistory()) {
8810 // We're doing a history load.
8811
8812 mOSHE->SharesDocumentWith(aLoadState->SHEntry(),
8813 &aState.mHistoryNavBetweenSameDoc);
8814 }
8815 }
8816
8817 // A same document navigation happens when we navigate between two SHEntries
8818 // for the same document. We do a same document navigation under two
8819 // circumstances. Either
8820 //
8821 // a) we're navigating between two different SHEntries which share a
8822 // document, or
8823 //
8824 // b) we're navigating to a new shentry whose URI differs from the
8825 // current URI only in its hash, the new hash is non-empty, and
8826 // we're not doing a POST.
8827 //
8828 // The restriction that the SHEntries in (a) must be different ensures
8829 // that history.go(0) and the like trigger full refreshes, rather than
8830 // same document navigations.
8831 if (!mozilla::SessionHistoryInParent()) {
8832 bool doSameDocumentNavigation =
8833 (aState.mHistoryNavBetweenSameDoc && mOSHE != aLoadState->SHEntry()) ||
8834 (!aLoadState->SHEntry() && !aLoadState->PostDataStream() &&
8835 aState.mSameExceptHashes && aState.mNewURIHasRef);
8836 MOZ_LOG(gSHLog, LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = gSHLog; if
((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "nsDocShell %p NavBetweenSameDoc=%d is same doc = %d"
, this, aState.mHistoryNavBetweenSameDoc, doSameDocumentNavigation
); } } while (0)
8837 ("nsDocShell %p NavBetweenSameDoc=%d is same doc = %d", this,do { const ::mozilla::LogModule* moz_real_module = gSHLog; if
((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "nsDocShell %p NavBetweenSameDoc=%d is same doc = %d"
, this, aState.mHistoryNavBetweenSameDoc, doSameDocumentNavigation
); } } while (0)
8838 aState.mHistoryNavBetweenSameDoc, doSameDocumentNavigation))do { const ::mozilla::LogModule* moz_real_module = gSHLog; if
((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "nsDocShell %p NavBetweenSameDoc=%d is same doc = %d"
, this, aState.mHistoryNavBetweenSameDoc, doSameDocumentNavigation
); } } while (0)
;
8839 return doSameDocumentNavigation;
8840 }
8841
8842 if (aState.mHistoryNavBetweenSameDoc &&
8843 !aLoadState->GetLoadingSessionHistoryInfo()->mLoadingCurrentEntry) {
8844 return true;
8845 }
8846
8847 MOZ_LOG(do { const ::mozilla::LogModule* moz_real_module = gSHLog; if
((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "nsDocShell::IsSameDocumentNavigation %p !LoadIsFromSessionHistory=%s "
"!PostDataStream: %s mSameExceptHashes: %s mNewURIHasRef: %s"
, this, !aLoadState->LoadIsFromSessionHistory() ? "true" :
"false", !aLoadState->PostDataStream() ? "true" : "false"
, aState.mSameExceptHashes ? "true" : "false", aState.mNewURIHasRef
? "true" : "false"); } } while (0)
8848 gSHLog, LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = gSHLog; if
((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "nsDocShell::IsSameDocumentNavigation %p !LoadIsFromSessionHistory=%s "
"!PostDataStream: %s mSameExceptHashes: %s mNewURIHasRef: %s"
, this, !aLoadState->LoadIsFromSessionHistory() ? "true" :
"false", !aLoadState->PostDataStream() ? "true" : "false"
, aState.mSameExceptHashes ? "true" : "false", aState.mNewURIHasRef
? "true" : "false"); } } while (0)
8849 ("nsDocShell::IsSameDocumentNavigation %p !LoadIsFromSessionHistory=%s "do { const ::mozilla::LogModule* moz_real_module = gSHLog; if
((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "nsDocShell::IsSameDocumentNavigation %p !LoadIsFromSessionHistory=%s "
"!PostDataStream: %s mSameExceptHashes: %s mNewURIHasRef: %s"
, this, !aLoadState->LoadIsFromSessionHistory() ? "true" :
"false", !aLoadState->PostDataStream() ? "true" : "false"
, aState.mSameExceptHashes ? "true" : "false", aState.mNewURIHasRef
? "true" : "false"); } } while (0)
8850 "!PostDataStream: %s mSameExceptHashes: %s mNewURIHasRef: %s",do { const ::mozilla::LogModule* moz_real_module = gSHLog; if
((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "nsDocShell::IsSameDocumentNavigation %p !LoadIsFromSessionHistory=%s "
"!PostDataStream: %s mSameExceptHashes: %s mNewURIHasRef: %s"
, this, !aLoadState->LoadIsFromSessionHistory() ? "true" :
"false", !aLoadState->PostDataStream() ? "true" : "false"
, aState.mSameExceptHashes ? "true" : "false", aState.mNewURIHasRef
? "true" : "false"); } } while (0)
8851 this, !aLoadState->LoadIsFromSessionHistory() ? "true" : "false",do { const ::mozilla::LogModule* moz_real_module = gSHLog; if
((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "nsDocShell::IsSameDocumentNavigation %p !LoadIsFromSessionHistory=%s "
"!PostDataStream: %s mSameExceptHashes: %s mNewURIHasRef: %s"
, this, !aLoadState->LoadIsFromSessionHistory() ? "true" :
"false", !aLoadState->PostDataStream() ? "true" : "false"
, aState.mSameExceptHashes ? "true" : "false", aState.mNewURIHasRef
? "true" : "false"); } } while (0)
8852 !aLoadState->PostDataStream() ? "true" : "false",do { const ::mozilla::LogModule* moz_real_module = gSHLog; if
((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "nsDocShell::IsSameDocumentNavigation %p !LoadIsFromSessionHistory=%s "
"!PostDataStream: %s mSameExceptHashes: %s mNewURIHasRef: %s"
, this, !aLoadState->LoadIsFromSessionHistory() ? "true" :
"false", !aLoadState->PostDataStream() ? "true" : "false"
, aState.mSameExceptHashes ? "true" : "false", aState.mNewURIHasRef
? "true" : "false"); } } while (0)
8853 aState.mSameExceptHashes ? "true" : "false",do { const ::mozilla::LogModule* moz_real_module = gSHLog; if
((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "nsDocShell::IsSameDocumentNavigation %p !LoadIsFromSessionHistory=%s "
"!PostDataStream: %s mSameExceptHashes: %s mNewURIHasRef: %s"
, this, !aLoadState->LoadIsFromSessionHistory() ? "true" :
"false", !aLoadState->PostDataStream() ? "true" : "false"
, aState.mSameExceptHashes ? "true" : "false", aState.mNewURIHasRef
? "true" : "false"); } } while (0)
8854 aState.mNewURIHasRef ? "true" : "false"))do { const ::mozilla::LogModule* moz_real_module = gSHLog; if
((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "nsDocShell::IsSameDocumentNavigation %p !LoadIsFromSessionHistory=%s "
"!PostDataStream: %s mSameExceptHashes: %s mNewURIHasRef: %s"
, this, !aLoadState->LoadIsFromSessionHistory() ? "true" :
"false", !aLoadState->PostDataStream() ? "true" : "false"
, aState.mSameExceptHashes ? "true" : "false", aState.mNewURIHasRef
? "true" : "false"); } } while (0)
;
8855 return !aLoadState->LoadIsFromSessionHistory() &&
8856 !aLoadState->PostDataStream() && aState.mSameExceptHashes &&
8857 aState.mNewURIHasRef;
8858}
8859
8860static bool IsSamePrincipalForDocumentURI(nsIPrincipal* aCurrentPrincipal,
8861 nsIURI* aCurrentURI,
8862 nsIURI* aNewURI) {
8863 if (!StaticPrefs::dom_security_setdocumenturi()) {
8864 return true;
8865 }
8866 nsCOMPtr<nsIURI> principalURI = aCurrentPrincipal->GetURI();
8867 if (aCurrentPrincipal->GetIsNullPrincipal()) {
8868 nsCOMPtr<nsIPrincipal> precursor =
8869 aCurrentPrincipal->GetPrecursorPrincipal();
8870 if (precursor) {
8871 principalURI = precursor->GetURI();
8872 }
8873 }
8874
8875 return !nsScriptSecurityManager::IsHttpOrHttpsAndCrossOrigin(principalURI,
8876 aNewURI) &&
8877 !nsScriptSecurityManager::IsHttpOrHttpsAndCrossOrigin(principalURI,
8878 aCurrentURI) &&
8879 !nsScriptSecurityManager::IsHttpOrHttpsAndCrossOrigin(aCurrentURI,
8880 aNewURI);
8881}
8882
8883nsresult nsDocShell::HandleSameDocumentNavigation(
8884 nsDocShellLoadState* aLoadState, SameDocumentNavigationState& aState,
8885 bool& aSameDocument) {
8886 aSameDocument = true;
8887#ifdef DEBUG1
8888 SameDocumentNavigationState state;
8889 MOZ_ASSERT(IsSameDocumentNavigation(aLoadState, state))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(IsSameDocumentNavigation(aLoadState, state))>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(IsSameDocumentNavigation(aLoadState, state)))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("IsSameDocumentNavigation(aLoadState, state)"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 8889); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "IsSameDocumentNavigation(aLoadState, state)"
")"); do { MOZ_CrashSequence(__null, 8889); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8890#endif
8891
8892 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)
8893 ("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)
8894 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)
8895 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)
;
8896
8897 RefPtr<Document> doc = GetDocument();
8898 NS_ENSURE_TRUE(doc, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(doc)), 0))) { NS_DebugBreak(NS_DEBUG_WARNING
, "NS_ENSURE_TRUE(" "doc" ") failed", nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 8898); return NS_ERROR_FAILURE; } } while (false)
;
8899
8900 nsCOMPtr<nsIURI> currentURI = mCurrentURI;
8901
8902 // We need to upgrade the new URI from http: to https:
8903 nsCOMPtr<nsIURI> newURI = aLoadState->URI();
8904 if (aState.mSecureUpgradeURI) {
8905 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(); })
;
8906 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)
8907 ("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)
;
8908 }
8909
8910 // check if documentPrincipal, mCurrentURI, and aLoadState->URI() are same
8911 // origin skip handling otherwise
8912 if (!IsSamePrincipalForDocumentURI(doc->NodePrincipal(), mCurrentURI,
8913 newURI)) {
8914 MOZ_LOG(gSHLog, LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = gSHLog; if
((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "nsDocShell[%p]: possible violation of the same origin policy "
"during same document navigation", this); } } while (0)
8915 ("nsDocShell[%p]: possible violation of the same origin policy "do { const ::mozilla::LogModule* moz_real_module = gSHLog; if
((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "nsDocShell[%p]: possible violation of the same origin policy "
"during same document navigation", this); } } while (0)
8916 "during same document navigation",do { const ::mozilla::LogModule* moz_real_module = gSHLog; if
((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "nsDocShell[%p]: possible violation of the same origin policy "
"during same document navigation", this); } } while (0)
8917 this))do { const ::mozilla::LogModule* moz_real_module = gSHLog; if
((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "nsDocShell[%p]: possible violation of the same origin policy "
"during same document navigation", this); } } while (0)
;
8918 return NS_OK;
8919 }
8920
8921 if (nsCOMPtr<nsPIDOMWindowInner> window = doc->GetInnerWindow()) {
8922 // https://html.spec.whatwg.org/#navigate-fragid
8923 // Step 1
8924 if (RefPtr<Navigation> navigation = window->Navigation()) {
8925 // Step 2
8926 RefPtr<nsIStructuredCloneContainer> destinationNavigationAPIState =
8927 mActiveEntry ? mActiveEntry->GetNavigationState() : nullptr;
8928 // Step 3
8929 if (aLoadState->GetNavigationAPIState()) {
8930 destinationNavigationAPIState = aLoadState->GetNavigationAPIState();
8931 }
8932
8933 AutoJSAPI jsapi;
8934 if (jsapi.Init(window)) {
8935 RefPtr<Element> sourceElement = aLoadState->GetSourceElement();
8936 // Step 4
8937 bool shouldContinue = navigation->FirePushReplaceReloadNavigateEvent(
8938 jsapi.cx(), aLoadState->GetNavigationType(), newURI,
8939 /* aIsSameDocument */ true, /* aIsSync */ true,
8940 Some(aLoadState->UserNavigationInvolvement()), sourceElement,
8941 /* aFormDataEntryList */ nullptr,
8942 /* aNavigationAPIState */ destinationNavigationAPIState,
8943 /* aClassicHistoryAPIState */ nullptr);
8944
8945 // Step 5
8946 if (!shouldContinue) {
8947 return NS_OK;
8948 }
8949 }
8950 }
8951 }
8952
8953 doc->DoNotifyPossibleTitleChange();
8954
8955 // Store the pending uninvoked directives if it is a same document
8956 // navigation. We need to set it here, in case the navigation happens before
8957 // the document has actually finished loading.
8958 doc->FragmentDirective()->SetTextDirectives(
8959 std::move(aState.mTextDirectives));
8960
8961#ifdef DEBUG1
8962 if (aState.mSameExceptHashes) {
8963 bool sameExceptHashes = false;
8964 currentURI->EqualsExceptRef(newURI, &sameExceptHashes);
8965 MOZ_ASSERT(sameExceptHashes)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(sameExceptHashes)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(sameExceptHashes))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("sameExceptHashes"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 8965); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "sameExceptHashes" ")"); do { MOZ_CrashSequence
(__null, 8965); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
8966 }
8967#endif
8968 const nsCOMPtr<nsILoadInfo> loadInfo =
8969 doc->GetChannel() ? doc->GetChannel()->LoadInfo() : nullptr;
8970 if (loadInfo) {
8971 loadInfo->SetIsSameDocumentNavigation(true);
8972 }
8973 // Save the position of the scrollers.
8974 nsPoint scrollPos = GetCurScrollPos();
8975
8976 // Reset mLoadType to its original value once we exit this block, because this
8977 // same document navigation might have started after a normal, network load,
8978 // and we don't want to clobber its load type. See bug 737307.
8979 Maybe<AutoRestore<uint32_t>> loadTypeResetter;
8980 if (StaticPrefs::
8981 docshell_shistory_sameDocumentNavigationOverridesLoadType() &&
8982 !doc->NodePrincipal()->IsURIInPrefList(
8983 "docshell.shistory.sameDocumentNavigationOverridesLoadType."
8984 "forceDisable")) {
8985 loadTypeResetter.emplace(mLoadType);
8986 }
8987 if (JustStartedNetworkLoad() && !loadTypeResetter.isSome()) {
8988 loadTypeResetter.emplace(mLoadType);
8989 }
8990
8991 // If a non-same-document-navigation (i.e., a network load) is pending, make
8992 // this a replacement load, so that we don't add a SHEntry here and the
8993 // network load goes into the SHEntry it expects to.
8994 if (JustStartedNetworkLoad() && (aLoadState->LoadType() & LOAD_CMD_NORMAL)) {
8995 mLoadType = LOAD_NORMAL_REPLACE;
8996 } else {
8997 mLoadType = aLoadState->LoadType();
8998 }
8999
9000 mURIResultedInDocument = true;
9001
9002 nsCOMPtr<nsISHEntry> oldLSHE = mLSHE;
9003
9004 // we need to assign aLoadState->SHEntry() to mLSHE right here, so that on
9005 // History loads, SetCurrentURI() called from OnNewURI() will send proper
9006 // onLocationChange() notifications to the browser to update back/forward
9007 // buttons.
9008 SetHistoryEntryAndUpdateBC(Some<nsISHEntry*>(aLoadState->SHEntry()),
9009 Nothing());
9010 UniquePtr<mozilla::dom::LoadingSessionHistoryInfo> oldLoadingEntry;
9011 mLoadingEntry.swap(oldLoadingEntry);
9012 if (aLoadState->GetLoadingSessionHistoryInfo()) {
9013 mLoadingEntry = MakeUnique<LoadingSessionHistoryInfo>(
9014 *aLoadState->GetLoadingSessionHistoryInfo());
9015 mNeedToReportActiveAfterLoadingBecomesActive = false;
9016 }
9017
9018 // Set the doc's URI according to the new history entry's URI.
9019 doc->SetDocumentURI(newURI);
9020
9021 /* This is a anchor traversal within the same page.
9022 * call OnNewURI() so that, this traversal will be
9023 * recorded in session and global history.
9024 */
9025 nsCOMPtr<nsIPrincipal> newURITriggeringPrincipal, newURIPrincipalToInherit,
9026 newURIPartitionedPrincipalToInherit;
9027 nsCOMPtr<nsIContentSecurityPolicy> newCsp;
9028 if (mozilla::SessionHistoryInParent() ? !!mActiveEntry : !!mOSHE) {
9029 if (mozilla::SessionHistoryInParent()) {
9030 newURITriggeringPrincipal = mActiveEntry->GetTriggeringPrincipal();
9031 newURIPrincipalToInherit = mActiveEntry->GetPrincipalToInherit();
9032 newURIPartitionedPrincipalToInherit =
9033 mActiveEntry->GetPartitionedPrincipalToInherit();
9034 newCsp = mActiveEntry->GetCsp();
9035 } else {
9036 newURITriggeringPrincipal = mOSHE->GetTriggeringPrincipal();
9037 newURIPrincipalToInherit = mOSHE->GetPrincipalToInherit();
9038 newURIPartitionedPrincipalToInherit =
9039 mOSHE->GetPartitionedPrincipalToInherit();
9040 newCsp = mOSHE->GetCsp();
9041 }
9042 } else {
9043 newURITriggeringPrincipal = aLoadState->TriggeringPrincipal();
9044 newURIPrincipalToInherit = doc->NodePrincipal();
9045 newURIPartitionedPrincipalToInherit = doc->PartitionedPrincipal();
9046 newCsp = doc->GetCsp();
9047 }
9048
9049 uint32_t locationChangeFlags = GetSameDocumentNavigationFlags(newURI);
9050
9051 // Pass true for aCloneSHChildren, since we're not
9052 // changing documents here, so all of our subframes are
9053 // still relevant to the new session history entry.
9054 //
9055 // It also makes OnNewURI(...) set LOCATION_CHANGE_SAME_DOCUMENT
9056 // flag on firing onLocationChange(...).
9057 // Anyway, aCloneSHChildren param is simply reflecting
9058 // doSameDocumentNavigation in this scope.
9059 //
9060 // Note: we'll actually fire onLocationChange later, in order to preserve
9061 // ordering of HistoryCommit() in the parent vs onLocationChange (bug
9062 // 1668126)
9063 bool locationChangeNeeded = OnNewURI(
9064 newURI, nullptr, newURITriggeringPrincipal, newURIPrincipalToInherit,
9065 newURIPartitionedPrincipalToInherit, newCsp, true, true);
9066
9067 nsCOMPtr<nsIInputStream> postData;
9068 nsCOMPtr<nsIReferrerInfo> referrerInfo;
9069 uint32_t cacheKey = 0;
9070
9071 bool scrollRestorationIsManual = false;
9072 if (!mozilla::SessionHistoryInParent()) {
9073 if (mOSHE) {
9074 /* save current position of scroller(s) (bug 59774) */
9075 mOSHE->SetScrollPosition(scrollPos.x, scrollPos.y);
9076 scrollRestorationIsManual = mOSHE->GetScrollRestorationIsManual();
9077 // Get the postdata, page ident and referrer info from the current page,
9078 // if the new load is being done via normal means. Note that "normal
9079 // means" can be checked for just by checking for LOAD_CMD_NORMAL, given
9080 // the loadType and allowScroll check above -- it filters out some
9081 // LOAD_CMD_NORMAL cases that we wouldn't want here.
9082 if (aLoadState->LoadType() & LOAD_CMD_NORMAL) {
9083 postData = mOSHE->GetPostData();
9084 cacheKey = mOSHE->GetCacheKey();
9085 referrerInfo = mOSHE->GetReferrerInfo();
9086 }
9087
9088 // Link our new SHEntry to the old SHEntry's back/forward
9089 // cache data, since the two SHEntries correspond to the
9090 // same document.
9091 if (mLSHE) {
9092 if (!aLoadState->LoadIsFromSessionHistory()) {
9093 // If we're not doing a history load, scroll restoration
9094 // should be inherited from the previous session history entry.
9095 SetScrollRestorationIsManualOnHistoryEntry(mLSHE,
9096 scrollRestorationIsManual);
9097 }
9098 mLSHE->AdoptBFCacheEntry(mOSHE);
9099 }
9100 }
9101 } else {
9102 if (mActiveEntry) {
9103 mActiveEntry->SetScrollPosition(scrollPos.x, scrollPos.y);
9104 if (mBrowsingContext) {
9105 CollectWireframe();
9106 if (XRE_IsParentProcess()) {
9107 SessionHistoryEntry* entry =
9108 mBrowsingContext->Canonical()->GetActiveSessionHistoryEntry();
9109 if (entry) {
9110 entry->SetScrollPosition(scrollPos.x, scrollPos.y);
9111 }
9112 } else {
9113 mozilla::Unused << ContentChild::GetSingleton()
9114 ->SendSessionHistoryEntryScrollPosition(
9115 mBrowsingContext, scrollPos.x,
9116 scrollPos.y);
9117 }
9118 }
9119 }
9120 if (mLoadingEntry) {
9121 if (!mLoadingEntry->mLoadIsFromSessionHistory) {
9122 // If we're not doing a history load, scroll restoration
9123 // should be inherited from the previous session history entry.
9124 // XXX This needs most probably tweaks once fragment navigation is
9125 // fixed to work with session-history-in-parent.
9126 SetScrollRestorationIsManualOnHistoryEntry(nullptr,
9127 scrollRestorationIsManual);
9128 }
9129 }
9130 }
9131
9132 // If we're doing a history load, use its scroll restoration state.
9133 if (aLoadState->LoadIsFromSessionHistory()) {
9134 if (mozilla::SessionHistoryInParent()) {
9135 scrollRestorationIsManual = aLoadState->GetLoadingSessionHistoryInfo()
9136 ->mInfo.GetScrollRestorationIsManual();
9137 } else {
9138 scrollRestorationIsManual =
9139 aLoadState->SHEntry()->GetScrollRestorationIsManual();
9140 }
9141 }
9142
9143 /* Assign mLSHE to mOSHE. This will either be a new entry created
9144 * by OnNewURI() for normal loads or aLoadState->SHEntry() for history
9145 * loads.
9146 */
9147 if (!mozilla::SessionHistoryInParent()) {
9148 if (mLSHE) {
9149 SetHistoryEntryAndUpdateBC(Nothing(), Some<nsISHEntry*>(mLSHE));
9150 // Save the postData obtained from the previous page
9151 // in to the session history entry created for the
9152 // anchor page, so that any history load of the anchor
9153 // page will restore the appropriate postData.
9154 if (postData) {
9155 mOSHE->SetPostData(postData);
9156 }
9157
9158 // Make sure we won't just repost without hitting the
9159 // cache first
9160 if (cacheKey != 0) {
9161 mOSHE->SetCacheKey(cacheKey);
9162 }
9163
9164 // As the document has not changed, the referrer info hasn't changed too,
9165 // so we can just copy it over.
9166 if (referrerInfo) {
9167 mOSHE->SetReferrerInfo(referrerInfo);
9168 }
9169 }
9170
9171 /* Set the title for the SH entry for this target url so that
9172 * SH menus in go/back/forward buttons won't be empty for this.
9173 * Note, this happens on mOSHE (and mActiveEntry in the future) because of
9174 * the code above.
9175 * Note, when session history lives in the parent process, this does not
9176 * update the title there.
9177 */
9178 SetTitleOnHistoryEntry(false);
9179 } else {
9180 if (aLoadState->LoadIsFromSessionHistory()) {
9181 MOZ_LOG(do { const ::mozilla::LogModule* moz_real_module = gSHLog; if
((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "Moving the loading entry to the active entry on nsDocShell %p to "
"%s", this, mLoadingEntry->mInfo.GetURI()->GetSpecOrDefault
().get()); } } while (0)
9182 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)
9183 ("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)
9184 "%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)
9185 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)
;
9186
9187 nsCOMPtr<nsILayoutHistoryState> currentLayoutHistoryState;
9188 if (mActiveEntry) {
9189 currentLayoutHistoryState = mActiveEntry->GetLayoutHistoryState();
9190 }
9191
9192 UniquePtr<SessionHistoryInfo> previousActiveEntry(mActiveEntry.release());
9193 mActiveEntry = MakeUnique<SessionHistoryInfo>(mLoadingEntry->mInfo);
9194 if (currentLayoutHistoryState) {
9195 // Restore the existing nsILayoutHistoryState object, since it is
9196 // possibly being used by the layout. When doing a new load, the
9197 // shared state is copied from the existing active entry, so this
9198 // special case is needed only with the history loads.
9199 mActiveEntry->SetLayoutHistoryState(currentLayoutHistoryState);
9200 }
9201
9202 if (cacheKey != 0) {
9203 mActiveEntry->SetCacheKey(cacheKey);
9204 }
9205
9206 // We're passing in mCurrentURI, which could be null. SessionHistoryCommit
9207 // does require a non-null uri if this is for a refresh load of the same
9208 // URI, but in that case mCurrentURI won't be null here.
9209 mBrowsingContext->SessionHistoryCommit(
9210 *mLoadingEntry, mLoadType, mCurrentURI, previousActiveEntry.get(),
9211 true,
9212 /* No expiration update on the same document loads*/
9213 false, cacheKey);
9214 // FIXME Need to set postdata.
9215
9216 // Set the title for the SH entry for this target url so that
9217 // SH menus in go/back/forward buttons won't be empty for this.
9218 // Note, when session history lives in the parent process, this does not
9219 // update the title there.
9220 SetTitleOnHistoryEntry(false);
9221 } else {
9222 Maybe<bool> scrollRestorationIsManual;
9223 if (mActiveEntry) {
9224 scrollRestorationIsManual.emplace(
9225 mActiveEntry->GetScrollRestorationIsManual());
9226
9227 // Get the postdata, page ident and referrer info from the current page,
9228 // if the new load is being done via normal means. Note that "normal
9229 // means" can be checked for just by checking for LOAD_CMD_NORMAL, given
9230 // the loadType and allowScroll check above -- it filters out some
9231 // LOAD_CMD_NORMAL cases that we wouldn't want here.
9232 if (aLoadState->LoadType() & LOAD_CMD_NORMAL) {
9233 postData = mActiveEntry->GetPostData();
9234 cacheKey = mActiveEntry->GetCacheKey();
9235 referrerInfo = mActiveEntry->GetReferrerInfo();
9236 }
9237 }
9238
9239 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)
9240 ("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)
9241 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)
;
9242 UniquePtr<SessionHistoryInfo> previousActiveEntry(mActiveEntry.release());
9243 if (previousActiveEntry) {
9244 mActiveEntry =
9245 MakeUnique<SessionHistoryInfo>(*previousActiveEntry, newURI);
9246 } else {
9247 mActiveEntry = MakeUnique<SessionHistoryInfo>(
9248 newURI, newURITriggeringPrincipal, newURIPrincipalToInherit,
9249 newURIPartitionedPrincipalToInherit, newCsp, mContentTypeHint);
9250 }
9251
9252 // Save the postData obtained from the previous page in to the session
9253 // history entry created for the anchor page, so that any history load of
9254 // the anchor page will restore the appropriate postData.
9255 if (postData) {
9256 mActiveEntry->SetPostData(postData);
9257 }
9258
9259 // Make sure we won't just repost without hitting the
9260 // cache first
9261 if (cacheKey != 0) {
9262 mActiveEntry->SetCacheKey(cacheKey);
9263 }
9264
9265 // As the document has not changed, the referrer info hasn't changed too,
9266 // so we can just copy it over.
9267 if (referrerInfo) {
9268 mActiveEntry->SetReferrerInfo(referrerInfo);
9269 }
9270
9271 // Set the title for the SH entry for this target url so that
9272 // SH menus in go/back/forward buttons won't be empty for this.
9273 mActiveEntry->SetTitle(mTitle);
9274
9275 if (scrollRestorationIsManual.isSome()) {
9276 mActiveEntry->SetScrollRestorationIsManual(
9277 scrollRestorationIsManual.value());
9278 }
9279
9280 if (LOAD_TYPE_HAS_FLAGS(mLoadType, LOAD_FLAGS_REPLACE_HISTORY)((mLoadType) & ((LOAD_FLAGS_REPLACE_HISTORY) << 16)
)
) {
9281 mBrowsingContext->ReplaceActiveSessionHistoryEntry(mActiveEntry.get());
9282 } else {
9283 mBrowsingContext->IncrementHistoryEntryCountForBrowsingContext();
9284 // FIXME We should probably just compute mChildOffset in the parent
9285 // instead of passing it over IPC here.
9286 mBrowsingContext->SetActiveSessionHistoryEntry(
9287 Some(scrollPos), mActiveEntry.get(), previousActiveEntry.get(),
9288 mLoadType, cacheKey);
9289 // FIXME Do we need to update mPreviousEntryIndex and mLoadedEntryIndex?
9290 }
9291 }
9292 }
9293
9294 if (locationChangeNeeded) {
9295 FireOnLocationChange(this, nullptr, newURI, locationChangeFlags);
9296 }
9297
9298 /* Restore the original LSHE if we were loading something
9299 * while same document navigation was initiated.
9300 */
9301 SetHistoryEntryAndUpdateBC(Some<nsISHEntry*>(oldLSHE), Nothing());
9302 mLoadingEntry.swap(oldLoadingEntry);
9303
9304 /* Set the title for the Global History entry for this anchor url.
9305 */
9306 UpdateGlobalHistoryTitle(newURI);
9307
9308 SetDocCurrentStateObj(mOSHE, mActiveEntry.get());
9309
9310 // Inform the favicon service that the favicon for oldURI also
9311 // applies to newURI.
9312 CopyFavicon(currentURI, newURI, UsePrivateBrowsing());
9313
9314 RefPtr<nsGlobalWindowOuter> scriptGlobal = mScriptGlobal;
9315 nsCOMPtr<nsPIDOMWindowInner> win =
9316 scriptGlobal ? scriptGlobal->GetCurrentInnerWindow() : nullptr;
9317
9318 // The check for uninvoked directives must come before ScrollToAnchor() is
9319 // called.
9320 const bool hasTextDirectives =
9321 doc->FragmentDirective()->HasUninvokedDirectives();
9322
9323 // ScrollToAnchor doesn't necessarily cause us to scroll the window;
9324 // the function decides whether a scroll is appropriate based on the
9325 // arguments it receives. But even if we don't end up scrolling,
9326 // ScrollToAnchor performs other important tasks, such as informing
9327 // the presShell that we have a new hash. See bug 680257.
9328 nsresult rv = ScrollToAnchor(aState.mCurrentURIHasRef, aState.mNewURIHasRef,
9329 aState.mNewHash, aLoadState->LoadType());
9330 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 9330); return rv; } } while (false)
;
9331
9332 /* restore previous position of scroller(s), if we're moving
9333 * back in history (bug 59774)
9334 */
9335 nscoord bx = 0;
9336 nscoord by = 0;
9337 bool needsScrollPosUpdate = false;
9338 if ((mozilla::SessionHistoryInParent() ? !!mActiveEntry : !!mOSHE) &&
9339 (aLoadState->LoadType() == LOAD_HISTORY ||
9340 aLoadState->LoadType() == LOAD_RELOAD_NORMAL) &&
9341 !scrollRestorationIsManual) {
9342 needsScrollPosUpdate = true;
9343 if (mozilla::SessionHistoryInParent()) {
9344 mActiveEntry->GetScrollPosition(&bx, &by);
9345 } else {
9346 mOSHE->GetScrollPosition(&bx, &by);
9347 }
9348 }
9349
9350 // Dispatch the popstate and hashchange events, as appropriate.
9351 //
9352 // The event dispatch below can cause us to re-enter script and
9353 // destroy the docshell, nulling out mScriptGlobal. Hold a stack
9354 // reference to avoid null derefs. See bug 914521.
9355 if (win) {
9356 if (RefPtr navigation = win->Navigation()) {
9357 MOZ_LOG(gNavigationLog, LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = gNavigationLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "nsDocShell %p triggering a navigation event from "
"HandleSameDocumentNavigation", this); } } while (0)
9358 ("nsDocShell %p triggering a navigation event from "do { const ::mozilla::LogModule* moz_real_module = gNavigationLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "nsDocShell %p triggering a navigation event from "
"HandleSameDocumentNavigation", this); } } while (0)
9359 "HandleSameDocumentNavigation",do { const ::mozilla::LogModule* moz_real_module = gNavigationLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "nsDocShell %p triggering a navigation event from "
"HandleSameDocumentNavigation", this); } } while (0)
9360 this))do { const ::mozilla::LogModule* moz_real_module = gNavigationLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "nsDocShell %p triggering a navigation event from "
"HandleSameDocumentNavigation", this); } } while (0)
;
9361 // Corresponds to step 6.4.2 from the Updating the document algorithm:
9362 // https://html.spec.whatwg.org/multipage/browsing-the-web.html#updating-the-document
9363 navigation->UpdateEntriesForSameDocumentNavigation(
9364 mActiveEntry.get(),
9365 LOAD_TYPE_HAS_FLAGS(mLoadType, LOAD_FLAGS_REPLACE_HISTORY)((mLoadType) & ((LOAD_FLAGS_REPLACE_HISTORY) << 16)
)
9366 ? NavigationType::Replace
9367 : aLoadState->LoadIsFromSessionHistory() ? NavigationType::Traverse
9368 : NavigationType::Push);
9369 }
9370
9371 // Fire a hashchange event URIs differ, and only in their hashes.
9372 // If the fragment contains a directive, compare hasRef.
9373 bool doHashchange = aState.mSameExceptHashes &&
9374 (!aState.mCurrentHash.Equals(aState.mNewHash) ||
9375 (hasTextDirectives &&
9376 aState.mCurrentURIHasRef != aState.mNewURIHasRef));
9377
9378 if (aState.mHistoryNavBetweenSameDoc || doHashchange) {
9379 win->DispatchSyncPopState();
9380 }
9381
9382 if (needsScrollPosUpdate && win->HasActiveDocument()) {
9383 SetCurScrollPosEx(bx, by);
9384 }
9385
9386 if (doHashchange) {
9387 // Note that currentURI hasn't changed because it's on the
9388 // stack, so we can just use it directly as the old URI.
9389 win->DispatchAsyncHashchange(currentURI, newURI);
9390 }
9391 }
9392
9393 return NS_OK;
9394}
9395
9396static bool NavigationShouldTakeFocus(nsDocShell* aDocShell,
9397 nsDocShellLoadState* aLoadState) {
9398 if (!aLoadState->AllowFocusMove()) {
9399 return false;
9400 }
9401 if (!aLoadState->HasValidUserGestureActivation()) {
9402 return false;
9403 }
9404 const auto& sourceBC = aLoadState->SourceBrowsingContext();
9405 if (!sourceBC || !sourceBC->IsActive()) {
9406 // If the navigation didn't come from a foreground tab, then we don't steal
9407 // focus.
9408 return false;
9409 }
9410 auto* bc = aDocShell->GetBrowsingContext();
9411 if (sourceBC.get() == bc) {
9412 // If it comes from the same tab / frame, don't steal focus either.
9413 return false;
9414 }
9415 auto* fm = nsFocusManager::GetFocusManager();
9416 if (fm && bc->IsActive() && fm->IsInActiveWindow(bc)) {
9417 // If we're already on the foreground tab of the foreground window, then we
9418 // don't need to do this. This helps to e.g. not steal focus from the
9419 // browser chrome unnecessarily.
9420 return false;
9421 }
9422 if (auto* doc = aDocShell->GetExtantDocument()) {
9423 if (doc->IsInitialDocument()) {
9424 // If we're the initial load for the browsing context, the browser
9425 // chrome determines what to focus. This is important because the
9426 // browser chrome may want to e.g focus the url-bar
9427 return false;
9428 }
9429 }
9430 // Take loadDivertedInBackground into account so the behavior would be the
9431 // same as how the tab first opened.
9432 return !Preferences::GetBool("browser.tabs.loadDivertedInBackground", false);
9433}
9434
9435uint32_t nsDocShell::GetLoadTypeForFormSubmission(
9436 BrowsingContext* aTargetBC, nsDocShellLoadState* aLoadState) {
9437 MOZ_ASSERT(aLoadState->IsFormSubmission())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aLoadState->IsFormSubmission())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aLoadState->IsFormSubmission
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("aLoadState->IsFormSubmission()", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 9437); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->IsFormSubmission()"
")"); do { MOZ_CrashSequence(__null, 9437); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9438
9439 // https://html.spec.whatwg.org/#form-submission-algorithm
9440 // 22. Let historyHandling be "push".
9441 // 23. If form document equals targetNavigable's active document, and
9442 // form document has not yet completely loaded, then set
9443 // historyHandling to "replace".
9444 return GetBrowsingContext() == aTargetBC && !mEODForCurrentDocument
9445 ? LOAD_NORMAL_REPLACE
9446 : LOAD_LINK;
9447}
9448
9449// InternalLoad performs several of the steps from
9450// https://html.spec.whatwg.org/#navigate.
9451nsresult nsDocShell::InternalLoad(nsDocShellLoadState* aLoadState,
9452 Maybe<uint32_t> aCacheKey) {
9453 MOZ_ASSERT(aLoadState, "need a load state!")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aLoadState)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aLoadState))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("aLoadState" " (" "need a load state!"
")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 9453
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState" ") ("
"need a load state!" ")"); do { MOZ_CrashSequence(__null, 9453
); __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
;
9454 MOZ_ASSERT(aLoadState->TriggeringPrincipal(),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aLoadState->TriggeringPrincipal())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aLoadState->TriggeringPrincipal
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("aLoadState->TriggeringPrincipal()" " (" "need a valid TriggeringPrincipal"
")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 9455
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->TriggeringPrincipal()"
") (" "need a valid TriggeringPrincipal" ")"); do { MOZ_CrashSequence
(__null, 9455); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
9455 "need a valid TriggeringPrincipal")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aLoadState->TriggeringPrincipal())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aLoadState->TriggeringPrincipal
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("aLoadState->TriggeringPrincipal()" " (" "need a valid TriggeringPrincipal"
")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 9455
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->TriggeringPrincipal()"
") (" "need a valid TriggeringPrincipal" ")"); do { MOZ_CrashSequence
(__null, 9455); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
9456
9457 if (!aLoadState->TriggeringPrincipal()) {
9458 MOZ_ASSERT(false, "InternalLoad needs a valid triggeringPrincipal")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "InternalLoad needs a valid triggeringPrincipal"
")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 9458
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") (" "InternalLoad needs a valid triggeringPrincipal"
")"); do { MOZ_CrashSequence(__null, 9458); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9459 return NS_ERROR_FAILURE;
9460 }
9461 if (NS_WARN_IF(mBrowsingContext->GetPendingInitialization())NS_warn_if_impl(mBrowsingContext->GetPendingInitialization
(), "mBrowsingContext->GetPendingInitialization()", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 9461)
) {
9462 return NS_ERROR_NOT_AVAILABLE;
9463 }
9464
9465 const bool shouldTakeFocus = NavigationShouldTakeFocus(this, aLoadState);
9466
9467 mOriginalUriString.Truncate();
9468
9469 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)
9470 ("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)
9471 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)
;
9472
9473 NS_ENSURE_TRUE(IsValidLoadType(aLoadState->LoadType()), NS_ERROR_INVALID_ARG)do { if ((__builtin_expect(!!(!(IsValidLoadType(aLoadState->
LoadType()))), 0))) { NS_DebugBreak(NS_DEBUG_WARNING, "NS_ENSURE_TRUE("
"IsValidLoadType(aLoadState->LoadType())" ") failed", nullptr
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 9473); return
NS_ERROR_INVALID_ARG; } } while (false)
;
9474
9475 // Cancel loads coming from Docshells that are being destroyed.
9476 if (mIsBeingDestroyed) {
9477 return NS_ERROR_NOT_AVAILABLE;
9478 }
9479
9480 nsresult rv = EnsureScriptEnvironment();
9481 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
9482 return rv;
9483 }
9484
9485 // If we have a target to move to, do that now.
9486 if (!aLoadState->Target().IsEmpty()) {
9487 return PerformRetargeting(aLoadState);
9488 }
9489
9490 // This is the non-retargeting load path, we've already set the right loadtype
9491 // for form submissions in nsDocShell::OnLinkClickSync.
9492 if (aLoadState->TargetBrowsingContext().IsNull()) {
9493 aLoadState->SetTargetBrowsingContext(GetBrowsingContext());
9494 }
9495
9496 MOZ_DIAGNOSTIC_ASSERT(do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aLoadState->TargetBrowsingContext() == GetBrowsingContext
())>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(aLoadState->TargetBrowsingContext() == GetBrowsingContext
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("aLoadState->TargetBrowsingContext() == GetBrowsingContext()"
" (" "Load must be targeting this BrowsingContext" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 9498); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "aLoadState->TargetBrowsingContext() == GetBrowsingContext()"
") (" "Load must be targeting this BrowsingContext" ")"); do
{ MOZ_CrashSequence(__null, 9498); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
9497 aLoadState->TargetBrowsingContext() == GetBrowsingContext(),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aLoadState->TargetBrowsingContext() == GetBrowsingContext
())>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(aLoadState->TargetBrowsingContext() == GetBrowsingContext
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("aLoadState->TargetBrowsingContext() == GetBrowsingContext()"
" (" "Load must be targeting this BrowsingContext" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 9498); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "aLoadState->TargetBrowsingContext() == GetBrowsingContext()"
") (" "Load must be targeting this BrowsingContext" ")"); do
{ MOZ_CrashSequence(__null, 9498); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
9498 "Load must be targeting this BrowsingContext")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aLoadState->TargetBrowsingContext() == GetBrowsingContext
())>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(aLoadState->TargetBrowsingContext() == GetBrowsingContext
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("aLoadState->TargetBrowsingContext() == GetBrowsingContext()"
" (" "Load must be targeting this BrowsingContext" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 9498); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "aLoadState->TargetBrowsingContext() == GetBrowsingContext()"
") (" "Load must be targeting this BrowsingContext" ")"); do
{ MOZ_CrashSequence(__null, 9498); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
9499
9500 MOZ_TRY(CheckDisallowedJavascriptLoad(aLoadState))__extension__({ auto mozTryVarTempResult = ::mozilla::ToResult
(CheckDisallowedJavascriptLoad(aLoadState)); if ((__builtin_expect
(!!(mozTryVarTempResult.isErr()), 0))) { return mozTryVarTempResult
.propagateErr(); } mozTryVarTempResult.unwrap(); })
;
9501
9502 // If we don't have a target, we're loading into ourselves, and our load
9503 // delegate may want to intercept that load.
9504 SameDocumentNavigationState sameDocumentNavigationState;
9505 bool sameDocument =
9506 IsSameDocumentNavigation(aLoadState, sameDocumentNavigationState) &&
9507 !aLoadState->GetPendingRedirectedChannel();
9508
9509 // Note: We do this check both here and in BrowsingContext::
9510 // LoadURI/InternalLoad, since document-specific sandbox flags are only
9511 // available in the process triggering the load, and we don't want the target
9512 // process to have to trust the triggering process to do the appropriate
9513 // checks for the BrowsingContext's sandbox flags.
9514 MOZ_TRY(mBrowsingContext->CheckSandboxFlags(aLoadState))__extension__({ auto mozTryVarTempResult = ::mozilla::ToResult
(mBrowsingContext->CheckSandboxFlags(aLoadState)); if ((__builtin_expect
(!!(mozTryVarTempResult.isErr()), 0))) { return mozTryVarTempResult
.propagateErr(); } mozTryVarTempResult.unwrap(); })
;
9515
9516 NS_ENSURE_STATE(!HasUnloadedParent())do { if ((__builtin_expect(!!(!(!HasUnloadedParent())), 0))) {
NS_DebugBreak(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "!HasUnloadedParent()"
") failed", nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 9516); return NS_ERROR_UNEXPECTED; } } while (false)
;
9517
9518 rv = CheckLoadingPermissions();
9519 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
9520 return rv;
9521 }
9522
9523 if (mFiredUnloadEvent) {
9524 if (IsOKToLoadURI(aLoadState->URI())) {
9525 MOZ_ASSERT(aLoadState->Target().IsEmpty(),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aLoadState->Target().IsEmpty())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aLoadState->Target().IsEmpty
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("aLoadState->Target().IsEmpty()" " (" "Shouldn't have a window target here!"
")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 9526
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->Target().IsEmpty()"
") (" "Shouldn't have a window target here!" ")"); do { MOZ_CrashSequence
(__null, 9526); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
9526 "Shouldn't have a window target here!")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aLoadState->Target().IsEmpty())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aLoadState->Target().IsEmpty
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("aLoadState->Target().IsEmpty()" " (" "Shouldn't have a window target here!"
")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 9526
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->Target().IsEmpty()"
") (" "Shouldn't have a window target here!" ")"); do { MOZ_CrashSequence
(__null, 9526); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
9527
9528 // If this is a replace load, make whatever load triggered
9529 // the unload event also a replace load, so we don't
9530 // create extra history entries.
9531 if (LOAD_TYPE_HAS_FLAGS(aLoadState->LoadType(),((aLoadState->LoadType()) & ((LOAD_FLAGS_REPLACE_HISTORY
) << 16))
9532 LOAD_FLAGS_REPLACE_HISTORY)((aLoadState->LoadType()) & ((LOAD_FLAGS_REPLACE_HISTORY
) << 16))
) {
9533 mLoadType = LOAD_NORMAL_REPLACE;
9534 }
9535
9536 // Do this asynchronously
9537 nsCOMPtr<nsIRunnable> ev = new InternalLoadEvent(this, aLoadState);
9538 return Dispatch(ev.forget());
9539 }
9540
9541 // Just ignore this load attempt
9542 return NS_OK;
9543 }
9544
9545 // If we are loading a URI that should inherit a security context (basically
9546 // javascript: at this point), and the caller has said that principal
9547 // inheritance is allowed, there are a few possible cases:
9548 //
9549 // 1) We are provided with the principal to inherit. In that case, we just use
9550 // it.
9551 //
9552 // 2) The load is coming from some other application. In this case we don't
9553 // want to inherit from whatever document we have loaded now, since the
9554 // load is unrelated to it.
9555 //
9556 // 3) It's a load from our application, but does not provide an explicit
9557 // principal to inherit. In that case, we want to inherit the principal of
9558 // our current document, or of our parent document (if any) if we don't
9559 // have a current document.
9560 {
9561 bool inherits;
9562
9563 if (!aLoadState->HasLoadFlags(LOAD_FLAGS_FROM_EXTERNAL) &&
9564 !aLoadState->PrincipalToInherit() &&
9565 (aLoadState->HasInternalLoadFlags(
9566 INTERNAL_LOAD_FLAGS_INHERIT_PRINCIPAL)) &&
9567 NS_SUCCEEDED(nsContentUtils::URIInheritsSecurityContext(((bool)(__builtin_expect(!!(!NS_FAILED_impl(nsContentUtils::URIInheritsSecurityContext
( aLoadState->URI(), &inherits))), 1)))
9568 aLoadState->URI(), &inherits))((bool)(__builtin_expect(!!(!NS_FAILED_impl(nsContentUtils::URIInheritsSecurityContext
( aLoadState->URI(), &inherits))), 1)))
&&
9569 inherits) {
9570 aLoadState->SetPrincipalToInherit(GetInheritedPrincipal(true));
9571 }
9572 // If principalToInherit is still null (e.g. if some of the conditions of
9573 // were not satisfied), then no inheritance of any sort will happen: the
9574 // load will just get a principal based on the URI being loaded.
9575 }
9576
9577 // If this docshell is owned by a frameloader, make sure to cancel
9578 // possible frameloader initialization before loading a new page.
9579 nsCOMPtr<nsIDocShellTreeItem> parent = GetInProcessParentDocshell();
9580 if (parent) {
9581 RefPtr<Document> doc = parent->GetDocument();
9582 if (doc) {
9583 doc->TryCancelFrameLoaderInitialization(this);
9584 }
9585 }
9586
9587 // Before going any further vet loads initiated by external programs.
9588 if (aLoadState->HasLoadFlags(LOAD_FLAGS_FROM_EXTERNAL)) {
9589 MOZ_DIAGNOSTIC_ASSERT(aLoadState->LoadType() == LOAD_NORMAL)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aLoadState->LoadType() == LOAD_NORMAL)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(aLoadState->LoadType() == LOAD_NORMAL))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("aLoadState->LoadType() == LOAD_NORMAL"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 9589); AnnotateMozCrashReason
("MOZ_DIAGNOSTIC_ASSERT" "(" "aLoadState->LoadType() == LOAD_NORMAL"
")"); do { MOZ_CrashSequence(__null, 9589); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9590
9591 // Disallow external chrome: loads targetted at content windows
9592 if (aLoadState->URI()->SchemeIs("chrome")) {
9593 NS_WARNING("blocked external chrome: url -- use '--chrome' option")NS_DebugBreak(NS_DEBUG_WARNING, "blocked external chrome: url -- use '--chrome' option"
, nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 9593)
;
9594 return NS_ERROR_FAILURE;
9595 }
9596
9597 // clear the decks to prevent context bleed-through (bug 298255)
9598 rv = CreateAboutBlankDocumentViewer(nullptr, nullptr, nullptr, nullptr,
9599 /* aIsInitialDocument */ false);
9600 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
9601 return NS_ERROR_FAILURE;
9602 }
9603 }
9604
9605 mAllowKeywordFixup = aLoadState->HasInternalLoadFlags(
9606 INTERNAL_LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP);
9607 mURIResultedInDocument = false; // reset the clock...
9608
9609 // If container is an iframe element and will lazy load element steps given
9610 // container returns true, then stop intersection-observing a lazy loading
9611 // element container and set container's lazy load resumption steps to null.
9612 if (IsSubframe()) {
9613 if (auto* iframe = HTMLIFrameElement::FromNodeOrNull(
9614 mBrowsingContext->GetEmbedderElement())) {
9615 // Per spec, reload doesn't cancel lazy loading iframes.
9616 if (!(aLoadState->LoadType() & LOAD_RELOAD_NORMAL)) {
9617 iframe->CancelLazyLoading(true /* aClearLazyLoadState */);
9618 }
9619 }
9620 }
9621
9622 // See if this is actually a load between two history entries for the same
9623 // document. If the process fails, or if we successfully navigate within the
9624 // same document, return.
9625 if (sameDocument) {
9626 nsresult rv = HandleSameDocumentNavigation(
9627 aLoadState, sameDocumentNavigationState, sameDocument);
9628 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 9628); return rv; } } while (false)
;
9629 if (shouldTakeFocus) {
9630 mBrowsingContext->Focus(CallerType::System, IgnoreErrors());
9631 }
9632 if (sameDocument) {
9633 return rv;
9634 }
9635 }
9636
9637 // mDocumentViewer->PermitUnload can destroy |this| docShell, which
9638 // causes the next call of CanSavePresentation to crash.
9639 // Hold onto |this| until we return, to prevent a crash from happening.
9640 // (bug#331040)
9641 nsCOMPtr<nsIDocShell> kungFuDeathGrip(this);
9642
9643 // Don't init timing for javascript:, since it generally doesn't
9644 // actually start a load or anything. If it does, we'll init
9645 // timing then, from OnStateChange.
9646
9647 // XXXbz mTiming should know what channel it's for, so we don't
9648 // need this hackery.
9649 const bool isJavaScript = aLoadState->URI()->SchemeIs("javascript");
9650 const bool isExternalProtocol =
9651 nsContentUtils::IsExternalProtocol(aLoadState->URI());
9652 const bool isDownload = !aLoadState->FileName().IsVoid();
9653 const bool toBeReset = !isJavaScript && MaybeInitTiming();
9654
9655 // FIXME(emilio): Should this be done by javascript: uris? What about external
9656 // protocols?
9657 if (mTiming && !isDownload) {
9658 mTiming->NotifyBeforeUnload();
9659 }
9660
9661 // The following steps are from https://html.spec.whatwg.org/#navigate
9662 // Step 19, and here we actually also perform step 2 from
9663 // #navigate-to-a-javascript:-url (step 20) where the ongoing navigation is
9664 // set to null.
9665 SetOngoingNavigation(isJavaScript ? Nothing()
9666 : Some(OngoingNavigation::NavigationID));
9667
9668 // Step 21
9669 if (RefPtr<Document> document = GetDocument();
9670 document &&
9671 aLoadState->UserNavigationInvolvement() !=
9672 UserNavigationInvolvement::BrowserUI &&
9673 !document->IsInitialDocument() &&
9674 !NS_IsAboutBlankAllowQueryAndFragment(document->GetDocumentURI()) &&
9675 NS_IsFetchScheme(aLoadState->URI()) &&
9676 document->NodePrincipal()->Subsumes(aLoadState->TriggeringPrincipal())) {
9677 if (nsCOMPtr<nsPIDOMWindowInner> window = document->GetInnerWindow()) {
9678 // Step 21.1
9679 if (RefPtr<Navigation> navigation = window->Navigation()) {
9680 AutoJSAPI jsapi;
9681 if (jsapi.Init(window)) {
9682 RefPtr<Element> sourceElement = aLoadState->GetSourceElement();
9683
9684 // Step 21.2
9685 RefPtr<FormData> formData = aLoadState->GetFormDataEntryList();
9686
9687 // Step 21.3
9688 RefPtr<nsIStructuredCloneContainer> navigationAPIStateForFiring =
9689 aLoadState->GetNavigationAPIState();
9690 if (!navigationAPIStateForFiring) {
9691 navigationAPIStateForFiring = nullptr;
9692 }
9693
9694 nsCOMPtr<nsIURI> destinationURL = aLoadState->URI();
9695 // Step 21.4
9696 bool shouldContinue = navigation->FirePushReplaceReloadNavigateEvent(
9697 jsapi.cx(), aLoadState->GetNavigationType(), destinationURL,
9698 /* aIsSameDocument */ false, /* aIsSync */ false,
9699 Some(aLoadState->UserNavigationInvolvement()), sourceElement,
9700 formData.forget(), navigationAPIStateForFiring,
9701 /* aClassicHistoryAPIState */ nullptr);
9702
9703 // Step 21.5
9704 if (!shouldContinue) {
9705 return NS_OK;
9706 }
9707 }
9708 }
9709 }
9710 }
9711
9712 // Check if the page doesn't want to be unloaded. The javascript:
9713 // protocol handler deals with this for javascript: URLs.
9714 // NOTE(emilio): As of this writing, other browsers fire beforeunload for
9715 // external protocols, so keep doing that even though they don't return data
9716 // and thus we won't really unload this...
9717 if (!isJavaScript && !isDownload &&
9718 !aLoadState->NotifiedBeforeUnloadListeners() && mDocumentViewer) {
9719 // Check if request is exempted from HTTPSOnlyMode and if https-first is
9720 // enabled, if so it means:
9721 // * https-first failed to upgrade request to https
9722 // * we already asked for permission to unload and the user accepted
9723 // otherwise we wouldn't be here.
9724 const bool isPrivateWin = GetOriginAttributes().IsPrivateBrowsing();
9725 const uint32_t loadType = aLoadState->LoadType();
9726
9727 // Check if request is a reload.
9728 const bool isHistoryOrReload =
9729 loadType == LOAD_RELOAD_NORMAL ||
9730 loadType == LOAD_RELOAD_BYPASS_CACHE ||
9731 loadType == LOAD_RELOAD_BYPASS_PROXY ||
9732 loadType == LOAD_RELOAD_BYPASS_PROXY_AND_CACHE ||
9733 loadType == LOAD_HISTORY;
9734
9735 // If it isn't a reload, the request already failed to be upgraded and
9736 // https-first is enabled then don't ask the user again for permission to
9737 // unload and just unload.
9738 bool okToUnload;
9739 if (!isHistoryOrReload && aLoadState->IsExemptFromHTTPSFirstMode() &&
9740 nsHTTPSOnlyUtils::GetUpgradeMode(isPrivateWin) ==
9741 nsHTTPSOnlyUtils::HTTPS_FIRST_MODE) {
9742 rv = mDocumentViewer->PermitUnload(
9743 nsIDocumentViewer::PermitUnloadAction::eDontPromptAndUnload,
9744 &okToUnload);
9745 } else {
9746 rv = mDocumentViewer->PermitUnload(&okToUnload);
9747 }
9748
9749 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && !okToUnload) {
9750 // The user chose not to unload the page, interrupt the
9751 // load.
9752 MaybeResetInitTiming(toBeReset);
9753 return NS_OK;
9754 }
9755 }
9756
9757 if (mTiming && !isDownload) {
9758 mTiming->NotifyUnloadAccepted(mCurrentURI);
9759 }
9760
9761 // In e10s, in the parent process, we refuse to load anything other than
9762 // "safe" resources that we ship or trust enough to give "special" URLs.
9763 // Similar check will be performed by the ParentProcessDocumentChannel if in
9764 // use.
9765 if (XRE_IsE10sParentProcess() &&
9766 !DocumentChannel::CanUseDocumentChannel(aLoadState->URI()) &&
9767 !CanLoadInParentProcess(aLoadState->URI())) {
9768 return NS_ERROR_FAILURE;
9769 }
9770
9771 // Whenever a top-level browsing context is navigated, the user agent MUST
9772 // lock the orientation of the document to the document's default
9773 // orientation. We don't explicitly check for a top-level browsing context
9774 // here because orientation is only set on top-level browsing contexts.
9775 if (mBrowsingContext->GetOrientationLock() != hal::ScreenOrientation::None) {
9776 MOZ_ASSERT(mBrowsingContext->IsTop())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mBrowsingContext->IsTop())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mBrowsingContext->IsTop()
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"mBrowsingContext->IsTop()", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 9776); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mBrowsingContext->IsTop()"
")"); do { MOZ_CrashSequence(__null, 9776); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9777 MOZ_ALWAYS_SUCCEEDS(do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(mBrowsingContext->SetOrientationLock(hal::ScreenOrientation
::None))), 1)))), 1))) { } else { do { do { } while (false); MOZ_ReportCrash
("" "NS_SUCCEEDED(mBrowsingContext->SetOrientationLock(hal::ScreenOrientation::None))"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 9778); AnnotateMozCrashReason
("MOZ_CRASH(" "NS_SUCCEEDED(mBrowsingContext->SetOrientationLock(hal::ScreenOrientation::None))"
")"); do { MOZ_CrashSequence(__null, 9778); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
9778 mBrowsingContext->SetOrientationLock(hal::ScreenOrientation::None))do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(mBrowsingContext->SetOrientationLock(hal::ScreenOrientation
::None))), 1)))), 1))) { } else { do { do { } while (false); MOZ_ReportCrash
("" "NS_SUCCEEDED(mBrowsingContext->SetOrientationLock(hal::ScreenOrientation::None))"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 9778); AnnotateMozCrashReason
("MOZ_CRASH(" "NS_SUCCEEDED(mBrowsingContext->SetOrientationLock(hal::ScreenOrientation::None))"
")"); do { MOZ_CrashSequence(__null, 9778); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
;
9779 if (mBrowsingContext->IsActive()) {
9780 ScreenOrientation::UpdateActiveOrientationLock(
9781 hal::ScreenOrientation::None);
9782 }
9783 }
9784
9785 // Check for saving the presentation here, before calling Stop().
9786 // This is necessary so that we can catch any pending requests.
9787 // Since the new request has not been created yet, we pass null for the
9788 // new request parameter.
9789 // Also pass nullptr for the document, since it doesn't affect the return
9790 // value for our purposes here.
9791 const bool savePresentation =
9792 CanSavePresentation(aLoadState->LoadType(), nullptr, nullptr,
9793 /* aReportBFCacheComboTelemetry */ true);
9794
9795 // nsDocShell::CanSavePresentation is for non-SHIP version only. Do a
9796 // separate check for SHIP so that we know if there are ongoing requests
9797 // before calling Stop() below.
9798 if (mozilla::SessionHistoryInParent()) {
9799 Document* document = GetDocument();
9800 uint32_t flags = 0;
9801 if (document && !document->CanSavePresentation(nullptr, flags, true)) {
9802 // This forces some flags into the WindowGlobalParent's mBFCacheStatus,
9803 // which we'll then use in CanonicalBrowsingContext::AllowedInBFCache,
9804 // and in particular we'll store BFCacheStatus::REQUEST if needed.
9805 // Also, we want to report all the flags to the parent process here (and
9806 // not just BFCacheStatus::NOT_ALLOWED), so that it can update the
9807 // telemetry data correctly.
9808 document->DisallowBFCaching(flags);
9809 }
9810 }
9811
9812 // Don't stop current network activity for javascript: URL's since they might
9813 // not result in any data, and thus nothing should be stopped in those cases.
9814 // In the case where they do result in data, the javascript: URL channel takes
9815 // care of stopping current network activity. Similarly, downloads don't
9816 // unload this document...
9817 if (!isJavaScript && !isDownload && !isExternalProtocol) {
9818 // Stop any current network activity.
9819 // Also stop content if this is a zombie doc. otherwise
9820 // the onload will be delayed by other loads initiated in the
9821 // background by the first document that
9822 // didn't fully load before the next load was initiated.
9823 // If not a zombie, don't stop content until data
9824 // starts arriving from the new URI...
9825 if ((mDocumentViewer && mDocumentViewer->GetPreviousViewer()) ||
9826 LOAD_TYPE_HAS_FLAGS(aLoadState->LoadType(), LOAD_FLAGS_STOP_CONTENT)((aLoadState->LoadType()) & ((LOAD_FLAGS_STOP_CONTENT)
<< 16))
) {
9827 rv = Stop(nsIWebNavigation::STOP_ALL);
9828 } else {
9829 rv = Stop(nsIWebNavigation::STOP_NETWORK);
9830 }
9831
9832 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
9833 return rv;
9834 }
9835 }
9836
9837 mLoadType = aLoadState->LoadType();
9838
9839 // aLoadState->SHEntry() should be assigned to mLSHE, only after Stop() has
9840 // been called. But when loading an error page, do not clear the
9841 // mLSHE for the real page.
9842 if (mLoadType != LOAD_ERROR_PAGE) {
9843 SetHistoryEntryAndUpdateBC(Some<nsISHEntry*>(aLoadState->SHEntry()),
9844 Nothing());
9845 if (aLoadState->LoadIsFromSessionHistory() &&
9846 !mozilla::SessionHistoryInParent()) {
9847 // We're making history navigation or a reload. Make sure our history ID
9848 // points to the same ID as SHEntry's docshell ID.
9849 nsID historyID = {};
9850 aLoadState->SHEntry()->GetDocshellID(historyID);
9851
9852 Unused << mBrowsingContext->SetHistoryID(historyID);
9853 }
9854 }
9855
9856 mSavingOldViewer = savePresentation;
9857
9858 // If we have a saved content viewer in history, restore and show it now.
9859 if (aLoadState->LoadIsFromSessionHistory() &&
9860 (mLoadType & LOAD_CMD_HISTORY)) {
9861 // https://html.spec.whatwg.org/#history-traversal:
9862 // To traverse the history
9863 // "If entry has a different Document object than the current entry, then
9864 // run the following substeps: Remove any tasks queued by the history
9865 // traversal task source..."
9866 // Same document object case was handled already above with
9867 // HandleSameDocumentNavigation call.
9868 RefPtr<ChildSHistory> shistory = GetRootSessionHistory();
9869 if (shistory) {
9870 shistory->RemovePendingHistoryNavigations();
9871 }
9872 if (!mozilla::SessionHistoryInParent()) {
9873 // It's possible that the previous viewer of mDocumentViewer is the
9874 // viewer that will end up in aLoadState->SHEntry() when it gets closed.
9875 // If that's the case, we need to go ahead and force it into its shentry
9876 // so we can restore it.
9877 if (mDocumentViewer) {
9878 nsCOMPtr<nsIDocumentViewer> prevViewer =
9879 mDocumentViewer->GetPreviousViewer();
9880 if (prevViewer) {
9881#ifdef DEBUG1
9882 nsCOMPtr<nsIDocumentViewer> prevPrevViewer =
9883 prevViewer->GetPreviousViewer();
9884 NS_ASSERTION(!prevPrevViewer, "Should never have viewer chain here")do { if (!(!prevPrevViewer)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "Should never have viewer chain here", "!prevPrevViewer", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 9884); MOZ_PretendNoReturn(); } } while (0)
;
9885#endif
9886 nsCOMPtr<nsISHEntry> viewerEntry;
9887 prevViewer->GetHistoryEntry(getter_AddRefs(viewerEntry));
9888 if (viewerEntry == aLoadState->SHEntry()) {
9889 // Make sure this viewer ends up in the right place
9890 mDocumentViewer->SetPreviousViewer(nullptr);
9891 prevViewer->Destroy();
9892 }
9893 }
9894 }
9895 nsCOMPtr<nsISHEntry> oldEntry = mOSHE;
9896 bool restoring;
9897 rv = RestorePresentation(aLoadState->SHEntry(), &restoring);
9898 if (restoring) {
9899 glean::bfcache::page_restored
9900 .EnumGet(glean::bfcache::PageRestoredLabel::eTrue)
9901 .Add();
9902 return rv;
9903 }
9904 glean::bfcache::page_restored
9905 .EnumGet(glean::bfcache::PageRestoredLabel::eFalse)
9906 .Add();
9907
9908 // We failed to restore the presentation, so clean up.
9909 // Both the old and new history entries could potentially be in
9910 // an inconsistent state.
9911 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
9912 if (oldEntry) {
9913 oldEntry->SyncPresentationState();
9914 }
9915
9916 aLoadState->SHEntry()->SyncPresentationState();
9917 }
9918 }
9919 }
9920
9921 bool isTopLevelDoc = mBrowsingContext->IsTopContent();
9922
9923 OriginAttributes attrs = GetOriginAttributes();
9924 attrs.SetFirstPartyDomain(isTopLevelDoc, aLoadState->URI());
9925
9926 PredictorLearn(aLoadState->URI(), nullptr,
9927 nsINetworkPredictor::LEARN_LOAD_TOPLEVEL, attrs);
9928 PredictorPredict(aLoadState->URI(), nullptr,
9929 nsINetworkPredictor::PREDICT_LOAD, attrs, nullptr);
9930
9931 nsCOMPtr<nsIRequest> req;
9932 rv = DoURILoad(aLoadState, aCacheKey, getter_AddRefs(req));
9933
9934 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
9935 if (shouldTakeFocus) {
9936 mBrowsingContext->Focus(CallerType::System, IgnoreErrors());
9937 }
9938 }
9939
9940 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
9941 nsCOMPtr<nsIChannel> chan(do_QueryInterface(req));
9942 UnblockEmbedderLoadEventForFailure();
9943 nsCOMPtr<nsIURI> uri = aLoadState->URI();
9944 if (DisplayLoadError(rv, uri, nullptr, chan) &&
9945 // FIXME: At this point code was using internal load flags, but checking
9946 // non-internal load flags?
9947 aLoadState->HasLoadFlags(LOAD_FLAGS_ERROR_LOAD_CHANGES_RV)) {
9948 return NS_ERROR_LOAD_SHOWED_ERRORPAGE;
9949 }
9950
9951 // We won't report any error if this is an unknown protocol error. The
9952 // reason behind this is that it will allow enumeration of external
9953 // protocols if we report an error for each unknown protocol.
9954 if (NS_ERROR_UNKNOWN_PROTOCOL == rv) {
9955 return NS_OK;
9956 }
9957
9958 // The spec says no exception should be raised for pre-navigation check
9959 // failures.
9960 if (NS_ERROR_DOM_SECURITY_ERR == rv) {
9961 return NS_OK;
9962 }
9963 }
9964
9965 return rv;
9966}
9967
9968/* static */
9969bool nsDocShell::CanLoadInParentProcess(nsIURI* aURI) {
9970 nsCOMPtr<nsIURI> uri = aURI;
9971 // In e10s, in the parent process, we refuse to load anything other than
9972 // "safe" resources that we ship or trust enough to give "special" URLs.
9973 bool canLoadInParent = false;
9974 if (NS_SUCCEEDED(NS_URIChainHasFlags(((bool)(__builtin_expect(!!(!NS_FAILED_impl(NS_URIChainHasFlags
( uri, nsIProtocolHandler::URI_IS_UI_RESOURCE, &canLoadInParent
))), 1)))
9975 uri, nsIProtocolHandler::URI_IS_UI_RESOURCE, &canLoadInParent))((bool)(__builtin_expect(!!(!NS_FAILED_impl(NS_URIChainHasFlags
( uri, nsIProtocolHandler::URI_IS_UI_RESOURCE, &canLoadInParent
))), 1)))
&&
9976 canLoadInParent) {
9977 // We allow UI resources.
9978 return true;
9979 }
9980 // For about: and extension-based URIs, which don't get
9981 // URI_IS_UI_RESOURCE, first remove layers of view-source:, if present.
9982 while (uri && uri->SchemeIs("view-source")) {
9983 nsCOMPtr<nsINestedURI> nested = do_QueryInterface(uri);
9984 if (nested) {
9985 nested->GetInnerURI(getter_AddRefs(uri));
9986 } else {
9987 break;
9988 }
9989 }
9990 // Allow about: URIs, and allow moz-extension ones if we're running
9991 // extension content in the parent process.
9992 if (!uri || uri->SchemeIs("about") ||
9993 (!StaticPrefs::extensions_webextensions_remote() &&
9994 uri->SchemeIs("moz-extension"))) {
9995 return true;
9996 }
9997#ifdef MOZ_THUNDERBIRD
9998 if (uri->SchemeIs("imap") || uri->SchemeIs("mailbox") ||
9999 uri->SchemeIs("news") || uri->SchemeIs("nntp") ||
10000 uri->SchemeIs("snews") || uri->SchemeIs("x-moz-ews")) {
10001 return true;
10002 }
10003#endif
10004 nsAutoCString scheme;
10005 uri->GetScheme(scheme);
10006 // Allow ext+foo URIs (extension-registered custom protocols). See
10007 // https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/protocol_handlers
10008 if (StringBeginsWith(scheme, "ext+"_ns) &&
10009 !StaticPrefs::extensions_webextensions_remote()) {
10010 return true;
10011 }
10012 // Final exception for some legacy automated tests:
10013 if (xpc::IsInAutomation() &&
10014 StaticPrefs::security_allow_unsafe_parent_loads()) {
10015 return true;
10016 }
10017 return false;
10018}
10019
10020nsIPrincipal* nsDocShell::GetInheritedPrincipal(
10021 bool aConsiderCurrentDocument, bool aConsiderPartitionedPrincipal) {
10022 RefPtr<Document> document;
10023 bool inheritedFromCurrent = false;
10024
10025 if (aConsiderCurrentDocument && mDocumentViewer) {
10026 document = mDocumentViewer->GetDocument();
10027 inheritedFromCurrent = true;
10028 }
10029
10030 if (!document) {
10031 nsCOMPtr<nsIDocShellTreeItem> parentItem;
10032 GetInProcessSameTypeParent(getter_AddRefs(parentItem));
10033 if (parentItem) {
10034 document = parentItem->GetDocument();
10035 }
10036 }
10037
10038 if (!document) {
10039 if (!aConsiderCurrentDocument) {
10040 return nullptr;
10041 }
10042
10043 // Make sure we end up with _something_ as the principal no matter
10044 // what.If this fails, we'll just get a null docViewer and bail.
10045 EnsureDocumentViewer();
10046 if (!mDocumentViewer) {
10047 return nullptr;
10048 }
10049 document = mDocumentViewer->GetDocument();
10050 }
10051
10052 //-- Get the document's principal
10053 if (document) {
10054 nsIPrincipal* docPrincipal = aConsiderPartitionedPrincipal
10055 ? document->PartitionedPrincipal()
10056 : document->NodePrincipal();
10057
10058 // Don't allow loads in typeContent docShells to inherit the system
10059 // principal from existing documents.
10060 if (inheritedFromCurrent && mItemType == typeContent &&
10061 docPrincipal->IsSystemPrincipal()) {
10062 return nullptr;
10063 }
10064
10065 return docPrincipal;
10066 }
10067
10068 return nullptr;
10069}
10070
10071/* static */ nsresult nsDocShell::CreateRealChannelForDocument(
10072 nsIChannel** aChannel, nsIURI* aURI, nsILoadInfo* aLoadInfo,
10073 nsIInterfaceRequestor* aCallbacks, nsLoadFlags aLoadFlags,
10074 const nsAString& aSrcdoc, nsIURI* aBaseURI) {
10075 nsCOMPtr<nsIChannel> channel;
10076 if (aSrcdoc.IsVoid()) {
10077 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(); })
10078 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(); })
10079 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(); })
10080 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(); })
;
10081
10082 if (aBaseURI) {
10083 nsCOMPtr<nsIViewSourceChannel> vsc = do_QueryInterface(channel);
10084 if (vsc) {
10085 MOZ_ALWAYS_SUCCEEDS(vsc->SetBaseURI(aBaseURI))do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(vsc->SetBaseURI(aBaseURI))), 1)))), 1))) { } else { do { do
{ } while (false); MOZ_ReportCrash("" "NS_SUCCEEDED(vsc->SetBaseURI(aBaseURI))"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 10085);
AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED(vsc->SetBaseURI(aBaseURI))"
")"); do { MOZ_CrashSequence(__null, 10085); __attribute__((
nomerge)) ::abort(); } while (false); } while (false); } } while
(false)
;
10086 }
10087 }
10088 } else if (aURI->SchemeIs("view-source")) {
10089 // Instantiate view source handler protocol, if it doesn't exist already.
10090 nsCOMPtr<nsIIOService> io(do_GetIOService());
10091 MOZ_ASSERT(io)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(io)>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(io))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("io", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 10091); AnnotateMozCrashReason("MOZ_ASSERT" "(" "io" ")"); do
{ MOZ_CrashSequence(__null, 10091); __attribute__((nomerge))
::abort(); } while (false); } } while (false)
;
10092 nsCOMPtr<nsIProtocolHandler> handler;
10093 nsresult rv =
10094 io->GetProtocolHandler("view-source", getter_AddRefs(handler));
10095 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
10096 return rv;
10097 }
10098
10099 nsViewSourceHandler* vsh = nsViewSourceHandler::GetInstance();
10100 if (!vsh) {
10101 return NS_ERROR_FAILURE;
10102 }
10103
10104 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(); })
10105 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(); })
;
10106 } else {
10107 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(); })
10108 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(); })
10109 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(); })
;
10110 nsCOMPtr<nsIInputStreamChannel> isc = do_QueryInterface(channel);
10111 MOZ_ASSERT(isc)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(isc)>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(isc))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("isc", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 10111); AnnotateMozCrashReason("MOZ_ASSERT" "(" "isc" ")");
do { MOZ_CrashSequence(__null, 10111); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
10112 isc->SetBaseURI(aBaseURI);
10113 }
10114
10115 if (aLoadFlags != nsIRequest::LOAD_NORMAL) {
10116 nsresult rv = channel->SetLoadFlags(aLoadFlags);
10117 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 10117); return rv; } } while (false)
;
10118 }
10119
10120 channel.forget(aChannel);
10121 return NS_OK;
10122}
10123
10124/* static */ bool nsDocShell::CreateAndConfigureRealChannelForLoadState(
10125 BrowsingContext* aBrowsingContext, nsDocShellLoadState* aLoadState,
10126 LoadInfo* aLoadInfo, nsIInterfaceRequestor* aCallbacks,
10127 nsDocShell* aDocShell, const OriginAttributes& aOriginAttributes,
10128 nsLoadFlags aLoadFlags, uint32_t aCacheKey, nsresult& aRv,
10129 nsIChannel** aChannel) {
10130 MOZ_ASSERT(aLoadInfo)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aLoadInfo)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aLoadInfo))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aLoadInfo", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 10130); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadInfo"
")"); do { MOZ_CrashSequence(__null, 10130); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10131
10132 nsString srcdoc = VoidString();
10133 bool isSrcdoc =
10134 aLoadState->HasInternalLoadFlags(INTERNAL_LOAD_FLAGS_IS_SRCDOC);
10135 if (isSrcdoc) {
10136 srcdoc = aLoadState->SrcdocData();
10137 }
10138
10139 aLoadInfo->SetTriggeringRemoteType(
10140 aLoadState->GetEffectiveTriggeringRemoteType());
10141
10142 if (aLoadState->PrincipalToInherit()) {
10143 aLoadInfo->SetPrincipalToInherit(aLoadState->PrincipalToInherit());
10144 }
10145 aLoadInfo->SetLoadTriggeredFromExternal(
10146 aLoadState->HasLoadFlags(LOAD_FLAGS_FROM_EXTERNAL));
10147 aLoadInfo->SetForceAllowDataURI(aLoadState->HasInternalLoadFlags(
10148 INTERNAL_LOAD_FLAGS_FORCE_ALLOW_DATA_URI));
10149 aLoadInfo->SetOriginalFrameSrcLoad(
10150 aLoadState->HasInternalLoadFlags(INTERNAL_LOAD_FLAGS_ORIGINAL_FRAME_SRC));
10151 aLoadInfo->SetIsNewWindowTarget(
10152 aLoadState->HasInternalLoadFlags(INTERNAL_LOAD_FLAGS_FIRST_LOAD));
10153
10154 bool inheritAttrs = false;
10155 if (aLoadState->PrincipalToInherit()) {
10156 inheritAttrs = nsContentUtils::ChannelShouldInheritPrincipal(
10157 aLoadState->PrincipalToInherit(), aLoadState->URI(),
10158 true, // aInheritForAboutBlank
10159 isSrcdoc);
10160 }
10161
10162 // Strip the target query parameters before creating the channel.
10163 aLoadState->MaybeStripTrackerQueryStrings(aBrowsingContext);
10164
10165 OriginAttributes attrs;
10166
10167 // Inherit origin attributes from PrincipalToInherit if inheritAttrs is
10168 // true. Otherwise we just use the origin attributes from docshell.
10169 if (inheritAttrs) {
10170 MOZ_ASSERT(aLoadState->PrincipalToInherit(),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aLoadState->PrincipalToInherit())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aLoadState->PrincipalToInherit
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("aLoadState->PrincipalToInherit()" " (" "We should have PrincipalToInherit here."
")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 10171
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->PrincipalToInherit()"
") (" "We should have PrincipalToInherit here." ")"); do { MOZ_CrashSequence
(__null, 10171); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
10171 "We should have PrincipalToInherit here.")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aLoadState->PrincipalToInherit())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aLoadState->PrincipalToInherit
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("aLoadState->PrincipalToInherit()" " (" "We should have PrincipalToInherit here."
")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 10171
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->PrincipalToInherit()"
") (" "We should have PrincipalToInherit here." ")"); do { MOZ_CrashSequence
(__null, 10171); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
10172 attrs = aLoadState->PrincipalToInherit()->OriginAttributesRef();
10173 // If firstPartyIsolation is not enabled, then PrincipalToInherit should
10174 // have the same origin attributes with docshell.
10175 MOZ_ASSERT_IF(!OriginAttributes::IsFirstPartyEnabled(),do { if (!OriginAttributes::IsFirstPartyEnabled()) { do { static_assert
( mozilla::detail::AssertionConditionType<decltype(attrs ==
aOriginAttributes)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(attrs == aOriginAttributes))
), 0))) { do { } while (false); MOZ_ReportAssertionFailure("attrs == aOriginAttributes"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 10176);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "attrs == aOriginAttributes"
")"); do { MOZ_CrashSequence(__null, 10176); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false); } } while
(false)
10176 attrs == aOriginAttributes)do { if (!OriginAttributes::IsFirstPartyEnabled()) { do { static_assert
( mozilla::detail::AssertionConditionType<decltype(attrs ==
aOriginAttributes)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(attrs == aOriginAttributes))
), 0))) { do { } while (false); MOZ_ReportAssertionFailure("attrs == aOriginAttributes"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 10176);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "attrs == aOriginAttributes"
")"); do { MOZ_CrashSequence(__null, 10176); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false); } } while
(false)
;
10177 } else {
10178 attrs = aOriginAttributes;
10179 attrs.SetFirstPartyDomain(IsTopLevelDoc(aBrowsingContext, aLoadInfo),
10180 aLoadState->URI());
10181 }
10182
10183 aRv = aLoadInfo->SetOriginAttributes(attrs);
10184 if (NS_WARN_IF(NS_FAILED(aRv))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(aRv
)), 0))), "NS_FAILED(aRv)", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 10184)
) {
10185 return false;
10186 }
10187
10188 if (aLoadState->GetIsFromProcessingFrameAttributes()) {
10189 aLoadInfo->SetIsFromProcessingFrameAttributes();
10190 }
10191
10192 // Propagate the IsFormSubmission flag to the loadInfo.
10193 if (aLoadState->IsFormSubmission()) {
10194 aLoadInfo->SetIsFormSubmission(true);
10195 }
10196
10197 aLoadInfo->SetUnstrippedURI(aLoadState->GetUnstrippedURI());
10198
10199 nsCOMPtr<nsIChannel> channel;
10200 aRv = CreateRealChannelForDocument(getter_AddRefs(channel), aLoadState->URI(),
10201 aLoadInfo, aCallbacks, aLoadFlags, srcdoc,
10202 aLoadState->BaseURI());
10203 NS_ENSURE_SUCCESS(aRv, false)do { nsresult __rv = aRv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "aRv", "false", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 10203); return false; } } while (false)
;
10204
10205 if (!channel) {
10206 return false;
10207 }
10208
10209 // If the HTTPS-Only mode is enabled, every insecure request gets upgraded to
10210 // HTTPS by default. This behavior can be disabled through the loadinfo flag
10211 // HTTPS_ONLY_EXEMPT.
10212 nsHTTPSOnlyUtils::TestSitePermissionAndPotentiallyAddExemption(channel);
10213
10214 // hack
10215 nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(channel));
10216 nsCOMPtr<nsIHttpChannelInternal> httpChannelInternal(
10217 do_QueryInterface(channel));
10218 nsCOMPtr<nsIURI> referrer;
10219 nsIReferrerInfo* referrerInfo = aLoadState->GetReferrerInfo();
10220 if (referrerInfo) {
10221 referrerInfo->GetOriginalReferrer(getter_AddRefs(referrer));
10222 }
10223 if (httpChannelInternal) {
10224 if (aLoadState->HasInternalLoadFlags(
10225 INTERNAL_LOAD_FLAGS_FORCE_ALLOW_COOKIES)) {
10226 aRv = httpChannelInternal->SetThirdPartyFlags(
10227 nsIHttpChannelInternal::THIRD_PARTY_FORCE_ALLOW);
10228 MOZ_ASSERT(NS_SUCCEEDED(aRv))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(((bool)(__builtin_expect(!!(!NS_FAILED_impl(aRv)), 1
))))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(aRv)), 1
)))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("((bool)(__builtin_expect(!!(!NS_FAILED_impl(aRv)), 1)))", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 10228); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(aRv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 10228); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10229 }
10230 if (aLoadState->FirstParty()) {
10231 aRv = httpChannelInternal->SetDocumentURI(aLoadState->URI());
10232 MOZ_ASSERT(NS_SUCCEEDED(aRv))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(((bool)(__builtin_expect(!!(!NS_FAILED_impl(aRv)), 1
))))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(aRv)), 1
)))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("((bool)(__builtin_expect(!!(!NS_FAILED_impl(aRv)), 1)))", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 10232); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(aRv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 10232); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10233 } else {
10234 aRv = httpChannelInternal->SetDocumentURI(referrer);
10235 MOZ_ASSERT(NS_SUCCEEDED(aRv))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(((bool)(__builtin_expect(!!(!NS_FAILED_impl(aRv)), 1
))))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(aRv)), 1
)))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("((bool)(__builtin_expect(!!(!NS_FAILED_impl(aRv)), 1)))", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 10235); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(aRv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 10235); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10236 }
10237 aRv = httpChannelInternal->SetRedirectMode(
10238 nsIHttpChannelInternal::REDIRECT_MODE_MANUAL);
10239 MOZ_ASSERT(NS_SUCCEEDED(aRv))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(((bool)(__builtin_expect(!!(!NS_FAILED_impl(aRv)), 1
))))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(aRv)), 1
)))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("((bool)(__builtin_expect(!!(!NS_FAILED_impl(aRv)), 1)))", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 10239); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(aRv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 10239); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10240 }
10241
10242 if (httpChannel) {
10243 if (aLoadState->HeadersStream()) {
10244 aRv = AddHeadersToChannel(aLoadState->HeadersStream(), httpChannel);
10245 }
10246 // Set the referrer explicitly
10247 // Referrer is currenly only set for link clicks here.
10248 if (referrerInfo) {
10249 aRv = httpChannel->SetReferrerInfo(referrerInfo);
10250 MOZ_ASSERT(NS_SUCCEEDED(aRv))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(((bool)(__builtin_expect(!!(!NS_FAILED_impl(aRv)), 1
))))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(aRv)), 1
)))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("((bool)(__builtin_expect(!!(!NS_FAILED_impl(aRv)), 1)))", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 10250); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(aRv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 10250); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10251 }
10252
10253 // Mark the http channel as UrgentStart for top level document loading in
10254 // active tab.
10255 if (IsUrgentStart(aBrowsingContext, aLoadInfo, aLoadState->LoadType())) {
10256 nsCOMPtr<nsIClassOfService> cos(do_QueryInterface(channel));
10257 if (cos) {
10258 cos->AddClassFlags(nsIClassOfService::UrgentStart);
10259 if (StaticPrefs::dom_document_priority_incremental()) {
10260 cos->SetIncremental(true);
10261 }
10262 }
10263 }
10264 }
10265
10266 channel->SetOriginalURI(aLoadState->OriginalURI() ? aLoadState->OriginalURI()
10267 : aLoadState->URI());
10268
10269 const nsACString& typeHint = aLoadState->TypeHint();
10270 if (!typeHint.IsVoid()) {
10271 channel->SetContentType(typeHint);
10272 }
10273
10274 const nsAString& fileName = aLoadState->FileName();
10275 if (!fileName.IsVoid()) {
10276 aRv = channel->SetContentDisposition(nsIChannel::DISPOSITION_ATTACHMENT);
10277 NS_ENSURE_SUCCESS(aRv, false)do { nsresult __rv = aRv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "aRv", "false", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 10277); return false; } } while (false)
;
10278 if (!fileName.IsEmpty()) {
10279 aRv = channel->SetContentDispositionFilename(fileName);
10280 NS_ENSURE_SUCCESS(aRv, false)do { nsresult __rv = aRv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "aRv", "false", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 10280); return false; } } while (false)
;
10281 }
10282 }
10283
10284 if (nsCOMPtr<nsIWritablePropertyBag2> props = do_QueryInterface(channel)) {
10285 nsCOMPtr<nsIURI> referrer;
10286 nsIReferrerInfo* referrerInfo = aLoadState->GetReferrerInfo();
10287 if (referrerInfo) {
10288 referrerInfo->GetOriginalReferrer(getter_AddRefs(referrer));
10289 }
10290 // save true referrer for those who need it (e.g. xpinstall whitelisting)
10291 // Currently only http and ftp channels support this.
10292 props->SetPropertyAsInterface(u"docshell.internalReferrer"_ns, referrer);
10293 }
10294
10295 nsCOMPtr<nsICacheInfoChannel> cacheChannel(do_QueryInterface(channel));
10296 auto loadType = aLoadState->LoadType();
10297
10298 if (loadType == LOAD_RELOAD_NORMAL &&
10299 StaticPrefs::
10300 browser_soft_reload_only_force_validate_top_level_document()) {
10301 nsCOMPtr<nsICacheInfoChannel> cachingChannel = do_QueryInterface(channel);
10302 if (cachingChannel) {
10303 cachingChannel->SetForceValidateCacheContent(true);
10304 }
10305 }
10306
10307 // figure out if we need to set the post data stream on the channel...
10308 if (aLoadState->PostDataStream()) {
10309 if (nsCOMPtr<nsIFormPOSTActionChannel> postChannel =
10310 do_QueryInterface(channel)) {
10311 // XXX it's a bit of a hack to rewind the postdata stream here but
10312 // it has to be done in case the post data is being reused multiple
10313 // times.
10314 nsCOMPtr<nsISeekableStream> postDataSeekable =
10315 do_QueryInterface(aLoadState->PostDataStream());
10316 if (postDataSeekable) {
10317 aRv = postDataSeekable->Seek(nsISeekableStream::NS_SEEK_SET, 0);
10318 NS_ENSURE_SUCCESS(aRv, false)do { nsresult __rv = aRv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "aRv", "false", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 10318); return false; } } while (false)
;
10319 }
10320
10321 // we really need to have a content type associated with this stream!!
10322 postChannel->SetUploadStream(aLoadState->PostDataStream(), ""_ns, -1);
10323
10324 // Ownership of the stream has transferred to the channel, clear our
10325 // reference.
10326 aLoadState->SetPostDataStream(nullptr);
10327 }
10328
10329 /* If there is a valid postdata *and* it is a History Load,
10330 * set up the cache key on the channel, to retrieve the
10331 * data *only* from the cache. If it is a normal reload, the
10332 * cache is free to go to the server for updated postdata.
10333 */
10334 if (cacheChannel && aCacheKey != 0) {
10335 if (loadType == LOAD_HISTORY || loadType == LOAD_RELOAD_CHARSET_CHANGE) {
10336 cacheChannel->SetCacheKey(aCacheKey);
10337 uint32_t loadFlags;
10338 if (NS_SUCCEEDED(channel->GetLoadFlags(&loadFlags))((bool)(__builtin_expect(!!(!NS_FAILED_impl(channel->GetLoadFlags
(&loadFlags))), 1)))
) {
10339 channel->SetLoadFlags(loadFlags |
10340 nsICachingChannel::LOAD_ONLY_FROM_CACHE);
10341 }
10342 } else if (loadType == LOAD_RELOAD_NORMAL) {
10343 cacheChannel->SetCacheKey(aCacheKey);
10344 }
10345 }
10346 } else {
10347 /* If there is no postdata, set the cache key on the channel, and
10348 * do not set the LOAD_ONLY_FROM_CACHE flag, so that the channel
10349 * will be free to get it from net if it is not found in cache.
10350 * New cache may use it creatively on CGI pages with GET
10351 * method and even on those that say "no-cache"
10352 */
10353 if (loadType == LOAD_HISTORY || loadType == LOAD_RELOAD_NORMAL ||
10354 loadType == LOAD_RELOAD_CHARSET_CHANGE ||
10355 loadType == LOAD_RELOAD_CHARSET_CHANGE_BYPASS_CACHE ||
10356 loadType == LOAD_RELOAD_CHARSET_CHANGE_BYPASS_PROXY_AND_CACHE) {
10357 if (cacheChannel && aCacheKey != 0) {
10358 cacheChannel->SetCacheKey(aCacheKey);
10359 }
10360 }
10361 }
10362
10363 if (nsCOMPtr<nsIScriptChannel> scriptChannel = do_QueryInterface(channel)) {
10364 // Allow execution against our context if the principals match
10365 scriptChannel->SetExecutionPolicy(nsIScriptChannel::EXECUTE_NORMAL);
10366 }
10367
10368 if (nsCOMPtr<nsITimedChannel> timedChannel = do_QueryInterface(channel)) {
10369 nsString initiatorType;
10370 switch (aLoadInfo->InternalContentPolicyType()) {
10371 case nsIContentPolicy::TYPE_INTERNAL_EMBED:
10372 initiatorType = u"embed"_ns;
10373 break;
10374 case nsIContentPolicy::TYPE_INTERNAL_OBJECT:
10375 initiatorType = u"object"_ns;
10376 break;
10377 default: {
10378 const auto& embedderElementType =
10379 aBrowsingContext->GetEmbedderElementType();
10380 if (embedderElementType) {
10381 initiatorType = *embedderElementType;
10382 }
10383 break;
10384 }
10385 }
10386
10387 if (!initiatorType.IsEmpty()) {
10388 timedChannel->SetInitiatorType(initiatorType);
10389 }
10390 }
10391
10392 nsCOMPtr<nsIURI> rpURI;
10393 aLoadInfo->GetResultPrincipalURI(getter_AddRefs(rpURI));
10394 Maybe<nsCOMPtr<nsIURI>> originalResultPrincipalURI;
10395 aLoadState->GetMaybeResultPrincipalURI(originalResultPrincipalURI);
10396 if (originalResultPrincipalURI &&
10397 (!aLoadState->KeepResultPrincipalURIIfSet() || !rpURI)) {
10398 // Unconditionally override, we want the replay to be equal to what has
10399 // been captured.
10400 aLoadInfo->SetResultPrincipalURI(originalResultPrincipalURI.ref());
10401 }
10402
10403 if (aLoadState->OriginalURI() && aLoadState->LoadReplace()) {
10404 // The LOAD_REPLACE flag and its handling here will be removed as part
10405 // of bug 1319110. For now preserve its restoration here to not break
10406 // any code expecting it being set specially on redirected channels.
10407 // If the flag has originally been set to change result of
10408 // NS_GetFinalChannelURI it won't have any effect and also won't cause
10409 // any harm.
10410 uint32_t loadFlags;
10411 aRv = channel->GetLoadFlags(&loadFlags);
10412 NS_ENSURE_SUCCESS(aRv, false)do { nsresult __rv = aRv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "aRv", "false", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 10412); return false; } } while (false)
;
10413 channel->SetLoadFlags(loadFlags | nsIChannel::LOAD_REPLACE);
10414 }
10415
10416 nsCOMPtr<nsIContentSecurityPolicy> csp = aLoadState->Csp();
10417 if (csp) {
10418 // Navigational requests that are same origin need to be upgraded in case
10419 // upgrade-insecure-requests is present. Please note that for document
10420 // navigations that bit is re-computed in case we encounter a server
10421 // side redirect so the navigation is not same-origin anymore.
10422 bool upgradeInsecureRequests = false;
10423 csp->GetUpgradeInsecureRequests(&upgradeInsecureRequests);
10424 if (upgradeInsecureRequests) {
10425 // only upgrade if the navigation is same origin
10426 nsCOMPtr<nsIPrincipal> resultPrincipal;
10427 aRv = nsContentUtils::GetSecurityManager()->GetChannelResultPrincipal(
10428 channel, getter_AddRefs(resultPrincipal));
10429 NS_ENSURE_SUCCESS(aRv, false)do { nsresult __rv = aRv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "aRv", "false", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 10429); return false; } } while (false)
;
10430 if (nsContentSecurityUtils::IsConsideredSameOriginForUIR(
10431 aLoadState->TriggeringPrincipal(), resultPrincipal)) {
10432 aLoadInfo->SetUpgradeInsecureRequests(true);
10433 }
10434 }
10435
10436 // For document loads we store the CSP that potentially needs to
10437 // be inherited by the new document, e.g. in case we are loading
10438 // an opaque origin like a data: URI. The actual inheritance
10439 // check happens within Document::InitCSP().
10440 // Please create an actual copy of the CSP (do not share the same
10441 // reference) otherwise a Meta CSP of an opaque origin will
10442 // incorrectly be propagated to the embedding document.
10443 RefPtr<nsCSPContext> cspToInherit = new nsCSPContext();
10444 cspToInherit->InitFromOther(static_cast<nsCSPContext*>(csp.get()));
10445 aLoadInfo->SetCSPToInherit(cspToInherit);
10446 }
10447
10448 channel.forget(aChannel);
10449 return true;
10450}
10451
10452bool nsDocShell::IsAboutBlankLoadOntoInitialAboutBlank(
10453 nsIURI* aURI, bool aInheritPrincipal, nsIPrincipal* aPrincipalToInherit) {
10454 return NS_IsAboutBlankAllowQueryAndFragment(aURI) && aInheritPrincipal &&
10455 (aPrincipalToInherit == GetInheritedPrincipal(false)) &&
10456 (!mDocumentViewer || !mDocumentViewer->GetDocument() ||
10457 mDocumentViewer->GetDocument()->IsInitialDocument());
10458}
10459
10460nsresult nsDocShell::PerformTrustedTypesPreNavigationCheck(
10461 nsDocShellLoadState* aLoadState, nsGlobalWindowInner* aWindow) const {
10462 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", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 10462); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aWindow" ")"
); do { MOZ_CrashSequence(__null, 10462); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
10463 RefPtr<nsIContentSecurityPolicy> csp = aWindow->GetCsp();
10464 if (csp->GetRequireTrustedTypesForDirectiveState() ==
10465 RequireTrustedTypesForDirectiveState::NONE) {
10466 return NS_OK;
10467 }
10468
10469 // If disposion is enforce for require-trusted-types-for, then we return
10470 // errors in order to block navigation. If it's report-only, errors are
10471 // ignored and the URL is unchanged.
10472 bool shouldBlockOnError = csp->GetRequireTrustedTypesForDirectiveState() ==
10473 RequireTrustedTypesForDirectiveState::ENFORCE;
10474
10475 // 2. Let urlString be the result of running the URL serializer on
10476 // request’s url.
10477 nsAutoCString urlString;
10478 aLoadState->URI()->GetSpec(urlString);
10479
10480 // 3. Let encodedScriptSource be the result of removing the leading
10481 // "javascript:" from urlString.
10482 constexpr auto javascriptScheme = "javascript:"_ns;
10483 const nsDependentCSubstring encodedScriptSource =
10484 Substring(urlString, javascriptScheme.Length());
10485
10486 // 4. Let convertedScriptSource be the result of executing Process value
10487 // with a default policy algorithm
10488 Maybe<nsAutoString> compliantStringHolder;
10489 NS_ConvertUTF8toUTF16 encodedScriptSourceUTF16(encodedScriptSource);
10490 constexpr nsLiteralString sink = u"Location href"_ns;
10491 auto reportPreNavigationCheckViolations = [&csp, &sink,
10492 &encodedScriptSourceUTF16] {
10493 // Report violation the same way as for "Should sink type mismatch
10494 // violation be blocked by Content Security Policy", since that's what
10495 // other browsers do. See
10496 // https://github.com/w3c/trusted-types/issues/584.
10497 auto location = JSCallingLocation::Get();
10498 TrustedTypeUtils::ReportSinkTypeMismatchViolations(
10499 csp, nullptr /* aCSPEventListener */, location.FileName(),
10500 location.mLine, location.mColumn, sink, kTrustedTypesOnlySinkGroup,
10501 encodedScriptSourceUTF16);
10502 };
10503 ErrorResult error;
10504 auto convertedScriptSource =
10505 TrustedTypeUtils::GetConvertedScriptSourceForPreNavigationCheck(
10506 *aWindow, encodedScriptSourceUTF16, sink, compliantStringHolder,
10507 error);
10508 error.WouldReportJSException();
10509 if (error.Failed()) {
10510 reportPreNavigationCheckViolations();
10511 if (shouldBlockOnError) {
10512 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, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 10512); return (error).StealNSResult(); } } while (0)
;
10513 }
10514 error.SuppressException();
10515 return NS_OK;
10516 }
10517
10518 // 5. Set urlString to be the result of prepending "javascript:" to
10519 // stringified convertedScriptSource.
10520 urlString = javascriptScheme + NS_ConvertUTF16toUTF8(*convertedScriptSource);
10521
10522 // 6. Let newURL be the result of running the URL parser on urlString.
10523 nsCOMPtr<nsIURI> newURL;
10524 nsresult rv = NS_NewURI(getter_AddRefs(newURL), urlString);
10525 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
10526 reportPreNavigationCheckViolations();
10527 return shouldBlockOnError ? rv : NS_OK;
10528 }
10529
10530 // 7. Set request’s url to newURL.
10531 aLoadState->SetURI(newURL);
10532 return NS_OK;
10533}
10534
10535nsresult nsDocShell::DoURILoad(nsDocShellLoadState* aLoadState,
10536 Maybe<uint32_t> aCacheKey,
10537 nsIRequest** aRequest) {
10538 // Double-check that we're still around to load this URI.
10539 if (mIsBeingDestroyed) {
10540 // Return NS_OK despite not doing anything to avoid throwing exceptions
10541 // from nsLocation::SetHref if the unload handler of the existing page
10542 // tears us down.
10543 return NS_OK;
10544 }
10545
10546 nsCOMPtr<nsIURILoader> uriLoader = components::URILoader::Service();
10547 if (NS_WARN_IF(!uriLoader)NS_warn_if_impl(!uriLoader, "!uriLoader", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 10547)
) {
10548 return NS_ERROR_UNEXPECTED;
10549 }
10550
10551 // Persist and sync layout history state before we load a new uri, as this
10552 // might be our last chance to do so, in the content process.
10553 PersistLayoutHistoryState();
10554 SynchronizeLayoutHistoryState();
10555
10556 nsresult rv;
10557 nsContentPolicyType contentPolicyType = DetermineContentType();
10558
10559 auto getSourceWindowContext = [this, &aLoadState] {
10560 const MaybeDiscardedBrowsingContext& sourceBC =
10561 aLoadState->SourceBrowsingContext();
10562 if (!sourceBC.IsNullOrDiscarded()) {
10563 if (WindowContext* wc = sourceBC.get()->GetCurrentWindowContext()) {
10564 return wc;
10565 }
10566 }
10567 return mBrowsingContext->GetParentWindowContext();
10568 };
10569
10570 if (StaticPrefs::dom_security_trusted_types_enabled() &&
10571 aLoadState->URI()->SchemeIs("javascript")) {
10572 if (WindowContext* sourceWindowContext = getSourceWindowContext()) {
10573 RefPtr<nsGlobalWindowInner> window =
10574 sourceWindowContext->GetInnerWindow();
10575 rv = PerformTrustedTypesPreNavigationCheck(aLoadState, window);
10576 // Default policy might destroy the whole docshell, so check that again.
10577 if (mIsBeingDestroyed) {
10578 return NS_OK;
10579 }
10580 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
10581 return NS_ERROR_DOM_SECURITY_ERR;
10582 }
10583 }
10584 }
10585
10586 if (IsSubframe()) {
10587 MOZ_ASSERT(contentPolicyType == nsIContentPolicy::TYPE_INTERNAL_IFRAME ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(contentPolicyType == nsIContentPolicy::TYPE_INTERNAL_IFRAME
|| contentPolicyType == nsIContentPolicy::TYPE_INTERNAL_FRAME
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(contentPolicyType == nsIContentPolicy::TYPE_INTERNAL_IFRAME
|| contentPolicyType == nsIContentPolicy::TYPE_INTERNAL_FRAME
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"contentPolicyType == nsIContentPolicy::TYPE_INTERNAL_IFRAME || contentPolicyType == nsIContentPolicy::TYPE_INTERNAL_FRAME"
" (" "DoURILoad thinks this is a frame and InternalLoad does not"
")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 10589
); 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, 10589); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
10588 contentPolicyType == nsIContentPolicy::TYPE_INTERNAL_FRAME,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(contentPolicyType == nsIContentPolicy::TYPE_INTERNAL_IFRAME
|| contentPolicyType == nsIContentPolicy::TYPE_INTERNAL_FRAME
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(contentPolicyType == nsIContentPolicy::TYPE_INTERNAL_IFRAME
|| contentPolicyType == nsIContentPolicy::TYPE_INTERNAL_FRAME
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"contentPolicyType == nsIContentPolicy::TYPE_INTERNAL_IFRAME || contentPolicyType == nsIContentPolicy::TYPE_INTERNAL_FRAME"
" (" "DoURILoad thinks this is a frame and InternalLoad does not"
")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 10589
); 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, 10589); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
10589 "DoURILoad thinks this is a frame and InternalLoad does not")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(contentPolicyType == nsIContentPolicy::TYPE_INTERNAL_IFRAME
|| contentPolicyType == nsIContentPolicy::TYPE_INTERNAL_FRAME
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(contentPolicyType == nsIContentPolicy::TYPE_INTERNAL_IFRAME
|| contentPolicyType == nsIContentPolicy::TYPE_INTERNAL_FRAME
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"contentPolicyType == nsIContentPolicy::TYPE_INTERNAL_IFRAME || contentPolicyType == nsIContentPolicy::TYPE_INTERNAL_FRAME"
" (" "DoURILoad thinks this is a frame and InternalLoad does not"
")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 10589
); 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, 10589); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10590 if (StaticPrefs::dom_block_external_protocol_in_iframes()) {
10591 // Only allow URLs able to return data in iframes.
10592 if (nsContentUtils::IsExternalProtocol(aLoadState->URI())) {
10593 // The context to check user-interaction with for the purposes of
10594 // popup-blocking.
10595 //
10596 // We generally want to check the context that initiated the navigation.
10597 WindowContext* sourceWindowContext = getSourceWindowContext();
10598 MOZ_ASSERT(sourceWindowContext)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(sourceWindowContext)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(sourceWindowContext))), 0)))
{ do { } while (false); MOZ_ReportAssertionFailure("sourceWindowContext"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 10598);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "sourceWindowContext"
")"); do { MOZ_CrashSequence(__null, 10598); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10599
10600 // FIXME: We can't check user-interaction against an OOP window. This is
10601 // the next best thing we can really do. The load state keeps whether
10602 // the navigation had a user interaction in process
10603 // (aLoadState->HasValidUserGestureActivation()), but we can't really
10604 // consume it, which we want to prevent popup-spamming from the same
10605 // click event.
10606 WindowContext* context =
10607 sourceWindowContext->IsInProcess()
10608 ? sourceWindowContext
10609 : mBrowsingContext->GetCurrentWindowContext();
10610 const bool popupBlocked = [&] {
10611 const bool active = mBrowsingContext->IsActive();
10612
10613 // For same-origin-with-top windows, we grant a single free popup
10614 // without user activation, see bug 1680721.
10615 //
10616 // We consume the flag now even if there's no user activation.
10617 const bool hasFreePass = [&] {
10618 if (!active ||
10619 !(context->IsInProcess() && context->SameOriginWithTop())) {
10620 return false;
10621 }
10622 nsGlobalWindowInner* win =
10623 context->TopWindowContext()->GetInnerWindow();
10624 return win && win->TryOpenExternalProtocolIframe();
10625 }();
10626
10627 if (context->IsInProcess() &&
10628 context->ConsumeTransientUserGestureActivation()) {
10629 // If the user has interacted with the page, consume it.
10630 return false;
10631 }
10632
10633 // TODO(emilio): Can we remove this check? It seems like what prompted
10634 // this code (bug 1514547) should be covered by transient user
10635 // activation, see bug 1514547.
10636 if (active &&
10637 PopupBlocker::ConsumeTimerTokenForExternalProtocolIframe()) {
10638 return false;
10639 }
10640
10641 if (sourceWindowContext->CanShowPopup()) {
10642 return false;
10643 }
10644
10645 if (hasFreePass) {
10646 return false;
10647 }
10648
10649 return true;
10650 }();
10651
10652 // No error must be returned when iframes are blocked.
10653 if (popupBlocked) {
10654 nsAutoString message;
10655 nsresult rv = nsContentUtils::GetLocalizedString(
10656 nsContentUtils::eDOM_PROPERTIES,
10657 "ExternalProtocolFrameBlockedNoUserActivation", message);
10658 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
10659 nsContentUtils::ReportToConsoleByWindowID(
10660 message, nsIScriptError::warningFlag, "DOM"_ns,
10661 context->InnerWindowId());
10662 }
10663 return NS_OK;
10664 }
10665 }
10666 }
10667
10668 // Only allow view-source scheme in top-level docshells. view-source is
10669 // the only scheme to which this applies at the moment due to potential
10670 // timing attacks to read data from cross-origin iframes. If this widens
10671 // we should add a protocol flag for whether the scheme is allowed in
10672 // frames and use something like nsNetUtil::NS_URIChainHasFlags.
10673 nsCOMPtr<nsIURI> tempURI = aLoadState->URI();
10674 nsCOMPtr<nsINestedURI> nestedURI = do_QueryInterface(tempURI);
10675 while (nestedURI) {
10676 // view-source should always be an nsINestedURI, loop and check the
10677 // scheme on this and all inner URIs that are also nested URIs.
10678 if (tempURI->SchemeIs("view-source")) {
10679 return NS_ERROR_UNKNOWN_PROTOCOL;
10680 }
10681 nestedURI->GetInnerURI(getter_AddRefs(tempURI));
10682 nestedURI = do_QueryInterface(tempURI);
10683 }
10684 } else {
10685 MOZ_ASSERT(contentPolicyType == nsIContentPolicy::TYPE_DOCUMENT,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(contentPolicyType == nsIContentPolicy::TYPE_DOCUMENT
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(contentPolicyType == nsIContentPolicy::TYPE_DOCUMENT
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"contentPolicyType == nsIContentPolicy::TYPE_DOCUMENT" " (" "DoURILoad thinks this is a document and InternalLoad does not"
")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 10686
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "contentPolicyType == nsIContentPolicy::TYPE_DOCUMENT"
") (" "DoURILoad thinks this is a document and InternalLoad does not"
")"); do { MOZ_CrashSequence(__null, 10686); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
10686 "DoURILoad thinks this is a document and InternalLoad does not")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(contentPolicyType == nsIContentPolicy::TYPE_DOCUMENT
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(contentPolicyType == nsIContentPolicy::TYPE_DOCUMENT
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"contentPolicyType == nsIContentPolicy::TYPE_DOCUMENT" " (" "DoURILoad thinks this is a document and InternalLoad does not"
")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 10686
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "contentPolicyType == nsIContentPolicy::TYPE_DOCUMENT"
") (" "DoURILoad thinks this is a document and InternalLoad does not"
")"); do { MOZ_CrashSequence(__null, 10686); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10687 }
10688
10689 // We want to inherit aLoadState->PrincipalToInherit() when:
10690 // 1. ChannelShouldInheritPrincipal returns true.
10691 // 2. aLoadState->URI() is not data: URI, or data: URI is not
10692 // configured as unique opaque origin.
10693 bool inheritPrincipal = false;
10694
10695 nsCOMPtr<nsIURI> uri = aLoadState->URI();
10696 if (aLoadState->PrincipalToInherit()) {
10697 bool isSrcdoc =
10698 aLoadState->HasInternalLoadFlags(INTERNAL_LOAD_FLAGS_IS_SRCDOC);
10699 bool inheritAttrs = nsContentUtils::ChannelShouldInheritPrincipal(
10700 aLoadState->PrincipalToInherit(), uri,
10701 true, // aInheritForAboutBlank
10702 isSrcdoc);
10703
10704 inheritPrincipal = inheritAttrs && !uri->SchemeIs("data");
10705 }
10706
10707 // See https://bugzilla.mozilla.org/show_bug.cgi?id=1736570
10708 const bool isAboutBlankLoadOntoInitialAboutBlank =
10709 IsAboutBlankLoadOntoInitialAboutBlank(uri, inheritPrincipal,
10710 aLoadState->PrincipalToInherit());
10711
10712 // FIXME We still have a ton of codepaths that don't pass through
10713 // DocumentLoadListener, so probably need to create session history info
10714 // in more places.
10715 if (aLoadState->GetLoadingSessionHistoryInfo()) {
10716 SetLoadingSessionHistoryInfo(*aLoadState->GetLoadingSessionHistoryInfo());
10717 } else if (isAboutBlankLoadOntoInitialAboutBlank &&
10718 mozilla::SessionHistoryInParent()) {
10719 // Materialize LoadingSessionHistoryInfo here, because DocumentChannel
10720 // loads have it, and later history behavior depends on it existing.
10721 UniquePtr<SessionHistoryInfo> entry = MakeUnique<SessionHistoryInfo>(
10722 uri, aLoadState->TriggeringPrincipal(),
10723 aLoadState->PrincipalToInherit(),
10724 aLoadState->PartitionedPrincipalToInherit(), aLoadState->Csp(),
10725 mContentTypeHint);
10726 mozilla::dom::LoadingSessionHistoryInfo info(*entry);
10727 SetLoadingSessionHistoryInfo(info, true);
10728 }
10729
10730 // open a channel for the url
10731
10732 // If we have a pending channel, use the channel we've already created here.
10733 // We don't need to set up load flags for our channel, as it has already been
10734 // created.
10735
10736 if (nsCOMPtr<nsIChannel> channel =
10737 aLoadState->GetPendingRedirectedChannel()) {
10738 // If we have a request outparameter, shove our channel into it.
10739 if (aRequest) {
10740 nsCOMPtr<nsIRequest> outRequest = channel;
10741 outRequest.forget(aRequest);
10742 }
10743
10744 return OpenRedirectedChannel(aLoadState);
10745 }
10746
10747 // There are two cases we care about:
10748 // * Top-level load: In this case, loadingNode is null, but loadingWindow
10749 // is our mScriptGlobal. We pass null for loadingPrincipal in this case.
10750 // * Subframe load: loadingWindow is null, but loadingNode is the frame
10751 // element for the load. loadingPrincipal is the NodePrincipal of the
10752 // frame element.
10753 nsCOMPtr<nsINode> loadingNode;
10754 nsCOMPtr<nsPIDOMWindowOuter> loadingWindow;
10755 nsCOMPtr<nsIPrincipal> loadingPrincipal;
10756 nsCOMPtr<nsISupports> topLevelLoadingContext;
10757
10758 if (contentPolicyType == nsIContentPolicy::TYPE_DOCUMENT) {
10759 loadingNode = nullptr;
10760 loadingPrincipal = nullptr;
10761 loadingWindow = mScriptGlobal;
10762 if (XRE_IsContentProcess()) {
10763 // In e10s the child process doesn't have access to the element that
10764 // contains the browsing context (because that element is in the chrome
10765 // process).
10766 nsCOMPtr<nsIBrowserChild> browserChild = GetBrowserChild();
10767 topLevelLoadingContext = ToSupports(browserChild);
10768 } else {
10769 // This is for loading non-e10s tabs and toplevel windows of various
10770 // sorts.
10771 // For the toplevel window cases, requestingElement will be null.
10772 nsCOMPtr<Element> requestingElement =
10773 loadingWindow->GetFrameElementInternal();
10774 topLevelLoadingContext = requestingElement;
10775 }
10776 } else {
10777 loadingWindow = nullptr;
10778 loadingNode = mScriptGlobal->GetFrameElementInternal();
10779 if (loadingNode) {
10780 // If we have a loading node, then use that as our loadingPrincipal.
10781 loadingPrincipal = loadingNode->NodePrincipal();
10782#ifdef DEBUG1
10783 // Get the docshell type for requestingElement.
10784 RefPtr<Document> requestingDoc = loadingNode->OwnerDoc();
10785 nsCOMPtr<nsIDocShell> elementDocShell = requestingDoc->GetDocShell();
10786 // requestingElement docshell type = current docshell type.
10787 MOZ_ASSERT(do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mItemType == elementDocShell->ItemType())>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(mItemType == elementDocShell->ItemType()))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("mItemType == elementDocShell->ItemType()"
" (" "subframes should have the same docshell type as their parent"
")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 10789
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mItemType == elementDocShell->ItemType()"
") (" "subframes should have the same docshell type as their parent"
")"); do { MOZ_CrashSequence(__null, 10789); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
10788 mItemType == elementDocShell->ItemType(),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mItemType == elementDocShell->ItemType())>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(mItemType == elementDocShell->ItemType()))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("mItemType == elementDocShell->ItemType()"
" (" "subframes should have the same docshell type as their parent"
")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 10789
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mItemType == elementDocShell->ItemType()"
") (" "subframes should have the same docshell type as their parent"
")"); do { MOZ_CrashSequence(__null, 10789); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
10789 "subframes should have the same docshell type as their parent")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mItemType == elementDocShell->ItemType())>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(mItemType == elementDocShell->ItemType()))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("mItemType == elementDocShell->ItemType()"
" (" "subframes should have the same docshell type as their parent"
")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 10789
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mItemType == elementDocShell->ItemType()"
") (" "subframes should have the same docshell type as their parent"
")"); do { MOZ_CrashSequence(__null, 10789); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10790#endif
10791 } else {
10792 if (mIsBeingDestroyed) {
10793 // If this isn't a top-level load and mScriptGlobal's frame element is
10794 // null, then the element got removed from the DOM while we were trying
10795 // to load this resource. This docshell is scheduled for destruction
10796 // already, so bail out here.
10797 return NS_OK;
10798 }
10799 // If we are not being destroyed and we do not have access to the loading
10800 // node, then we are a remote subframe. Set the loading principal
10801 // to be a null principal and then set it correctly in the parent.
10802 loadingPrincipal = NullPrincipal::Create(GetOriginAttributes(), nullptr);
10803 }
10804 }
10805
10806 if (!aLoadState->TriggeringPrincipal()) {
10807 MOZ_ASSERT(false, "DoURILoad needs a valid triggeringPrincipal")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "DoURILoad needs a valid triggeringPrincipal"
")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 10807
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") (" "DoURILoad needs a valid triggeringPrincipal"
")"); do { MOZ_CrashSequence(__null, 10807); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10808 return NS_ERROR_FAILURE;
10809 }
10810
10811 uint32_t sandboxFlags = mBrowsingContext->GetSandboxFlags();
10812 nsSecurityFlags securityFlags =
10813 nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_SEC_CONTEXT_IS_NULL;
10814
10815 if (mLoadType == LOAD_ERROR_PAGE) {
10816 securityFlags |= nsILoadInfo::SEC_LOAD_ERROR_PAGE;
10817 }
10818
10819 if (inheritPrincipal) {
10820 securityFlags |= nsILoadInfo::SEC_FORCE_INHERIT_PRINCIPAL;
10821 }
10822
10823 // Must never have a parent for TYPE_DOCUMENT loads
10824 MOZ_ASSERT_IF(contentPolicyType == nsIContentPolicy::TYPE_DOCUMENT,do { if (contentPolicyType == nsIContentPolicy::TYPE_DOCUMENT
) { do { static_assert( mozilla::detail::AssertionConditionType
<decltype(!mBrowsingContext->GetParent())>::isValid,
"invalid assertion condition"); if ((__builtin_expect(!!(!(!
!(!mBrowsingContext->GetParent()))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("!mBrowsingContext->GetParent()"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 10825);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mBrowsingContext->GetParent()"
")"); do { MOZ_CrashSequence(__null, 10825); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false); } } while
(false)
10825 !mBrowsingContext->GetParent())do { if (contentPolicyType == nsIContentPolicy::TYPE_DOCUMENT
) { do { static_assert( mozilla::detail::AssertionConditionType
<decltype(!mBrowsingContext->GetParent())>::isValid,
"invalid assertion condition"); if ((__builtin_expect(!!(!(!
!(!mBrowsingContext->GetParent()))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("!mBrowsingContext->GetParent()"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 10825);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mBrowsingContext->GetParent()"
")"); do { MOZ_CrashSequence(__null, 10825); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false); } } while
(false)
;
10826 // Subdocuments must have a parent
10827 MOZ_ASSERT_IF(contentPolicyType == nsIContentPolicy::TYPE_SUBDOCUMENT,do { if (contentPolicyType == nsIContentPolicy::TYPE_SUBDOCUMENT
) { do { static_assert( mozilla::detail::AssertionConditionType
<decltype(mBrowsingContext->GetParent())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mBrowsingContext->GetParent
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("mBrowsingContext->GetParent()", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 10828); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mBrowsingContext->GetParent()"
")"); do { MOZ_CrashSequence(__null, 10828); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false); } } while
(false)
10828 mBrowsingContext->GetParent())do { if (contentPolicyType == nsIContentPolicy::TYPE_SUBDOCUMENT
) { do { static_assert( mozilla::detail::AssertionConditionType
<decltype(mBrowsingContext->GetParent())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mBrowsingContext->GetParent
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("mBrowsingContext->GetParent()", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 10828); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mBrowsingContext->GetParent()"
")"); do { MOZ_CrashSequence(__null, 10828); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false); } } while
(false)
;
10829 mBrowsingContext->SetTriggeringAndInheritPrincipals(
10830 aLoadState->TriggeringPrincipal(), aLoadState->PrincipalToInherit(),
10831 aLoadState->GetLoadIdentifier());
10832 RefPtr<LoadInfo> loadInfo;
10833 if (contentPolicyType == nsIContentPolicy::TYPE_DOCUMENT) {
10834 loadInfo =
10835 new LoadInfo(loadingWindow, uri, aLoadState->TriggeringPrincipal(),
10836 topLevelLoadingContext, securityFlags, sandboxFlags);
10837 } else {
10838 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(); })
10839 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(); })
10840 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(); })
10841 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(); })
;
10842 }
10843 RefPtr<WindowContext> context = mBrowsingContext->GetCurrentWindowContext();
10844
10845 if (isAboutBlankLoadOntoInitialAboutBlank) {
10846 // Match the DocumentChannel case where the default for third-partiness
10847 // differs from the default in LoadInfo construction here.
10848 // toolkit/components/antitracking/test/browser/browser_aboutblank.js
10849 // fails without this.
10850 BrowsingContext* top = mBrowsingContext->Top();
10851 if (top == mBrowsingContext) {
10852 // If we're at the top, this must be a window.open()ed
10853 // window, and we can't be third-party relative to ourselves.
10854 loadInfo->SetIsThirdPartyContextToTopWindow(false);
10855 } else {
10856 if (Document* topDoc = top->GetDocument()) {
10857 bool thirdParty = false;
10858 mozilla::Unused << topDoc->GetPrincipal()->IsThirdPartyPrincipal(
10859 aLoadState->PrincipalToInherit(), &thirdParty);
10860 loadInfo->SetIsThirdPartyContextToTopWindow(thirdParty);
10861 } else {
10862 // If top is in a different process, we have to be third-party relative
10863 // to it.
10864 loadInfo->SetIsThirdPartyContextToTopWindow(true);
10865 }
10866 }
10867 }
10868
10869 if (mLoadType != LOAD_ERROR_PAGE && context && context->IsInProcess()) {
10870 if (context->HasValidTransientUserGestureActivation()) {
10871 aLoadState->SetHasValidUserGestureActivation(true);
10872 aLoadState->SetTextDirectiveUserActivation(true);
10873 }
10874 if (!aLoadState->TriggeringWindowId()) {
10875 aLoadState->SetTriggeringWindowId(context->Id());
10876 }
10877 if (!aLoadState->TriggeringStorageAccess()) {
10878 Document* contextDoc = context->GetExtantDoc();
10879 if (contextDoc) {
10880 aLoadState->SetTriggeringStorageAccess(
10881 contextDoc->UsingStorageAccess());
10882 }
10883 }
10884 }
10885
10886 // in case this docshell load was triggered by a valid transient user gesture,
10887 // or also the load originates from external, then we pass that information on
10888 // to the loadinfo, which allows e.g. setting Sec-Fetch-User request headers.
10889 if (aLoadState->HasValidUserGestureActivation() ||
10890 aLoadState->HasLoadFlags(LOAD_FLAGS_FROM_EXTERNAL)) {
10891 loadInfo->SetHasValidUserGestureActivation(true);
10892 aLoadState->SetTextDirectiveUserActivation(true);
10893 }
10894
10895 loadInfo->SetTextDirectiveUserActivation(
10896 aLoadState->GetTextDirectiveUserActivation());
10897
10898 loadInfo->SetTriggeringWindowId(aLoadState->TriggeringWindowId());
10899 loadInfo->SetTriggeringStorageAccess(aLoadState->TriggeringStorageAccess());
10900 loadInfo->SetTriggeringSandboxFlags(aLoadState->TriggeringSandboxFlags());
10901 net::ClassificationFlags flags = aLoadState->TriggeringClassificationFlags();
10902 loadInfo->SetTriggeringFirstPartyClassificationFlags(flags.firstPartyFlags);
10903 loadInfo->SetTriggeringThirdPartyClassificationFlags(flags.thirdPartyFlags);
10904 loadInfo->SetIsMetaRefresh(aLoadState->IsMetaRefresh());
10905
10906 uint32_t cacheKey = 0;
10907 if (aCacheKey) {
10908 cacheKey = *aCacheKey;
10909 } else if (mozilla::SessionHistoryInParent()) {
10910 if (mLoadingEntry) {
10911 cacheKey = mLoadingEntry->mInfo.GetCacheKey();
10912 } else if (mActiveEntry) { // for reload cases
10913 cacheKey = mActiveEntry->GetCacheKey();
10914 }
10915 } else {
10916 if (mLSHE) {
10917 cacheKey = mLSHE->GetCacheKey();
10918 } else if (mOSHE) { // for reload cases
10919 cacheKey = mOSHE->GetCacheKey();
10920 }
10921 }
10922
10923 bool uriModified;
10924 if (mLSHE || mLoadingEntry) {
10925 if (mLoadingEntry) {
10926 uriModified = mLoadingEntry->mInfo.GetURIWasModified();
10927 } else {
10928 uriModified = mLSHE->GetURIWasModified();
10929 }
10930 } else {
10931 uriModified = false;
10932 }
10933
10934 bool isEmbeddingBlockedError = false;
10935 if (mFailedChannel) {
10936 nsresult status;
10937 mFailedChannel->GetStatus(&status);
10938 isEmbeddingBlockedError = status == NS_ERROR_XFO_VIOLATION ||
10939 status == NS_ERROR_CSP_FRAME_ANCESTOR_VIOLATION;
10940 }
10941
10942 nsLoadFlags loadFlags = aLoadState->CalculateChannelLoadFlags(
10943 mBrowsingContext, uriModified, Some(isEmbeddingBlockedError));
10944
10945 nsCOMPtr<nsIChannel> channel;
10946 if (DocumentChannel::CanUseDocumentChannel(uri) &&
10947 !isAboutBlankLoadOntoInitialAboutBlank) {
10948 channel = DocumentChannel::CreateForDocument(
10949 aLoadState, loadInfo, loadFlags, this, cacheKey, uriModified,
10950 isEmbeddingBlockedError);
10951 MOZ_ASSERT(channel)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(channel)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(channel))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("channel", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 10951); AnnotateMozCrashReason("MOZ_ASSERT" "(" "channel" ")"
); do { MOZ_CrashSequence(__null, 10951); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
10952
10953 // Disable keyword fixup when using DocumentChannel, since
10954 // DocumentLoadListener will handle this for us (in the parent process).
10955 mAllowKeywordFixup = false;
10956 } else if (!CreateAndConfigureRealChannelForLoadState(
10957 mBrowsingContext, aLoadState, loadInfo, this, this,
10958 GetOriginAttributes(), loadFlags, cacheKey, rv,
10959 getter_AddRefs(channel))) {
10960 return rv;
10961 }
10962
10963 // Make sure to give the caller a channel if we managed to create one
10964 // This is important for correct error page/session history interaction
10965 if (aRequest) {
10966 NS_ADDREF(*aRequest = channel)(*aRequest = channel)->AddRef();
10967 }
10968
10969 const nsACString& typeHint = aLoadState->TypeHint();
10970 if (!typeHint.IsVoid()) {
10971 mContentTypeHint = typeHint;
10972 } else {
10973 mContentTypeHint.Truncate();
10974 }
10975
10976 // Load attributes depend on load type...
10977 if (mLoadType == LOAD_RELOAD_CHARSET_CHANGE) {
10978 // Use SetAllowStaleCacheContent (not LOAD_FROM_CACHE flag) since we
10979 // only want to force cache load for this channel, not the whole
10980 // loadGroup.
10981 nsCOMPtr<nsICacheInfoChannel> cachingChannel = do_QueryInterface(channel);
10982 if (cachingChannel) {
10983 cachingChannel->SetAllowStaleCacheContent(true);
10984 }
10985 }
10986
10987 uint32_t openFlags =
10988 nsDocShell::ComputeURILoaderFlags(mBrowsingContext, mLoadType);
10989 return OpenInitializedChannel(channel, uriLoader, openFlags);
10990}
10991
10992static nsresult AppendSegmentToString(nsIInputStream* aIn, void* aClosure,
10993 const char* aFromRawSegment,
10994 uint32_t aToOffset, uint32_t aCount,
10995 uint32_t* aWriteCount) {
10996 // aFromSegment now contains aCount bytes of data.
10997
10998 nsAutoCString* buf = static_cast<nsAutoCString*>(aClosure);
10999 buf->Append(aFromRawSegment, aCount);
11000
11001 // Indicate that we have consumed all of aFromSegment
11002 *aWriteCount = aCount;
11003 return NS_OK;
11004}
11005
11006/* static */ nsresult nsDocShell::AddHeadersToChannel(
11007 nsIInputStream* aHeadersData, nsIChannel* aGenericChannel) {
11008 nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(aGenericChannel);
11009 NS_ENSURE_STATE(httpChannel)do { if ((__builtin_expect(!!(!(httpChannel)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "httpChannel" ") failed"
, nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 11009); return NS_ERROR_UNEXPECTED; } } while (false)
;
11010
11011 uint32_t numRead;
11012 nsAutoCString headersString;
11013 nsresult rv = aHeadersData->ReadSegments(
11014 AppendSegmentToString, &headersString, UINT32_MAX(4294967295U), &numRead);
11015 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 11015); return rv; } } while (false)
;
11016
11017 // used during the manipulation of the String from the InputStream
11018 nsAutoCString headerName;
11019 nsAutoCString headerValue;
11020 int32_t crlf;
11021 int32_t colon;
11022
11023 //
11024 // Iterate over the headersString: for each "\r\n" delimited chunk,
11025 // add the value as a header to the nsIHttpChannel
11026 //
11027
11028 static const char kWhitespace[] = "\b\t\r\n ";
11029 while (true) {
11030 crlf = headersString.Find("\r\n");
11031 if (crlf == kNotFound) {
11032 return NS_OK;
11033 }
11034
11035 const nsACString& oneHeader = StringHead(headersString, crlf);
11036
11037 colon = oneHeader.FindChar(':');
11038 if (colon == kNotFound) {
11039 return NS_ERROR_UNEXPECTED;
11040 }
11041
11042 headerName = StringHead(oneHeader, colon);
11043 headerValue = Substring(oneHeader, colon + 1);
11044
11045 headerName.Trim(kWhitespace);
11046 headerValue.Trim(kWhitespace);
11047
11048 headersString.Cut(0, crlf + 2);
11049
11050 //
11051 // FINALLY: we can set the header!
11052 //
11053
11054 rv = httpChannel->SetRequestHeader(headerName, headerValue, true);
11055 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 11055); return rv; } } while (false)
;
11056 }
11057
11058 MOZ_ASSERT_UNREACHABLE("oops")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "MOZ_ASSERT_UNREACHABLE: "
"oops" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 11058); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "oops" ")"); do { MOZ_CrashSequence
(__null, 11058); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
11059 return NS_ERROR_UNEXPECTED;
11060}
11061
11062/* static */ uint32_t nsDocShell::ComputeURILoaderFlags(
11063 BrowsingContext* aBrowsingContext, uint32_t aLoadType,
11064 bool aIsDocumentLoad) {
11065 MOZ_ASSERT(aBrowsingContext)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aBrowsingContext)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aBrowsingContext))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("aBrowsingContext"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 11065);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "aBrowsingContext" ")"
); do { MOZ_CrashSequence(__null, 11065); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
11066
11067 uint32_t openFlags = 0;
11068 if (aLoadType == LOAD_LINK) {
11069 openFlags |= nsIURILoader::IS_CONTENT_PREFERRED;
11070 }
11071 if (!aBrowsingContext->GetAllowContentRetargeting()) {
11072 openFlags |= nsIURILoader::DONT_RETARGET;
11073 }
11074
11075 if (!aIsDocumentLoad) {
11076 openFlags |= nsIURILoader::IS_OBJECT_EMBED;
11077
11078 // Unless the pref is set, object/embed loads always specify DONT_RETARGET.
11079 // See bug 1868001 for details.
11080 if (!StaticPrefs::dom_navigation_object_embed_allow_retargeting()) {
11081 openFlags |= nsIURILoader::DONT_RETARGET;
11082 }
11083 }
11084
11085 return openFlags;
11086}
11087
11088nsresult nsDocShell::OpenInitializedChannel(nsIChannel* aChannel,
11089 nsIURILoader* aURILoader,
11090 uint32_t aOpenFlags) {
11091 nsresult rv = NS_OK;
11092
11093 // If anything fails here, make sure to clear our initial ClientSource.
11094 auto cleanupInitialClient =
11095 MakeScopeExit([&] { mInitialClientSource.reset(); });
11096
11097 nsCOMPtr<nsPIDOMWindowOuter> win = GetWindow();
11098 NS_ENSURE_TRUE(win, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(win)), 0))) { NS_DebugBreak(NS_DEBUG_WARNING
, "NS_ENSURE_TRUE(" "win" ") failed", nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 11098); return NS_ERROR_FAILURE; } } while (false)
;
11099
11100 MaybeCreateInitialClientSource();
11101
11102 // Let the client channel helper know if we are using DocumentChannel,
11103 // since redirects get handled in the parent process in that case.
11104 RefPtr<net::DocumentChannel> docChannel = do_QueryObject(aChannel);
11105 if (docChannel && XRE_IsContentProcess()) {
11106 // Tell the content process nsDocumentOpenInfo to not try to do
11107 // any sort of targeting.
11108 aOpenFlags |= nsIURILoader::DONT_RETARGET;
11109 }
11110
11111 // Since we are loading a document we need to make sure the proper reserved
11112 // and initial client data is stored on the nsILoadInfo. The
11113 // ClientChannelHelper does this and ensures that it is propagated properly
11114 // on redirects. We pass no reserved client here so that the helper will
11115 // create the reserved ClientSource if necessary.
11116 Maybe<ClientInfo> noReservedClient;
11117 if (docChannel) {
11118 // When using DocumentChannel, all redirect handling is done in the parent,
11119 // so we just need the child variant to watch for the internal redirect
11120 // to the final channel.
11121 rv = AddClientChannelHelperInChild(aChannel,
11122 GetMainThreadSerialEventTarget());
11123 docChannel->SetInitialClientInfo(GetInitialClientInfo());
11124 } else {
11125 rv = AddClientChannelHelper(aChannel, std::move(noReservedClient),
11126 GetInitialClientInfo(),
11127 GetMainThreadSerialEventTarget());
11128 }
11129 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 11129); return rv; } } while (false)
;
11130
11131 rv = aURILoader->OpenURI(aChannel, aOpenFlags, this);
11132 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 11132); return rv; } } while (false)
;
11133
11134 // We're about to load a new page and it may take time before necko
11135 // gives back any data, so main thread might have a chance to process a
11136 // collector slice
11137 nsJSContext::MaybeRunNextCollectorSlice(this, JS::GCReason::DOCSHELL);
11138
11139 // Success. Keep the initial ClientSource if it exists.
11140 cleanupInitialClient.release();
11141
11142 return NS_OK;
11143}
11144
11145nsresult nsDocShell::OpenRedirectedChannel(nsDocShellLoadState* aLoadState) {
11146 nsCOMPtr<nsIChannel> channel = aLoadState->GetPendingRedirectedChannel();
11147 MOZ_ASSERT(channel)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(channel)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(channel))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("channel", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 11147); AnnotateMozCrashReason("MOZ_ASSERT" "(" "channel" ")"
); do { MOZ_CrashSequence(__null, 11147); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
11148
11149 // If anything fails here, make sure to clear our initial ClientSource.
11150 auto cleanupInitialClient =
11151 MakeScopeExit([&] { mInitialClientSource.reset(); });
11152
11153 nsCOMPtr<nsPIDOMWindowOuter> win = GetWindow();
11154 NS_ENSURE_TRUE(win, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(win)), 0))) { NS_DebugBreak(NS_DEBUG_WARNING
, "NS_ENSURE_TRUE(" "win" ") failed", nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 11154); return NS_ERROR_FAILURE; } } while (false)
;
11155
11156 MaybeCreateInitialClientSource();
11157
11158 nsCOMPtr<nsILoadInfo> loadInfo = channel->LoadInfo();
11159
11160 LoadInfo* li = static_cast<LoadInfo*>(loadInfo.get());
11161 if (loadInfo->GetExternalContentPolicyType() ==
11162 ExtContentPolicy::TYPE_DOCUMENT) {
11163 li->UpdateBrowsingContextID(mBrowsingContext->Id());
11164 } else if (loadInfo->GetExternalContentPolicyType() ==
11165 ExtContentPolicy::TYPE_SUBDOCUMENT) {
11166 li->UpdateFrameBrowsingContextID(mBrowsingContext->Id());
11167 }
11168
11169 // If we did a process switch, then we should have an existing allocated
11170 // ClientInfo, so we just need to allocate a corresponding ClientSource.
11171 CreateReservedSourceIfNeeded(channel, GetMainThreadSerialEventTarget());
11172
11173 uint32_t documentOpenInfoFlags = nsIURILoader::DONT_RETARGET;
11174 if (loadInfo->GetExternalContentPolicyType() ==
11175 ExtContentPolicy::TYPE_OBJECT) {
11176 documentOpenInfoFlags |= nsIURILoader::IS_OBJECT_EMBED;
11177 }
11178
11179 RefPtr<nsDocumentOpenInfo> loader =
11180 new nsDocumentOpenInfo(this, documentOpenInfoFlags, nullptr);
11181 channel->SetLoadGroup(mLoadGroup);
11182
11183 MOZ_ALWAYS_SUCCEEDS(loader->Prepare())do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(loader->Prepare())), 1)))), 1))) { } else { do { do { } while
(false); MOZ_ReportCrash("" "NS_SUCCEEDED(loader->Prepare())"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 11183);
AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED(loader->Prepare())"
")"); do { MOZ_CrashSequence(__null, 11183); __attribute__((
nomerge)) ::abort(); } while (false); } while (false); } } while
(false)
;
11184
11185 nsresult rv = NS_OK;
11186 if (XRE_IsParentProcess()) {
11187 // If we're in the parent, the we don't have an nsIChildChannel, just
11188 // the original channel, which is already open in this process.
11189
11190 // DocumentLoadListener expects to get an nsIParentChannel, so
11191 // we create a wrapper around the channel and nsIStreamListener
11192 // that forwards functionality as needed, and then we register
11193 // it under the provided identifier.
11194 RefPtr<ParentChannelWrapper> wrapper =
11195 new ParentChannelWrapper(channel, loader);
11196 wrapper->Register(aLoadState->GetPendingRedirectChannelRegistrarId());
11197
11198 mLoadGroup->AddRequest(channel, nullptr);
11199 } else if (nsCOMPtr<nsIChildChannel> childChannel =
11200 do_QueryInterface(channel)) {
11201 // Our channel was redirected from another process, so doesn't need to
11202 // be opened again. However, it does need its listener hooked up
11203 // correctly.
11204 rv = childChannel->CompleteRedirectSetup(loader);
11205 } else {
11206 // It's possible for the redirected channel to not implement
11207 // nsIChildChannel and be entirely local (like srcdoc). In that case we
11208 // can just open the local instance and it will work.
11209 rv = channel->AsyncOpen(loader);
11210 }
11211 if (rv == NS_ERROR_NO_CONTENT) {
11212 return NS_OK;
11213 }
11214 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 11214); return rv; } } while (false)
;
11215
11216 // Success. Keep the initial ClientSource if it exists.
11217 cleanupInitialClient.release();
11218 return NS_OK;
11219}
11220
11221// https://html.spec.whatwg.org/#scrolling-to-a-fragment
11222nsresult nsDocShell::ScrollToAnchor(bool aCurHasRef, bool aNewHasRef,
11223 nsACString& aNewHash, uint32_t aLoadType) {
11224 if (!mCurrentURI) {
11225 return NS_OK;
11226 }
11227
11228 RefPtr<PresShell> presShell = GetPresShell();
11229 if (!presShell) {
11230 // If we failed to get the shell, or if there is no shell,
11231 // nothing left to do here.
11232 return NS_OK;
11233 }
11234
11235 ScrollContainerFrame* rootScroll = presShell->GetRootScrollContainerFrame();
11236 if (rootScroll) {
11237 rootScroll->ClearDidHistoryRestore();
11238 }
11239
11240 // If it's a load from history, we don't have any anchor jumping to do.
11241 // Scrollbar position will be restored by the caller based on positions stored
11242 // in session history.
11243 bool scroll = aLoadType != LOAD_HISTORY && aLoadType != LOAD_RELOAD_NORMAL;
11244 // If the load contains text directives, try to apply them. This may fail if
11245 // the load is a same-document load that was initiated before the document was
11246 // fully loaded and the target is not yet included in the DOM tree.
11247 // For this case, the `uninvokedTextDirectives` are not cleared, so that
11248 // `Document::ScrollToRef()` can re-apply the text directive.
11249 // `Document::ScrollToRef()` is (presumably) the second "async" call mentioned
11250 // in sec. 7.4.2.3.3 in the HTML spec, "Fragment navigations":
11251 // https://html.spec.whatwg.org/#scroll-to-fragid:~:text=This%20algorithm%20will%20be%20called%20twice
11252
11253 const RefPtr fragmentDirective = GetDocument()->FragmentDirective();
11254 const nsTArray<RefPtr<nsRange>> textDirectiveRanges =
11255 fragmentDirective->FindTextFragmentsInDocument();
11256 fragmentDirective->HighlightTextDirectives(textDirectiveRanges);
11257 const bool scrollToTextDirective =
11258 !textDirectiveRanges.IsEmpty() &&
11259 fragmentDirective->IsTextDirectiveAllowedToBeScrolledTo();
11260 const RefPtr<nsRange> textDirectiveToScroll =
11261 scrollToTextDirective ? textDirectiveRanges[0] : nullptr;
11262
11263 // If we have no new anchor, we do not want to scroll, unless there is a
11264 // current anchor and we are doing a history load. So return if we have no
11265 // new anchor, and there is no current anchor or the load is not a history
11266 // load.
11267 if ((!aCurHasRef || aLoadType != LOAD_HISTORY) && !aNewHasRef &&
11268 !scrollToTextDirective) {
11269 return NS_OK;
11270 }
11271
11272 // Both the new and current URIs refer to the same page. We can now
11273 // browse to the hash stored in the new URI.
11274
11275 if (aNewHash.IsEmpty() && !scrollToTextDirective) {
11276 // 2. If fragment is the empty string, then return the special value top of
11277 // the document.
11278 //
11279 // Tell the shell it's at an anchor without scrolling.
11280 presShell->GoToAnchor(u""_ns, nullptr, false);
11281
11282 if (scroll) {
11283 // Scroll to the top of the page. Ignore the return value; failure to
11284 // scroll here (e.g. if there is no root scrollframe) is not grounds for
11285 // canceling the load!
11286 SetCurScrollPosEx(0, 0);
11287 }
11288
11289 return NS_OK;
11290 }
11291
11292 // 3. Let potentialIndicatedElement be the result of finding a potential
11293 // indicated element given document and fragment.
11294 NS_ConvertUTF8toUTF16 uStr(aNewHash);
11295
11296 MOZ_ASSERT(!uStr.IsEmpty() || scrollToTextDirective)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!uStr.IsEmpty() || scrollToTextDirective)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(!uStr.IsEmpty() || scrollToTextDirective))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("!uStr.IsEmpty() || scrollToTextDirective"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 11296);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "!uStr.IsEmpty() || scrollToTextDirective"
")"); do { MOZ_CrashSequence(__null, 11296); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11297
11298 auto rv = presShell->GoToAnchor(uStr, textDirectiveToScroll, scroll,
11299 ScrollFlags::ScrollSmoothAuto);
11300
11301 // 4. If potentialIndicatedElement is not null, then return
11302 // potentialIndicatedElement.
11303 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
11304 return NS_OK;
11305 }
11306
11307 // 5. Let fragmentBytes be the result of percent-decoding fragment.
11308 nsAutoCString fragmentBytes;
11309 const bool unescaped = NS_UnescapeURL(aNewHash.Data(), aNewHash.Length(),
11310 /* aFlags = */ 0, fragmentBytes);
11311
11312 if (!unescaped) {
11313 // Another attempt is only necessary if characters were unescaped.
11314 return NS_OK;
11315 }
11316
11317 if (fragmentBytes.IsEmpty()) {
11318 // When aNewHash contains "%00", the unescaped string may be empty, and
11319 // GoToAnchor asserts if we ask it to scroll to an empty ref.
11320 presShell->GoToAnchor(u""_ns, nullptr, false);
11321 return NS_OK;
11322 }
11323
11324 // 6. Let decodedFragment be the result of running UTF-8 decode without BOM on
11325 // fragmentBytes.
11326 nsAutoString decodedFragment;
11327 rv = UTF_8_ENCODING->DecodeWithoutBOMHandling(fragmentBytes, decodedFragment);
11328 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 11328); return rv; } } while (false)
;
11329
11330 // 7. Set potentialIndicatedElement to the result of finding a potential
11331 // indicated element given document and decodedFragment.
11332 //
11333 // Ignore the return value of GoToAnchor, since it will return an error if
11334 // there is no such anchor in the document, which is actually a success
11335 // condition for us (we want to update the session history with the new URI no
11336 // matter whether we actually scrolled somewhere).
11337 presShell->GoToAnchor(decodedFragment, nullptr, scroll,
11338 ScrollFlags::ScrollSmoothAuto);
11339
11340 return NS_OK;
11341}
11342
11343bool nsDocShell::OnNewURI(nsIURI* aURI, nsIChannel* aChannel,
11344 nsIPrincipal* aTriggeringPrincipal,
11345 nsIPrincipal* aPrincipalToInherit,
11346 nsIPrincipal* aPartitionedPrincipalToInherit,
11347 nsIContentSecurityPolicy* aCsp,
11348 bool aAddToGlobalHistory, bool aCloneSHChildren) {
11349 MOZ_ASSERT(aURI, "uri is null")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aURI)>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(aURI))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("aURI" " (" "uri is null" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 11349); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aURI" ") ("
"uri is null" ")"); do { MOZ_CrashSequence(__null, 11349); __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
;
11350 MOZ_ASSERT(!aChannel || !aTriggeringPrincipal, "Shouldn't have both set")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aChannel || !aTriggeringPrincipal)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!aChannel || !aTriggeringPrincipal
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"!aChannel || !aTriggeringPrincipal" " (" "Shouldn't have both set"
")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 11350
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aChannel || !aTriggeringPrincipal"
") (" "Shouldn't have both set" ")"); do { MOZ_CrashSequence
(__null, 11350); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
11351
11352 MOZ_ASSERT(!aPrincipalToInherit ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aPrincipalToInherit || (aPrincipalToInherit &&
aTriggeringPrincipal))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!aPrincipalToInherit || (aPrincipalToInherit
&& aTriggeringPrincipal)))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("!aPrincipalToInherit || (aPrincipalToInherit && aTriggeringPrincipal)"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 11353);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aPrincipalToInherit || (aPrincipalToInherit && aTriggeringPrincipal)"
")"); do { MOZ_CrashSequence(__null, 11353); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
11353 (aPrincipalToInherit && aTriggeringPrincipal))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aPrincipalToInherit || (aPrincipalToInherit &&
aTriggeringPrincipal))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!aPrincipalToInherit || (aPrincipalToInherit
&& aTriggeringPrincipal)))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("!aPrincipalToInherit || (aPrincipalToInherit && aTriggeringPrincipal)"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 11353);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aPrincipalToInherit || (aPrincipalToInherit && aTriggeringPrincipal)"
")"); do { MOZ_CrashSequence(__null, 11353); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11354
11355#if defined(DEBUG1)
11356 if (MOZ_LOG_TEST(gDocShellLog, LogLevel::Debug)(__builtin_expect(!!(mozilla::detail::log_test(gDocShellLog, LogLevel
::Debug)), 0))
) {
11357 nsAutoCString chanName;
11358 if (aChannel) {
11359 aChannel->GetName(chanName);
11360 } else {
11361 chanName.AssignLiteral("<no channel>");
11362 }
11363
11364 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)
11365 ("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)
11366 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)
;
11367 }
11368#endif
11369
11370 bool equalUri = false;
11371
11372 // Get the post data and the HTTP response code from the channel.
11373 uint32_t responseStatus = 0;
11374 nsCOMPtr<nsIInputStream> inputStream;
11375 if (aChannel) {
11376 nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(aChannel));
11377
11378 // Check if the HTTPChannel is hiding under a multiPartChannel
11379 if (!httpChannel) {
11380 GetHttpChannel(aChannel, getter_AddRefs(httpChannel));
11381 }
11382
11383 if (httpChannel) {
11384 nsCOMPtr<nsIUploadChannel> uploadChannel(do_QueryInterface(httpChannel));
11385 if (uploadChannel) {
11386 uploadChannel->GetUploadStream(getter_AddRefs(inputStream));
11387 }
11388
11389 // If the response status indicates an error, unlink this session
11390 // history entry from any entries sharing its document.
11391 nsresult rv = httpChannel->GetResponseStatus(&responseStatus);
11392 if (mLSHE && NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && responseStatus >= 400) {
11393 mLSHE->AbandonBFCacheEntry();
11394 // FIXME Do the same for mLoadingEntry
11395 }
11396 }
11397 }
11398
11399 // Determine if this type of load should update history.
11400 bool updateGHistory = ShouldUpdateGlobalHistory(mLoadType);
11401
11402 // We don't update session history on reload unless we're loading
11403 // an iframe in shift-reload case.
11404 bool updateSHistory = mBrowsingContext->ShouldUpdateSessionHistory(mLoadType);
11405
11406 // Create SH Entry (mLSHE) only if there is a SessionHistory object in the
11407 // root browsing context.
11408 // FIXME If session history in the parent is enabled then we only do this if
11409 // the session history object is in process, otherwise we can't really
11410 // use the mLSHE anyway. Once session history is only stored in the
11411 // parent then this code will probably be removed anyway.
11412 RefPtr<ChildSHistory> rootSH = GetRootSessionHistory();
11413 if (!rootSH) {
11414 updateSHistory = false;
11415 updateGHistory = false; // XXX Why global history too?
11416 }
11417
11418 // Check if the url to be loaded is the same as the one already loaded.
11419 if (mCurrentURI) {
11420 aURI->Equals(mCurrentURI, &equalUri);
11421 }
11422
11423#ifdef DEBUG1
11424 bool shAvailable = (rootSH != nullptr);
11425
11426 // XXX This log message is almost useless because |updateSHistory|
11427 // and |updateGHistory| are not correct at this point.
11428
11429 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)
11430 (" 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)
11431 " 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)
11432 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)
;
11433#endif
11434
11435 /* If the url to be loaded is the same as the one already there,
11436 * and the original loadType is LOAD_NORMAL, LOAD_LINK, or
11437 * LOAD_STOP_CONTENT, set loadType to LOAD_NORMAL_REPLACE so that
11438 * AddToSessionHistory() won't mess with the current SHEntry and
11439 * if this page has any frame children, it also will be handled
11440 * properly. see bug 83684
11441 *
11442 * NB: If mOSHE is null but we have a current URI, then it probably
11443 * means that we must be at the transient about:blank content viewer;
11444 * we should let the normal load continue, since there's nothing to
11445 * replace. Sometimes this happens after a session restore (eg process
11446 * switch) and mCurrentURI is not about:blank; we assume we can let the load
11447 * continue (Bug 1301399).
11448 *
11449 * XXX Hopefully changing the loadType at this time will not hurt
11450 * anywhere. The other way to take care of sequentially repeating
11451 * frameset pages is to add new methods to nsIDocShellTreeItem.
11452 * Hopefully I don't have to do that.
11453 */
11454 if (equalUri &&
11455 (mozilla::SessionHistoryInParent() ? !!mActiveEntry : !!mOSHE) &&
11456 (mLoadType == LOAD_NORMAL || mLoadType == LOAD_LINK ||
11457 mLoadType == LOAD_STOP_CONTENT) &&
11458 !inputStream) {
11459 mLoadType = LOAD_NORMAL_REPLACE;
11460 }
11461
11462 // If this is a refresh to the currently loaded url, we don't
11463 // have to update session or global history.
11464 if (mLoadType == LOAD_REFRESH && !inputStream && equalUri) {
11465 SetHistoryEntryAndUpdateBC(Some<nsISHEntry*>(mOSHE), Nothing());
11466 }
11467
11468 /* If the user pressed shift-reload, cache will create a new cache key
11469 * for the page. Save the new cacheKey in Session History.
11470 * see bug 90098
11471 */
11472 if (aChannel && IsForceReloadType(mLoadType)) {
11473 MOZ_ASSERT(!updateSHistory || IsSubframe(),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!updateSHistory || IsSubframe())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!updateSHistory || IsSubframe
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!updateSHistory || IsSubframe()" " (" "We shouldn't be updating session history for forced"
" reloads unless we're in a newly created iframe!" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 11475); 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, 11475); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
11474 "We shouldn't be updating session history for forced"do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!updateSHistory || IsSubframe())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!updateSHistory || IsSubframe
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!updateSHistory || IsSubframe()" " (" "We shouldn't be updating session history for forced"
" reloads unless we're in a newly created iframe!" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 11475); 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, 11475); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
11475 " reloads unless we're in a newly created iframe!")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!updateSHistory || IsSubframe())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!updateSHistory || IsSubframe
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!updateSHistory || IsSubframe()" " (" "We shouldn't be updating session history for forced"
" reloads unless we're in a newly created iframe!" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 11475); 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, 11475); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11476
11477 nsCOMPtr<nsICacheInfoChannel> cacheChannel(do_QueryInterface(aChannel));
11478 uint32_t cacheKey = 0;
11479 // Get the Cache Key and store it in SH.
11480 if (cacheChannel) {
11481 cacheChannel->GetCacheKey(&cacheKey);
11482 }
11483 // If we already have a loading history entry, store the new cache key
11484 // in it. Otherwise, since we're doing a reload and won't be updating
11485 // our history entry, store the cache key in our current history entry.
11486 SetCacheKeyOnHistoryEntry(mLSHE ? mLSHE : mOSHE, cacheKey);
11487
11488 if (!mozilla::SessionHistoryInParent()) {
11489 // Since we're force-reloading, clear all the sub frame history.
11490 ClearFrameHistory(mLSHE);
11491 ClearFrameHistory(mOSHE);
11492 }
11493 }
11494
11495 if (!mozilla::SessionHistoryInParent()) {
11496 // Clear subframe history on refresh.
11497 // XXX: history.go(0) won't go this path as mLoadType is LOAD_HISTORY in
11498 // this case. One should re-validate after bug 1331865 fixed.
11499 if (mLoadType == LOAD_REFRESH) {
11500 ClearFrameHistory(mLSHE);
11501 ClearFrameHistory(mOSHE);
11502 }
11503
11504 if (updateSHistory) {
11505 // Update session history if necessary...
11506 if (!mLSHE && (mItemType == typeContent) && mURIResultedInDocument) {
11507 /* This is a fresh page getting loaded for the first time
11508 *.Create a Entry for it and add it to SH, if this is the
11509 * rootDocShell
11510 */
11511 (void)AddToSessionHistory(aURI, aChannel, aTriggeringPrincipal,
11512 aPrincipalToInherit,
11513 aPartitionedPrincipalToInherit, aCsp,
11514 aCloneSHChildren, getter_AddRefs(mLSHE));
11515 }
11516 } else if (GetSessionHistory() && mLSHE && mURIResultedInDocument) {
11517 // Even if we don't add anything to SHistory, ensure the current index
11518 // points to the same SHEntry as our mLSHE.
11519
11520 GetSessionHistory()->LegacySHistory()->EnsureCorrectEntryAtCurrIndex(
11521 mLSHE);
11522 }
11523 }
11524
11525 // If this is a POST request, we do not want to include this in global
11526 // history.
11527 if (ShouldAddURIVisit(aChannel) && updateGHistory && aAddToGlobalHistory &&
11528 !net::ChannelIsPost(aChannel)) {
11529 nsCOMPtr<nsIURI> previousURI;
11530 uint32_t previousFlags = 0;
11531
11532 if (mLoadType & LOAD_CMD_RELOAD) {
11533 // On a reload request, we don't set redirecting flags.
11534 previousURI = aURI;
11535 } else {
11536 ExtractLastVisit(aChannel, getter_AddRefs(previousURI), &previousFlags);
11537 }
11538
11539 AddURIVisit(aURI, previousURI, previousFlags, responseStatus);
11540 }
11541
11542 // If this was a history load or a refresh, or it was a history load but
11543 // later changed to LOAD_NORMAL_REPLACE due to redirection, update the index
11544 // in session history.
11545 if (!mozilla::SessionHistoryInParent() && rootSH &&
11546 ((mLoadType & (LOAD_CMD_HISTORY | LOAD_CMD_RELOAD)) ||
11547 mLoadType == LOAD_NORMAL_REPLACE || mLoadType == LOAD_REFRESH_REPLACE)) {
11548 mPreviousEntryIndex = rootSH->Index();
11549 if (!mozilla::SessionHistoryInParent()) {
11550 rootSH->LegacySHistory()->UpdateIndex();
11551 }
11552 mLoadedEntryIndex = rootSH->Index();
11553 MOZ_LOG(gPageCacheLog, LogLevel::Verbose,do { const ::mozilla::LogModule* moz_real_module = gPageCacheLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Verbose)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Verbose, "Previous index: %d, Loaded index: %d", mPreviousEntryIndex
, mLoadedEntryIndex); } } while (0)
11554 ("Previous index: %d, Loaded index: %d", mPreviousEntryIndex,do { const ::mozilla::LogModule* moz_real_module = gPageCacheLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Verbose)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Verbose, "Previous index: %d, Loaded index: %d", mPreviousEntryIndex
, mLoadedEntryIndex); } } while (0)
11555 mLoadedEntryIndex))do { const ::mozilla::LogModule* moz_real_module = gPageCacheLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Verbose)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Verbose, "Previous index: %d, Loaded index: %d", mPreviousEntryIndex
, mLoadedEntryIndex); } } while (0)
;
11556 }
11557
11558 // aCloneSHChildren exactly means "we are not loading a new document".
11559 uint32_t locationFlags =
11560 aCloneSHChildren ? uint32_t(LOCATION_CHANGE_SAME_DOCUMENT) : 0;
11561
11562 bool onLocationChangeNeeded =
11563 SetCurrentURI(aURI, aChannel, false,
11564 /* aIsInitialAboutBlank */ false, locationFlags);
11565 // Make sure to store the referrer from the channel, if any
11566 nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(aChannel));
11567 if (httpChannel) {
11568 mReferrerInfo = httpChannel->GetReferrerInfo();
11569 }
11570 return onLocationChangeNeeded;
11571}
11572
11573Maybe<Wireframe> nsDocShell::GetWireframe() {
11574 const bool collectWireFrame =
11575 mozilla::SessionHistoryInParent() &&
11576 StaticPrefs::browser_history_collectWireframes() &&
11577 mBrowsingContext->IsTopContent() && mActiveEntry;
11578
11579 if (!collectWireFrame) {
11580 return Nothing();
11581 }
11582
11583 RefPtr<Document> doc = mDocumentViewer->GetDocument();
11584 Nullable<Wireframe> wireframe;
11585 doc->GetWireframeWithoutFlushing(false, wireframe);
11586 if (wireframe.IsNull()) {
11587 return Nothing();
11588 }
11589 return Some(wireframe.Value());
11590}
11591
11592bool nsDocShell::CollectWireframe() {
11593 Maybe<Wireframe> wireframe = GetWireframe();
11594 if (wireframe.isNothing()) {
11595 return false;
11596 }
11597
11598 if (XRE_IsParentProcess()) {
11599 SessionHistoryEntry* entry =
11600 mBrowsingContext->Canonical()->GetActiveSessionHistoryEntry();
11601 if (entry) {
11602 entry->SetWireframe(wireframe);
11603 }
11604 } else {
11605 mozilla::Unused
11606 << ContentChild::GetSingleton()->SendSessionHistoryEntryWireframe(
11607 mBrowsingContext, wireframe.ref());
11608 }
11609
11610 return true;
11611}
11612
11613//*****************************************************************************
11614// nsDocShell: Session History
11615//*****************************************************************************
11616
11617NS_IMETHODIMPnsresult
11618nsDocShell::AddState(JS::Handle<JS::Value> aData, const nsAString& aTitle,
11619 const nsAString& aURL, bool aReplace, JSContext* aCx) {
11620 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)
11621 ("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)
11622 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)
11623 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)
;
11624 // Implements History.pushState and History.replaceState
11625
11626 // Here's what we do, roughly in the order specified by HTML5. The specific
11627 // steps we are executing are at
11628 // <https://html.spec.whatwg.org/multipage/history.html#dom-history-pushstate>,
11629 // <https://html.spec.whatwg.org/#shared-history-push/replace-state-steps>,
11630 // and
11631 // <https://html.spec.whatwg.org/multipage/history.html#url-and-history-update-steps>.
11632 // This function basically implements #dom-history-pushstate and
11633 // UpdateURLAndHistory implements #url-and-history-update-steps.
11634 //
11635 // A. Serialize aData using structured clone. This is #dom-history-pushstate
11636 // step 5.
11637 // B. If the third argument is present, #dom-history-pushstate step 7.
11638 // 7.1. Resolve the url, relative to our document.
11639 // 7.2. If (a) fails, raise a SECURITY_ERR
11640 // 7.4. Compare the resulting absolute URL to the document's address. If
11641 // any part of the URLs difer other than the <path>, <query>, and
11642 // <fragment> components, raise a SECURITY_ERR and abort.
11643 // C. If !aReplace, #url-and-history-update-steps steps 2.1-2.3:
11644 // Remove from the session history all entries after the current entry,
11645 // as we would after a regular navigation, and save the current
11646 // entry's scroll position (bug 590573).
11647 // D. #url-and-history-update-steps step 2.4 or step 3. As apropriate,
11648 // either add a state object entry to the session history after the
11649 // current entry with the following properties, or modify the current
11650 // session history entry to set
11651 // a. cloned data as the state object,
11652 // b. if the third argument was present, the absolute URL found in
11653 // step 2
11654 // Also clear the new history entry's POST data (see bug 580069).
11655 // E. If aReplace is false (i.e. we're doing a pushState instead of a
11656 // replaceState), notify bfcache that we've navigated to a new page.
11657 // F. If the third argument is present, set the document's current address
11658 // to the absolute URL found in step B. This is
11659 // #url-and-history-update-steps step 4.
11660 //
11661 // It's important that this function not run arbitrary scripts after step A
11662 // and before completing step E. For example, if a script called
11663 // history.back() before we completed step E, bfcache might destroy an
11664 // active content viewer. Since EvictOutOfRangeDocumentViewers at the end of
11665 // step E might run script, we can't just put a script blocker around the
11666 // critical section.
11667 //
11668 // Note that we completely ignore the aTitle parameter.
11669
11670 nsresult rv;
11671
11672 RefPtr<Document> document = GetDocument();
11673 NS_ENSURE_TRUE(document, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(document)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "document" ") failed", nullptr
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 11673);
return NS_ERROR_FAILURE; } } while (false)
;
11674
11675 // Don't clobber the load type of an existing network load.
11676 Maybe<AutoRestore<uint32_t>> loadTypeResetter;
11677 if (StaticPrefs::
11678 docshell_shistory_sameDocumentNavigationOverridesLoadType() &&
11679 !document->NodePrincipal()->IsURIInPrefList(
11680 "docshell.shistory.sameDocumentNavigationOverridesLoadType."
11681 "forceDisable")) {
11682 loadTypeResetter.emplace(mLoadType);
11683 }
11684
11685 // pushState effectively becomes replaceState when we've started a network
11686 // load but haven't adopted its document yet. This mirrors what we do with
11687 // changes to the hash at this stage of the game.
11688 if (JustStartedNetworkLoad()) {
11689 if (!loadTypeResetter.isSome()) {
11690 loadTypeResetter.emplace(mLoadType);
11691 }
11692 aReplace = true;
11693 }
11694
11695 // Step A: Serialize aData using structured clone.
11696 // https://html.spec.whatwg.org/multipage/history.html#dom-history-pushstate
11697 // step 5.
11698 nsCOMPtr<nsIStructuredCloneContainer> scContainer;
11699
11700 // scContainer->Init might cause arbitrary JS to run, and this code might
11701 // navigate the page we're on, potentially to a different origin! (bug
11702 // 634834) To protect against this, we abort if our principal changes due
11703 // to the InitFromJSVal() call.
11704 {
11705 RefPtr<Document> origDocument = GetDocument();
11706 if (!origDocument) {
11707 return NS_ERROR_DOM_SECURITY_ERR;
11708 }
11709 nsCOMPtr<nsIPrincipal> origPrincipal = origDocument->NodePrincipal();
11710
11711 scContainer = new nsStructuredCloneContainer();
11712 rv = scContainer->InitFromJSVal(aData, aCx);
11713 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 11713); return rv; } } while (false)
;
11714
11715 RefPtr<Document> newDocument = GetDocument();
11716 if (!newDocument) {
11717 return NS_ERROR_DOM_SECURITY_ERR;
11718 }
11719 nsCOMPtr<nsIPrincipal> newPrincipal = newDocument->NodePrincipal();
11720
11721 bool principalsEqual = false;
11722 origPrincipal->Equals(newPrincipal, &principalsEqual);
11723 NS_ENSURE_TRUE(principalsEqual, NS_ERROR_DOM_SECURITY_ERR)do { if ((__builtin_expect(!!(!(principalsEqual)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "principalsEqual" ") failed"
, nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 11723); return NS_ERROR_DOM_SECURITY_ERR; } } while (false)
;
11724 }
11725
11726 // Check that the state object isn't too long.
11727 int32_t maxStateObjSize = StaticPrefs::browser_history_maxStateObjectSize();
11728 if (maxStateObjSize < 0) {
11729 maxStateObjSize = 0;
11730 }
11731
11732 uint64_t scSize;
11733 rv = scContainer->GetSerializedNBytes(&scSize);
11734 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 11734); return rv; } } while (false)
;
11735
11736 NS_ENSURE_TRUE(scSize <= (uint32_t)maxStateObjSize, NS_ERROR_ILLEGAL_VALUE)do { if ((__builtin_expect(!!(!(scSize <= (uint32_t)maxStateObjSize
)), 0))) { NS_DebugBreak(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "scSize <= (uint32_t)maxStateObjSize"
") failed", nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 11736); return NS_ERROR_ILLEGAL_VALUE; } } while (false)
;
11737
11738 // Step B: Resolve aURL.
11739 // https://html.spec.whatwg.org/multipage/history.html#dom-history-pushstate
11740 // step 7.
11741 bool equalURIs = true;
11742 nsCOMPtr<nsIURI> currentURI;
11743 if (mCurrentURI) {
11744 currentURI = nsIOService::CreateExposableURI(mCurrentURI);
11745 } else {
11746 currentURI = mCurrentURI;
11747 }
11748 nsCOMPtr<nsIURI> newURI;
11749 if (aURL.Length() == 0) {
11750 newURI = currentURI;
11751 } else {
11752 // 7.1: Resolve aURL relative to mURI
11753
11754 nsIURI* docBaseURI = document->GetDocBaseURI();
11755 if (!docBaseURI) {
11756 return NS_ERROR_FAILURE;
11757 }
11758
11759 nsAutoCString spec;
11760 docBaseURI->GetSpec(spec);
11761
11762 rv = NS_NewURI(getter_AddRefs(newURI), aURL,
11763 document->GetDocumentCharacterSet(), docBaseURI);
11764
11765 // 7.2: If 2a fails, raise a SECURITY_ERR
11766 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
11767 return NS_ERROR_DOM_SECURITY_ERR;
11768 }
11769
11770 if (!document->CanRewriteURL(newURI)) {
11771 return NS_ERROR_DOM_SECURITY_ERR;
11772 }
11773
11774 if (currentURI) {
11775 currentURI->Equals(newURI, &equalURIs);
11776 } else {
11777 equalURIs = false;
11778 }
11779
11780 } // end of same-origin check
11781
11782 // https://html.spec.whatwg.org/#shared-history-push/replace-state-steps
11783 // Step 8
11784 if (nsCOMPtr<nsPIDOMWindowInner> window = document->GetInnerWindow()) {
11785 if (RefPtr<Navigation> navigation = window->Navigation()) {
11786 bool shouldContinue = navigation->FirePushReplaceReloadNavigateEvent(
11787 aCx, aReplace ? NavigationType::Replace : NavigationType::Push,
11788 newURI,
11789 /* aIsSameDocument */ true, /* aIsSync */ true,
11790 /* aUserInvolvement */ Nothing(),
11791 /* aSourceElement */ nullptr, /* aFormDataEntryList */ nullptr,
11792 /* aNavigationAPIState */ nullptr, scContainer);
11793
11794 // Step 9
11795 if (!shouldContinue) {
11796 return NS_OK;
11797 }
11798 }
11799 }
11800
11801 // Step 10
11802 // Run #url-and-history-update-steps
11803 rv = UpdateURLAndHistory(document, newURI, scContainer,
11804 aReplace ? NavigationHistoryBehavior::Replace
11805 : NavigationHistoryBehavior::Push,
11806 currentURI, equalURIs);
11807 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 11807); return rv; } } while (false)
;
11808
11809 return NS_OK;
11810}
11811
11812nsresult nsDocShell::UpdateURLAndHistory(
11813 Document* aDocument, nsIURI* aNewURI, nsIStructuredCloneContainer* aData,
11814 NavigationHistoryBehavior aHistoryHandling, nsIURI* aCurrentURI,
11815 bool aEqualURIs) {
11816 // Implements
11817 // https://html.spec.whatwg.org/multipage/history.html#url-and-history-update-steps
11818 MOZ_ASSERT(aHistoryHandling != NavigationHistoryBehavior::Auto)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aHistoryHandling != NavigationHistoryBehavior::Auto)
>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(aHistoryHandling != NavigationHistoryBehavior::Auto)
)), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aHistoryHandling != NavigationHistoryBehavior::Auto"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 11818);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "aHistoryHandling != NavigationHistoryBehavior::Auto"
")"); do { MOZ_CrashSequence(__null, 11818); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11819 bool isReplace = aHistoryHandling == NavigationHistoryBehavior::Replace;
11820
11821 // If we have a pending title change, handle it before creating a new entry.
11822 aDocument->DoNotifyPossibleTitleChange();
11823
11824 // Step 2, if aReplace is false: Create a new entry in the session
11825 // history. This will erase all SHEntries after the new entry and make this
11826 // entry the current one. This operation may modify mOSHE, which we need
11827 // later, so we keep a reference here.
11828 NS_ENSURE_TRUE(mOSHE || mActiveEntry || isReplace, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(mOSHE || mActiveEntry || isReplace
)), 0))) { NS_DebugBreak(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "mOSHE || mActiveEntry || isReplace"
") failed", nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 11828); return NS_ERROR_FAILURE; } } while (false)
;
11829 nsCOMPtr<nsISHEntry> oldOSHE = mOSHE;
11830
11831 // If this push/replaceState changed the document's current URI and the new
11832 // URI differs from the old URI in more than the hash, or if the old
11833 // SHEntry's URI was modified in this way by a push/replaceState call
11834 // set URIWasModified to true for the current SHEntry (bug 669671).
11835 bool sameExceptHashes = true;
11836 aNewURI->EqualsExceptRef(aCurrentURI, &sameExceptHashes);
11837 bool uriWasModified;
11838 if (sameExceptHashes) {
11839 if (mozilla::SessionHistoryInParent()) {
11840 uriWasModified = mActiveEntry && mActiveEntry->GetURIWasModified();
11841 } else {
11842 uriWasModified = oldOSHE && oldOSHE->GetURIWasModified();
11843 }
11844 } else {
11845 uriWasModified = true;
11846 }
11847
11848 mLoadType = LOAD_PUSHSTATE;
11849
11850 nsCOMPtr<nsISHEntry> newSHEntry;
11851 if (!isReplace) {
11852 // Step 2.
11853
11854 // Step 2.2, "Remove any tasks queued by the history traversal task
11855 // source that are associated with any Document objects in the
11856 // top-level browsing context's document family." This is very hard in
11857 // SessionHistoryInParent since we can't synchronously access the
11858 // pending navigations that are already sent to the parent. We can
11859 // abort any AsyncGo navigations that are waiting to be sent. If we
11860 // send a message to the parent, it would be processed after any
11861 // navigations previously sent. So long as we consider the "history
11862 // traversal task source" to be the list in this process we match the
11863 // spec. If we move the entire list to the parent, we can handle the
11864 // aborting of loads there, but we don't have a way to synchronously
11865 // remove entries as we do here for non-SHIP.
11866 RefPtr<ChildSHistory> shistory = GetRootSessionHistory();
11867 if (shistory) {
11868 shistory->RemovePendingHistoryNavigations();
11869 }
11870
11871 nsPoint scrollPos = GetCurScrollPos();
11872
11873 bool scrollRestorationIsManual;
11874 if (mozilla::SessionHistoryInParent()) {
11875 // FIXME Need to save the current scroll position on mActiveEntry.
11876 scrollRestorationIsManual = mActiveEntry->GetScrollRestorationIsManual();
11877 } else {
11878 // Save the current scroll position (bug 590573). Step 2.3.
11879 mOSHE->SetScrollPosition(scrollPos.x, scrollPos.y);
11880
11881 scrollRestorationIsManual = mOSHE->GetScrollRestorationIsManual();
11882 }
11883
11884 nsCOMPtr<nsIContentSecurityPolicy> csp = aDocument->GetCsp();
11885
11886 if (mozilla::SessionHistoryInParent()) {
11887 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)
11888 ("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)
;
11889
11890 nsString title(mActiveEntry->GetTitle());
11891 nsCOMPtr<nsIReferrerInfo> referrerInfo = mActiveEntry->GetReferrerInfo();
11892
11893 UpdateActiveEntry(false,
11894 /* aPreviousScrollPos = */ Some(scrollPos), aNewURI,
11895 /* aOriginalURI = */ nullptr,
11896 /* aReferrerInfo = */ referrerInfo,
11897 /* aTriggeringPrincipal = */ aDocument->NodePrincipal(),
11898 csp, title, scrollRestorationIsManual, aData,
11899 uriWasModified);
11900 } else {
11901 // Since we're not changing which page we have loaded, pass
11902 // true for aCloneChildren.
11903 nsresult rv = AddToSessionHistory(
11904 aNewURI, nullptr,
11905 aDocument->NodePrincipal(), // triggeringPrincipal
11906 nullptr, nullptr, csp, true, getter_AddRefs(newSHEntry));
11907 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 11907); return rv; } } while (false)
;
11908
11909 NS_ENSURE_TRUE(newSHEntry, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(newSHEntry)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "newSHEntry" ") failed",
nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp",
11909); return NS_ERROR_FAILURE; } } while (false)
;
11910
11911 // Session history entries created by pushState inherit scroll restoration
11912 // mode from the current entry.
11913 newSHEntry->SetScrollRestorationIsManual(scrollRestorationIsManual);
11914
11915 // Set the new SHEntry's title (bug 655273).
11916 nsString title;
11917 mOSHE->GetTitle(title);
11918 newSHEntry->SetTitle(title);
11919
11920 nsCOMPtr<nsIReferrerInfo> referrerInfo = mOSHE->GetReferrerInfo();
11921 newSHEntry->SetReferrerInfo(referrerInfo);
11922
11923 // Link the new SHEntry to the old SHEntry's BFCache entry, since the
11924 // two entries correspond to the same document.
11925 NS_ENSURE_SUCCESS(newSHEntry->AdoptBFCacheEntry(oldOSHE),do { nsresult __rv = newSHEntry->AdoptBFCacheEntry(oldOSHE
); if (((bool)(__builtin_expect(!!(NS_FAILED_impl(__rv)), 0))
)) { const char* name = mozilla::GetStaticErrorName(__rv); mozilla
::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "newSHEntry->AdoptBFCacheEntry(oldOSHE)"
, "NS_ERROR_FAILURE", static_cast<uint32_t>(__rv), name
? " (" : "", name ? name : "", name ? ")" : ""); NS_DebugBreak
(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 11926); return NS_ERROR_FAILURE; } } while (false)
11926 NS_ERROR_FAILURE)do { nsresult __rv = newSHEntry->AdoptBFCacheEntry(oldOSHE
); if (((bool)(__builtin_expect(!!(NS_FAILED_impl(__rv)), 0))
)) { const char* name = mozilla::GetStaticErrorName(__rv); mozilla
::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "newSHEntry->AdoptBFCacheEntry(oldOSHE)"
, "NS_ERROR_FAILURE", static_cast<uint32_t>(__rv), name
? " (" : "", name ? name : "", name ? ")" : ""); NS_DebugBreak
(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 11926); return NS_ERROR_FAILURE; } } while (false)
;
11927
11928 // AddToSessionHistory may not modify mOSHE. In case it doesn't,
11929 // we'll just set mOSHE here.
11930 mOSHE = newSHEntry;
11931 }
11932 } else if (mozilla::SessionHistoryInParent()) {
11933 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)
11934 ("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)
11935 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)
;
11936 // Setting the resultPrincipalURI to nullptr is fine here: it will cause
11937 // NS_GetFinalChannelURI to use the originalURI as the URI, which is aNewURI
11938 // in our case. We could also set it to aNewURI, with the same result.
11939 // We don't use aTitle here, see bug 544535.
11940 nsString title;
11941 nsCOMPtr<nsIReferrerInfo> referrerInfo;
11942 if (mActiveEntry) {
11943 title = mActiveEntry->GetTitle();
11944 referrerInfo = mActiveEntry->GetReferrerInfo();
11945 } else {
11946 referrerInfo = nullptr;
11947 }
11948 UpdateActiveEntry(
11949 true, /* aPreviousScrollPos = */ Nothing(), aNewURI, aNewURI,
11950 /* aReferrerInfo = */ referrerInfo, aDocument->NodePrincipal(),
11951 aDocument->GetCsp(), title,
11952 mActiveEntry && mActiveEntry->GetScrollRestorationIsManual(), aData,
11953 uriWasModified);
11954 } else {
11955 // Step 3.
11956 newSHEntry = mOSHE;
11957
11958 MOZ_LOG(gSHLog, LogLevel::Debug, ("nsDocShell %p step 3", this))do { const ::mozilla::LogModule* moz_real_module = gSHLog; if
((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "nsDocShell %p step 3", this); } } while (
0)
;
11959 // Since we're not changing which page we have loaded, pass
11960 // true for aCloneChildren.
11961 if (!newSHEntry) {
11962 nsresult rv = AddToSessionHistory(
11963 aNewURI, nullptr,
11964 aDocument->NodePrincipal(), // triggeringPrincipal
11965 nullptr, nullptr, aDocument->GetCsp(), true,
11966 getter_AddRefs(newSHEntry));
11967 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 11967); return rv; } } while (false)
;
11968 mOSHE = newSHEntry;
11969 }
11970
11971 nsCOMPtr<nsIReferrerInfo> referrerInfo = mOSHE->GetReferrerInfo();
11972
11973 newSHEntry->SetURI(aNewURI);
11974 newSHEntry->SetOriginalURI(aNewURI);
11975 // We replaced the URI of the entry, clear the unstripped URI as it
11976 // shouldn't be used for reloads anymore.
11977 newSHEntry->SetUnstrippedURI(nullptr);
11978 // Setting the resultPrincipalURI to nullptr is fine here: it will cause
11979 // NS_GetFinalChannelURI to use the originalURI as the URI, which is aNewURI
11980 // in our case. We could also set it to aNewURI, with the same result.
11981 newSHEntry->SetResultPrincipalURI(nullptr);
11982 newSHEntry->SetLoadReplace(false);
11983 newSHEntry->SetReferrerInfo(referrerInfo);
11984 }
11985
11986 if (!mozilla::SessionHistoryInParent()) {
11987 // Step 2.4 and 3: Modify new/original session history entry and clear its
11988 // POST data, if there is any.
11989 newSHEntry->SetStateData(aData);
11990 newSHEntry->SetPostData(nullptr);
11991
11992 newSHEntry->SetURIWasModified(uriWasModified);
11993
11994 // Step E as described at the top of AddState: If aReplace is false,
11995 // indicating that we're doing a pushState rather than a replaceState,
11996 // notify bfcache that we've added a page to the history so it can evict
11997 // content viewers if appropriate. Otherwise call ReplaceEntry so that we
11998 // notify nsIHistoryListeners that an entry was replaced. We may not have a
11999 // root session history if this call is coming from a document.open() in a
12000 // docshell subtree that disables session history.
12001 RefPtr<ChildSHistory> rootSH = GetRootSessionHistory();
12002 if (rootSH) {
12003 rootSH->LegacySHistory()->EvictDocumentViewersOrReplaceEntry(newSHEntry,
12004 isReplace);
12005 }
12006 }
12007
12008 // Step 4: If the document's URI changed, update document's URI and update
12009 // global history.
12010 //
12011 // We need to call FireOnLocationChange so that the browser's address bar
12012 // gets updated and the back button is enabled, but we only need to
12013 // explicitly call FireOnLocationChange if we're not calling SetCurrentURI,
12014 // since SetCurrentURI will call FireOnLocationChange for us.
12015 //
12016 // Both SetCurrentURI(...) and FireDummyOnLocationChange() pass
12017 // nullptr for aRequest param to FireOnLocationChange(...). Such an update
12018 // notification is allowed only when we know docshell is not loading a new
12019 // document and it requires LOCATION_CHANGE_SAME_DOCUMENT flag. Otherwise,
12020 // FireOnLocationChange(...) breaks security UI.
12021 //
12022 // If the docshell is shutting down, don't update the document URI, as we
12023 // can't load into a docshell that is being destroyed.
12024 if (!aEqualURIs && !mIsBeingDestroyed) {
12025 aDocument->SetDocumentURI(aNewURI);
12026 SetCurrentURI(aNewURI, nullptr, /* aFireLocationChange */ true,
12027 /* aIsInitialAboutBlank */ false,
12028 GetSameDocumentNavigationFlags(aNewURI));
12029
12030 AddURIVisit(aNewURI, aCurrentURI, 0);
12031
12032 // AddURIVisit doesn't set the title for the new URI in global history,
12033 // so do that here.
12034 UpdateGlobalHistoryTitle(aNewURI);
12035
12036 // Inform the favicon service that our old favicon applies to this new
12037 // URI.
12038 CopyFavicon(aCurrentURI, aNewURI, UsePrivateBrowsing());
12039 } else {
12040 FireDummyOnLocationChange();
12041 }
12042 aDocument->SetStateObject(aData);
12043
12044 if (RefPtr navigation = aDocument->GetInnerWindow()->Navigation()) {
12045 MOZ_LOG(gNavigationLog, LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = gNavigationLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "nsDocShell %p triggering a navigation event for a same-document "
"navigation from UpdateURLAndHistory -> isReplace: %s", this
, isReplace ? "true" : "false"); } } while (0)
12046 ("nsDocShell %p triggering a navigation event for a same-document "do { const ::mozilla::LogModule* moz_real_module = gNavigationLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "nsDocShell %p triggering a navigation event for a same-document "
"navigation from UpdateURLAndHistory -> isReplace: %s", this
, isReplace ? "true" : "false"); } } while (0)
12047 "navigation from UpdateURLAndHistory -> isReplace: %s",do { const ::mozilla::LogModule* moz_real_module = gNavigationLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "nsDocShell %p triggering a navigation event for a same-document "
"navigation from UpdateURLAndHistory -> isReplace: %s", this
, isReplace ? "true" : "false"); } } while (0)
12048 this, isReplace ? "true" : "false"))do { const ::mozilla::LogModule* moz_real_module = gNavigationLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "nsDocShell %p triggering a navigation event for a same-document "
"navigation from UpdateURLAndHistory -> isReplace: %s", this
, isReplace ? "true" : "false"); } } while (0)
;
12049 // Step 11: Update the navigation API entries for a same-document
12050 // navigation given document's relevant global object's navigation API,
12051 // newEntry, and historyHandling.
12052 navigation->UpdateEntriesForSameDocumentNavigation(
12053 mActiveEntry.get(),
12054 isReplace ? NavigationType::Replace : NavigationType::Push);
12055 }
12056
12057 return NS_OK;
12058}
12059
12060NS_IMETHODIMPnsresult
12061nsDocShell::GetCurrentScrollRestorationIsManual(bool* aIsManual) {
12062 if (mozilla::SessionHistoryInParent()) {
12063 *aIsManual = mActiveEntry && mActiveEntry->GetScrollRestorationIsManual();
12064 return NS_OK;
12065 }
12066
12067 *aIsManual = false;
12068 if (mOSHE) {
12069 return mOSHE->GetScrollRestorationIsManual(aIsManual);
12070 }
12071
12072 return NS_OK;
12073}
12074
12075NS_IMETHODIMPnsresult
12076nsDocShell::SetCurrentScrollRestorationIsManual(bool aIsManual) {
12077 SetScrollRestorationIsManualOnHistoryEntry(mOSHE, aIsManual);
12078
12079 return NS_OK;
12080}
12081
12082void nsDocShell::SetScrollRestorationIsManualOnHistoryEntry(
12083 nsISHEntry* aSHEntry, bool aIsManual) {
12084 if (aSHEntry) {
12085 aSHEntry->SetScrollRestorationIsManual(aIsManual);
12086 }
12087
12088 if (mActiveEntry && mBrowsingContext) {
12089 mActiveEntry->SetScrollRestorationIsManual(aIsManual);
12090 if (XRE_IsParentProcess()) {
12091 SessionHistoryEntry* entry =
12092 mBrowsingContext->Canonical()->GetActiveSessionHistoryEntry();
12093 if (entry) {
12094 entry->SetScrollRestorationIsManual(aIsManual);
12095 }
12096 } else {
12097 mozilla::Unused << ContentChild::GetSingleton()
12098 ->SendSessionHistoryEntryScrollRestorationIsManual(
12099 mBrowsingContext, aIsManual);
12100 }
12101 }
12102}
12103
12104void nsDocShell::SetCacheKeyOnHistoryEntry(nsISHEntry* aSHEntry,
12105 uint32_t aCacheKey) {
12106 if (aSHEntry) {
12107 aSHEntry->SetCacheKey(aCacheKey);
12108 }
12109
12110 if (mActiveEntry && mBrowsingContext) {
12111 mActiveEntry->SetCacheKey(aCacheKey);
12112 if (XRE_IsParentProcess()) {
12113 SessionHistoryEntry* entry =
12114 mBrowsingContext->Canonical()->GetActiveSessionHistoryEntry();
12115 if (entry) {
12116 entry->SetCacheKey(aCacheKey);
12117 }
12118 } else {
12119 mozilla::Unused
12120 << ContentChild::GetSingleton()->SendSessionHistoryEntryCacheKey(
12121 mBrowsingContext, aCacheKey);
12122 }
12123 }
12124}
12125
12126/* static */
12127bool nsDocShell::ShouldAddToSessionHistory(nsIURI* aURI, nsIChannel* aChannel) {
12128 // I believe none of the about: urls should go in the history. But then
12129 // that could just be me... If the intent is only deny about:blank then we
12130 // should just do a spec compare, rather than two gets of the scheme and
12131 // then the path. -Gagan
12132 nsresult rv;
12133 nsAutoCString buf;
12134
12135 rv = aURI->GetScheme(buf);
12136 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
12137 return false;
12138 }
12139
12140 if (buf.EqualsLiteral("about")) {
12141 rv = aURI->GetPathQueryRef(buf);
12142 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
12143 return false;
12144 }
12145
12146 if (buf.EqualsLiteral("blank")) {
12147 return false;
12148 }
12149 // We only want to add about:newtab if it's not privileged, and
12150 // if it is not configured to show the blank page.
12151 if (buf.EqualsLiteral("newtab")) {
12152 if (!StaticPrefs::browser_newtabpage_enabled()) {
12153 return false;
12154 }
12155
12156 NS_ENSURE_TRUE(aChannel, false)do { if ((__builtin_expect(!!(!(aChannel)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aChannel" ") failed", nullptr
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 12156);
return false; } } while (false)
;
12157 nsCOMPtr<nsIPrincipal> resultPrincipal;
12158 rv = nsContentUtils::GetSecurityManager()->GetChannelResultPrincipal(
12159 aChannel, getter_AddRefs(resultPrincipal));
12160 NS_ENSURE_SUCCESS(rv, false)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "false", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 12160); return false; } } while (false)
;
12161 return !resultPrincipal->IsSystemPrincipal();
12162 }
12163 }
12164
12165 return true;
12166}
12167
12168nsresult nsDocShell::AddToSessionHistory(
12169 nsIURI* aURI, nsIChannel* aChannel, nsIPrincipal* aTriggeringPrincipal,
12170 nsIPrincipal* aPrincipalToInherit,
12171 nsIPrincipal* aPartitionedPrincipalToInherit,
12172 nsIContentSecurityPolicy* aCsp, bool aCloneChildren,
12173 nsISHEntry** aNewEntry) {
12174 MOZ_ASSERT(aURI, "uri is null")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aURI)>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(aURI))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("aURI" " (" "uri is null" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 12174); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aURI" ") ("
"uri is null" ")"); do { MOZ_CrashSequence(__null, 12174); __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
;
12175 MOZ_ASSERT(!aChannel || !aTriggeringPrincipal, "Shouldn't have both set")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aChannel || !aTriggeringPrincipal)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!aChannel || !aTriggeringPrincipal
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"!aChannel || !aTriggeringPrincipal" " (" "Shouldn't have both set"
")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 12175
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aChannel || !aTriggeringPrincipal"
") (" "Shouldn't have both set" ")"); do { MOZ_CrashSequence
(__null, 12175); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
12176 MOZ_DIAGNOSTIC_ASSERT(!mozilla::SessionHistoryInParent())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mozilla::SessionHistoryInParent())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mozilla::SessionHistoryInParent
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!mozilla::SessionHistoryInParent()", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 12176); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "!mozilla::SessionHistoryInParent()"
")"); do { MOZ_CrashSequence(__null, 12176); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12177
12178#if defined(DEBUG1)
12179 if (MOZ_LOG_TEST(gDocShellLog, LogLevel::Debug)(__builtin_expect(!!(mozilla::detail::log_test(gDocShellLog, LogLevel
::Debug)), 0))
) {
12180 nsAutoCString chanName;
12181 if (aChannel) {
12182 aChannel->GetName(chanName);
12183 } else {
12184 chanName.AssignLiteral("<no channel>");
12185 }
12186
12187 MOZ_LOG(gDocShellLog, LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = gDocShellLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "nsDocShell[%p]::AddToSessionHistory(\"%s\", [%s])\n"
, this, aURI->GetSpecOrDefault().get(), chanName.get()); }
} while (0)
12188 ("nsDocShell[%p]::AddToSessionHistory(\"%s\", [%s])\n", this,do { const ::mozilla::LogModule* moz_real_module = gDocShellLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "nsDocShell[%p]::AddToSessionHistory(\"%s\", [%s])\n"
, this, aURI->GetSpecOrDefault().get(), chanName.get()); }
} while (0)
12189 aURI->GetSpecOrDefault().get(), chanName.get()))do { const ::mozilla::LogModule* moz_real_module = gDocShellLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "nsDocShell[%p]::AddToSessionHistory(\"%s\", [%s])\n"
, this, aURI->GetSpecOrDefault().get(), chanName.get()); }
} while (0)
;
12190 }
12191#endif
12192
12193 nsresult rv = NS_OK;
12194 nsCOMPtr<nsISHEntry> entry;
12195
12196 /*
12197 * If this is a LOAD_FLAGS_REPLACE_HISTORY in a subframe, we use
12198 * the existing SH entry in the page and replace the url and
12199 * other vitalities.
12200 */
12201 if (LOAD_TYPE_HAS_FLAGS(mLoadType, LOAD_FLAGS_REPLACE_HISTORY)((mLoadType) & ((LOAD_FLAGS_REPLACE_HISTORY) << 16)
)
&&
12202 !mBrowsingContext->IsTop()) {
12203 // This is a subframe
12204 entry = mOSHE;
12205 if (entry) {
12206 entry->ClearEntry();
12207 }
12208 }
12209
12210 // Create a new entry if necessary.
12211 if (!entry) {
12212 entry = new nsSHEntry();
12213 }
12214
12215 // Get the post data & referrer
12216 nsCOMPtr<nsIInputStream> inputStream;
12217 nsCOMPtr<nsIURI> originalURI;
12218 nsCOMPtr<nsIURI> resultPrincipalURI;
12219 nsCOMPtr<nsIURI> unstrippedURI;
12220 bool loadReplace = false;
12221 nsCOMPtr<nsIReferrerInfo> referrerInfo;
12222 uint32_t cacheKey = 0;
12223 nsCOMPtr<nsIPrincipal> triggeringPrincipal = aTriggeringPrincipal;
12224 nsCOMPtr<nsIPrincipal> principalToInherit = aPrincipalToInherit;
12225 nsCOMPtr<nsIPrincipal> partitionedPrincipalToInherit =
12226 aPartitionedPrincipalToInherit;
12227 nsCOMPtr<nsIContentSecurityPolicy> csp = aCsp;
12228 bool expired = false; // by default the page is not expired
12229 bool discardLayoutState = false;
12230 nsCOMPtr<nsICacheInfoChannel> cacheChannel;
12231 bool userActivation = false;
12232
12233 if (aChannel) {
12234 cacheChannel = do_QueryInterface(aChannel);
12235
12236 /* If there is a caching channel, get the Cache Key and store it
12237 * in SH.
12238 */
12239 if (cacheChannel) {
12240 cacheChannel->GetCacheKey(&cacheKey);
12241 }
12242 nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(aChannel));
12243
12244 // Check if the httpChannel is hiding under a multipartChannel
12245 if (!httpChannel) {
12246 GetHttpChannel(aChannel, getter_AddRefs(httpChannel));
12247 }
12248 if (httpChannel) {
12249 nsCOMPtr<nsIUploadChannel> uploadChannel(do_QueryInterface(httpChannel));
12250 if (uploadChannel) {
12251 uploadChannel->GetUploadStream(getter_AddRefs(inputStream));
12252 }
12253 httpChannel->GetOriginalURI(getter_AddRefs(originalURI));
12254 uint32_t loadFlags;
12255 aChannel->GetLoadFlags(&loadFlags);
12256 loadReplace = loadFlags & nsIChannel::LOAD_REPLACE;
12257 rv = httpChannel->GetReferrerInfo(getter_AddRefs(referrerInfo));
12258 MOZ_ASSERT(NS_SUCCEEDED(rv))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
)))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 12258); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 12258); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12259
12260 discardLayoutState = ShouldDiscardLayoutState(httpChannel);
12261 }
12262
12263 nsCOMPtr<nsILoadInfo> loadInfo = aChannel->LoadInfo();
12264 if (!triggeringPrincipal) {
12265 triggeringPrincipal = loadInfo->TriggeringPrincipal();
12266 }
12267 if (!csp) {
12268 csp = loadInfo->GetCspToInherit();
12269 }
12270
12271 loadInfo->GetResultPrincipalURI(getter_AddRefs(resultPrincipalURI));
12272
12273 loadInfo->GetUnstrippedURI(getter_AddRefs(unstrippedURI));
12274
12275 userActivation = loadInfo->GetHasValidUserGestureActivation();
12276
12277 // For now keep storing just the principal in the SHEntry.
12278 if (!principalToInherit) {
12279 if (loadInfo->GetLoadingSandboxed()) {
12280 if (loadInfo->GetLoadingPrincipal()) {
12281 principalToInherit = NullPrincipal::CreateWithInheritedAttributes(
12282 loadInfo->GetLoadingPrincipal());
12283 } else {
12284 // get the OriginAttributes
12285 OriginAttributes attrs;
12286 loadInfo->GetOriginAttributes(&attrs);
12287 principalToInherit = NullPrincipal::Create(attrs);
12288 }
12289 } else {
12290 principalToInherit = loadInfo->PrincipalToInherit();
12291 }
12292 }
12293
12294 if (!partitionedPrincipalToInherit) {
12295 // XXXehsan is it correct to fall back to the principal to inherit in all
12296 // cases? For example, what about the cases where we are using the load
12297 // info's principal to inherit? Do we need to add a similar concept to
12298 // load info for partitioned principal?
12299 partitionedPrincipalToInherit = principalToInherit;
12300 }
12301 }
12302
12303 nsAutoString srcdoc;
12304 bool srcdocEntry = false;
12305 nsCOMPtr<nsIURI> baseURI;
12306
12307 nsCOMPtr<nsIInputStreamChannel> inStrmChan = do_QueryInterface(aChannel);
12308 if (inStrmChan) {
12309 bool isSrcdocChannel;
12310 inStrmChan->GetIsSrcdocChannel(&isSrcdocChannel);
12311 if (isSrcdocChannel) {
12312 inStrmChan->GetSrcdocData(srcdoc);
12313 srcdocEntry = true;
12314 inStrmChan->GetBaseURI(getter_AddRefs(baseURI));
12315 } else {
12316 srcdoc.SetIsVoid(true);
12317 }
12318 }
12319 /* If cache got a 'no-store', ask SH not to store
12320 * HistoryLayoutState. By default, SH will set this
12321 * flag to true and save HistoryLayoutState.
12322 */
12323 bool saveLayoutState = !discardLayoutState;
12324
12325 if (cacheChannel) {
12326 // Check if the page has expired from cache
12327 uint32_t expTime = 0;
12328 cacheChannel->GetCacheTokenExpirationTime(&expTime);
12329 uint32_t now = PRTimeToSeconds(PR_Now());
12330 if (expTime <= now) {
12331 expired = true;
12332 }
12333 }
12334
12335 // Title is set in nsDocShell::SetTitle()
12336 entry->Create(aURI, // uri
12337 u""_ns, // Title
12338 inputStream, // Post data stream
12339 cacheKey, // CacheKey
12340 mContentTypeHint, // Content-type
12341 triggeringPrincipal, // Channel or provided principal
12342 principalToInherit, partitionedPrincipalToInherit, csp,
12343 HistoryID(), GetCreatedDynamically(), originalURI,
12344 resultPrincipalURI, unstrippedURI, loadReplace, referrerInfo,
12345 srcdoc, srcdocEntry, baseURI, saveLayoutState, expired,
12346 userActivation);
12347
12348 if (mBrowsingContext->IsTop() && GetSessionHistory()) {
12349 Maybe<int32_t> previousEntryIndex;
12350 Maybe<int32_t> loadedEntryIndex;
12351
12352 if (mBrowsingContext->IsTop() &&
12353 !ShouldAddToSessionHistory(aURI, aChannel)) {
12354 entry->SetTransient();
12355 }
12356 rv = GetSessionHistory()->LegacySHistory()->AddToRootSessionHistory(
12357 aCloneChildren, mOSHE, mBrowsingContext, entry, mLoadType,
12358 &previousEntryIndex, &loadedEntryIndex);
12359
12360 MOZ_ASSERT(NS_SUCCEEDED(rv), "Could not add entry to root session history")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
)))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))" " ("
"Could not add entry to root session history" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 12360); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
") (" "Could not add entry to root session history" ")"); do
{ MOZ_CrashSequence(__null, 12360); __attribute__((nomerge))
::abort(); } while (false); } } while (false)
;
12361 if (previousEntryIndex.isSome()) {
12362 mPreviousEntryIndex = previousEntryIndex.value();
12363 }
12364 if (loadedEntryIndex.isSome()) {
12365 mLoadedEntryIndex = loadedEntryIndex.value();
12366 }
12367
12368 // aCloneChildren implies that we are retaining the same document, thus we
12369 // need to signal to the top WC that the new SHEntry may receive a fresh
12370 // user interaction flag.
12371 if (aCloneChildren) {
12372 WindowContext* topWc = mBrowsingContext->GetTopWindowContext();
12373 if (topWc && !topWc->IsDiscarded()) {
12374 MOZ_ALWAYS_SUCCEEDS(topWc->SetSHEntryHasUserInteraction(false))do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(topWc->SetSHEntryHasUserInteraction(false))), 1)))), 1)))
{ } else { do { do { } while (false); MOZ_ReportCrash("" "NS_SUCCEEDED(topWc->SetSHEntryHasUserInteraction(false))"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 12374);
AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED(topWc->SetSHEntryHasUserInteraction(false))"
")"); do { MOZ_CrashSequence(__null, 12374); __attribute__((
nomerge)) ::abort(); } while (false); } while (false); } } while
(false)
;
12375 }
12376 }
12377 } else {
12378 // This is a subframe, make sure that this new SHEntry will be
12379 // marked with user interaction.
12380 WindowContext* topWc = mBrowsingContext->GetTopWindowContext();
12381 if (topWc && !topWc->IsDiscarded()) {
12382 MOZ_ALWAYS_SUCCEEDS(topWc->SetSHEntryHasUserInteraction(false))do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(topWc->SetSHEntryHasUserInteraction(false))), 1)))), 1)))
{ } else { do { do { } while (false); MOZ_ReportCrash("" "NS_SUCCEEDED(topWc->SetSHEntryHasUserInteraction(false))"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 12382);
AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED(topWc->SetSHEntryHasUserInteraction(false))"
")"); do { MOZ_CrashSequence(__null, 12382); __attribute__((
nomerge)) ::abort(); } while (false); } while (false); } } while
(false)
;
12383 }
12384 if (!mOSHE || !LOAD_TYPE_HAS_FLAGS(mLoadType, LOAD_FLAGS_REPLACE_HISTORY)((mLoadType) & ((LOAD_FLAGS_REPLACE_HISTORY) << 16)
)
) {
12385 rv = AddChildSHEntryToParent(entry, mBrowsingContext->ChildOffset(),
12386 aCloneChildren);
12387 }
12388 }
12389
12390 // Return the new SH entry...
12391 if (aNewEntry) {
12392 *aNewEntry = nullptr;
12393 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
12394 entry.forget(aNewEntry);
12395 }
12396 }
12397
12398 return rv;
12399}
12400
12401void nsDocShell::UpdateActiveEntry(
12402 bool aReplace, const Maybe<nsPoint>& aPreviousScrollPos, nsIURI* aURI,
12403 nsIURI* aOriginalURI, nsIReferrerInfo* aReferrerInfo,
12404 nsIPrincipal* aTriggeringPrincipal, nsIContentSecurityPolicy* aCsp,
12405 const nsAString& aTitle, bool aScrollRestorationIsManual,
12406 nsIStructuredCloneContainer* aData, bool aURIWasModified) {
12407 MOZ_ASSERT(mozilla::SessionHistoryInParent())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mozilla::SessionHistoryInParent())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mozilla::SessionHistoryInParent
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("mozilla::SessionHistoryInParent()", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 12407); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mozilla::SessionHistoryInParent()"
")"); do { MOZ_CrashSequence(__null, 12407); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12408 MOZ_ASSERT(aURI, "uri is null")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aURI)>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(aURI))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("aURI" " (" "uri is null" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 12408); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aURI" ") ("
"uri is null" ")"); do { MOZ_CrashSequence(__null, 12408); __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
;
12409 MOZ_ASSERT(mLoadType == LOAD_PUSHSTATE,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mLoadType == LOAD_PUSHSTATE)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mLoadType == LOAD_PUSHSTATE)
)), 0))) { do { } while (false); MOZ_ReportAssertionFailure("mLoadType == LOAD_PUSHSTATE"
" (" "This code only deals with pushState" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 12410); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mLoadType == LOAD_PUSHSTATE"
") (" "This code only deals with pushState" ")"); do { MOZ_CrashSequence
(__null, 12410); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
12410 "This code only deals with pushState")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mLoadType == LOAD_PUSHSTATE)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mLoadType == LOAD_PUSHSTATE)
)), 0))) { do { } while (false); MOZ_ReportAssertionFailure("mLoadType == LOAD_PUSHSTATE"
" (" "This code only deals with pushState" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 12410); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mLoadType == LOAD_PUSHSTATE"
") (" "This code only deals with pushState" ")"); do { MOZ_CrashSequence
(__null, 12410); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
12411 MOZ_ASSERT_IF(aPreviousScrollPos.isSome(), !aReplace)do { if (aPreviousScrollPos.isSome()) { do { static_assert( mozilla
::detail::AssertionConditionType<decltype(!aReplace)>::
isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!aReplace))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!aReplace", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 12411); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aReplace"
")"); do { MOZ_CrashSequence(__null, 12411); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false); } } while
(false)
;
12412
12413 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)
12414 ("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)
12415 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)
;
12416
12417 // Even if we're replacing an existing entry we create new a
12418 // SessionHistoryInfo. In the parent process we'll keep the existing
12419 // SessionHistoryEntry, but just replace its SessionHistoryInfo, that way the
12420 // entry keeps identity but its data is replaced.
12421 bool replace = aReplace && mActiveEntry;
12422
12423 if (!replace) {
12424 CollectWireframe();
12425 }
12426
12427 UniquePtr<SessionHistoryInfo> previousActiveEntry(mActiveEntry.release());
12428 if (previousActiveEntry) {
12429 // Link this entry to the previous active entry.
12430 mActiveEntry = MakeUnique<SessionHistoryInfo>(*previousActiveEntry, aURI);
12431 } else {
12432 mActiveEntry = MakeUnique<SessionHistoryInfo>(
12433 aURI, aTriggeringPrincipal, nullptr, nullptr, aCsp, mContentTypeHint);
12434 }
12435 mActiveEntry->SetOriginalURI(aOriginalURI);
12436 mActiveEntry->SetUnstrippedURI(nullptr);
12437 mActiveEntry->SetReferrerInfo(aReferrerInfo);
12438 mActiveEntry->SetTitle(aTitle);
12439 mActiveEntry->SetStateData(static_cast<nsStructuredCloneContainer*>(aData));
12440 mActiveEntry->SetURIWasModified(aURIWasModified);
12441 mActiveEntry->SetScrollRestorationIsManual(aScrollRestorationIsManual);
12442
12443 if (replace) {
12444 mBrowsingContext->ReplaceActiveSessionHistoryEntry(mActiveEntry.get());
12445 } else {
12446 mBrowsingContext->IncrementHistoryEntryCountForBrowsingContext();
12447 // FIXME We should probably just compute mChildOffset in the parent
12448 // instead of passing it over IPC here.
12449 mBrowsingContext->SetActiveSessionHistoryEntry(
12450 aPreviousScrollPos, mActiveEntry.get(), previousActiveEntry.get(),
12451 mLoadType,
12452 /* aCacheKey = */ 0);
12453 // FIXME Do we need to update mPreviousEntryIndex and mLoadedEntryIndex?
12454 }
12455}
12456
12457nsresult nsDocShell::LoadHistoryEntry(nsISHEntry* aEntry, uint32_t aLoadType,
12458 bool aUserActivation) {
12459 NS_ENSURE_TRUE(aEntry, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(aEntry)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aEntry" ") failed", nullptr
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 12459);
return NS_ERROR_FAILURE; } } while (false)
;
12460
12461 nsresult rv;
12462 RefPtr<nsDocShellLoadState> loadState;
12463 rv = aEntry->CreateLoadInfo(getter_AddRefs(loadState));
12464 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 12464); return rv; } } while (false)
;
12465
12466 // Calling CreateAboutBlankDocumentViewer can set mOSHE to null, and if
12467 // that's the only thing holding a ref to aEntry that will cause aEntry to
12468 // die while we're loading it. So hold a strong ref to aEntry here, just
12469 // in case.
12470 nsCOMPtr<nsISHEntry> kungFuDeathGrip(aEntry);
12471
12472 loadState->SetHasValidUserGestureActivation(
12473 loadState->HasValidUserGestureActivation() || aUserActivation);
12474
12475 loadState->SetTextDirectiveUserActivation(
12476 loadState->GetTextDirectiveUserActivation() || aUserActivation);
12477
12478 return LoadHistoryEntry(loadState, aLoadType, aEntry == mOSHE);
12479}
12480
12481nsresult nsDocShell::LoadHistoryEntry(const LoadingSessionHistoryInfo& aEntry,
12482 uint32_t aLoadType,
12483 bool aUserActivation) {
12484 RefPtr<nsDocShellLoadState> loadState = aEntry.CreateLoadInfo();
12485 loadState->SetHasValidUserGestureActivation(
12486 loadState->HasValidUserGestureActivation() || aUserActivation);
12487
12488 loadState->SetTextDirectiveUserActivation(
12489 loadState->GetTextDirectiveUserActivation() || aUserActivation);
12490
12491 return LoadHistoryEntry(loadState, aLoadType, aEntry.mLoadingCurrentEntry);
12492}
12493
12494void nsDocShell::MaybeFireTraverseHistory(nsDocShellLoadState* aLoadState) {
12495 if (!Navigation::IsAPIEnabled()) {
12496 return;
12497 }
12498
12499 BrowsingContext* browsingContext = GetBrowsingContext();
12500 if (!browsingContext || !browsingContext->IsTop()) {
12501 return;
12502 }
12503 if (!mActiveEntry) {
12504 return;
12505 }
12506
12507 if (aLoadState->GetLoadingSessionHistoryInfo()->mInfo.SharedId() ==
12508 mActiveEntry->SharedId()) {
12509 return;
12510 }
12511
12512 nsCOMPtr<nsIPrincipal> oldPrincipal =
12513 aLoadState->GetLoadingSessionHistoryInfo()->mInfo.GetResultPrincipalURI()
12514 ? BasePrincipal::CreateContentPrincipal(
12515 aLoadState->GetLoadingSessionHistoryInfo()
12516 ->mInfo.GetResultPrincipalURI(),
12517 OriginAttributes{})
12518 : nullptr;
12519
12520 nsCOMPtr<nsIPrincipal> currentPrincipal =
12521 mActiveEntry->GetResultPrincipalURI()
12522 ? BasePrincipal::CreateContentPrincipal(
12523 mActiveEntry->GetResultPrincipalURI(), OriginAttributes{})
12524 : nullptr;
12525 if (!oldPrincipal || !currentPrincipal) {
12526 // TODO it's not clear why these can be null https://bugzil.la/1976017
12527 return;
12528 }
12529
12530 if (!oldPrincipal->Equals(currentPrincipal)) {
12531 return;
12532 }
12533
12534 if (RefPtr window = GetActiveWindow()) {
12535 if (RefPtr navigation = window->Navigation()) {
12536 if (AutoJSAPI jsapi; jsapi.Init(window)) {
12537 // This should send the correct user involvment. See bug 1903552.
12538 navigation->FireTraverseNavigateEvent(
12539 jsapi.cx(), aLoadState->GetLoadingSessionHistoryInfo()->mInfo,
12540 Nothing());
12541 }
12542 }
12543 }
12544}
12545
12546nsresult nsDocShell::LoadHistoryEntry(nsDocShellLoadState* aLoadState,
12547 uint32_t aLoadType,
12548 bool aLoadingCurrentEntry) {
12549 if (!IsNavigationAllowed()) {
12550 return NS_OK;
12551 }
12552
12553 // We are setting load type afterwards so we don't have to
12554 // send it in an IPC message
12555 aLoadState->SetLoadType(aLoadType);
12556
12557 SetOngoingNavigation(Some(OngoingNavigation::Traversal));
12558
12559 nsresult rv;
12560 if (aLoadState->URI()->SchemeIs("javascript")) {
12561 // We're loading a URL that will execute script from inside asyncOpen.
12562 // Replace the current document with about:blank now to prevent
12563 // anything from the current document from leaking into any JavaScript
12564 // code in the URL.
12565 // Don't cache the presentation if we're going to just reload the
12566 // current entry. Caching would lead to trying to save the different
12567 // content viewers in the same nsISHEntry object.
12568 rv = CreateAboutBlankDocumentViewer(
12569 aLoadState->PrincipalToInherit(),
12570 aLoadState->PartitionedPrincipalToInherit(), nullptr, nullptr,
12571 /* aIsInitialDocument */ false, Nothing(), !aLoadingCurrentEntry);
12572
12573 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
12574 // The creation of the intermittent about:blank content
12575 // viewer failed for some reason (potentially because the
12576 // user prevented it). Interrupt the history load.
12577 return NS_OK;
12578 }
12579
12580 if (!aLoadState->TriggeringPrincipal()) {
12581 // Ensure that we have a triggeringPrincipal. Otherwise javascript:
12582 // URIs will pick it up from the about:blank page we just loaded,
12583 // and we don't really want even that in this case.
12584 nsCOMPtr<nsIPrincipal> principal =
12585 NullPrincipal::Create(GetOriginAttributes());
12586 aLoadState->SetTriggeringPrincipal(principal);
12587 }
12588 }
12589
12590 /* If there is a valid postdata *and* the user pressed
12591 * reload or shift-reload, take user's permission before we
12592 * repost the data to the server.
12593 */
12594 if ((aLoadType & LOAD_CMD_RELOAD) && aLoadState->PostDataStream()) {
12595 bool repost;
12596 rv = ConfirmRepost(&repost);
12597 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
12598 return rv;
12599 }
12600
12601 // If the user pressed cancel in the dialog, return. We're done here.
12602 if (!repost) {
12603 return NS_BINDING_ABORTED;
12604 }
12605 }
12606
12607 // If there is no valid triggeringPrincipal, we deny the load
12608 MOZ_ASSERT(aLoadState->TriggeringPrincipal(),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aLoadState->TriggeringPrincipal())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aLoadState->TriggeringPrincipal
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("aLoadState->TriggeringPrincipal()" " (" "need a valid triggeringPrincipal to load from history"
")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 12609
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->TriggeringPrincipal()"
") (" "need a valid triggeringPrincipal to load from history"
")"); do { MOZ_CrashSequence(__null, 12609); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
12609 "need a valid triggeringPrincipal to load from history")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aLoadState->TriggeringPrincipal())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aLoadState->TriggeringPrincipal
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("aLoadState->TriggeringPrincipal()" " (" "need a valid triggeringPrincipal to load from history"
")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 12609
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->TriggeringPrincipal()"
") (" "need a valid triggeringPrincipal to load from history"
")"); do { MOZ_CrashSequence(__null, 12609); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12610 if (!aLoadState->TriggeringPrincipal()) {
12611 return NS_ERROR_FAILURE;
12612 }
12613
12614 MaybeFireTraverseHistory(aLoadState);
12615
12616 return InternalLoad(aLoadState); // No nsIRequest
12617}
12618
12619NS_IMETHODIMPnsresult
12620nsDocShell::PersistLayoutHistoryState() {
12621 nsresult rv = NS_OK;
12622
12623 if (mozilla::SessionHistoryInParent() ? !!mActiveEntry : !!mOSHE) {
12624 bool scrollRestorationIsManual;
12625 if (mozilla::SessionHistoryInParent()) {
12626 scrollRestorationIsManual = mActiveEntry->GetScrollRestorationIsManual();
12627 } else {
12628 scrollRestorationIsManual = mOSHE->GetScrollRestorationIsManual();
12629 }
12630 nsCOMPtr<nsILayoutHistoryState> layoutState;
12631 if (RefPtr<PresShell> presShell = GetPresShell()) {
12632 rv = presShell->CaptureHistoryState(getter_AddRefs(layoutState));
12633 } else if (scrollRestorationIsManual) {
12634 // Even if we don't have layout anymore, we may want to reset the
12635 // current scroll state in layout history.
12636 GetLayoutHistoryState(getter_AddRefs(layoutState));
12637 }
12638
12639 if (scrollRestorationIsManual && layoutState) {
12640 layoutState->ResetScrollState();
12641 }
12642 }
12643
12644 return rv;
12645}
12646
12647void nsDocShell::SwapHistoryEntries(nsISHEntry* aOldEntry,
12648 nsISHEntry* aNewEntry) {
12649 if (aOldEntry == mOSHE) {
12650 mOSHE = aNewEntry;
12651 }
12652
12653 if (aOldEntry == mLSHE) {
12654 mLSHE = aNewEntry;
12655 }
12656}
12657
12658void nsDocShell::SetHistoryEntryAndUpdateBC(const Maybe<nsISHEntry*>& aLSHE,
12659 const Maybe<nsISHEntry*>& aOSHE) {
12660 // We want to hold on to the reference in mLSHE before we update it.
12661 // Otherwise, SetHistoryEntry could release the last reference to
12662 // the entry while aOSHE is pointing to it.
12663 nsCOMPtr<nsISHEntry> deathGripOldLSHE;
12664 if (aLSHE.isSome()) {
12665 deathGripOldLSHE = SetHistoryEntry(&mLSHE, aLSHE.value());
12666 MOZ_ASSERT(mLSHE.get() == aLSHE.value())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mLSHE.get() == aLSHE.value())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mLSHE.get() == aLSHE.value()
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"mLSHE.get() == aLSHE.value()", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 12666); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mLSHE.get() == aLSHE.value()"
")"); do { MOZ_CrashSequence(__null, 12666); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12667 }
12668 nsCOMPtr<nsISHEntry> deathGripOldOSHE;
12669 if (aOSHE.isSome()) {
12670 deathGripOldOSHE = SetHistoryEntry(&mOSHE, aOSHE.value());
12671 MOZ_ASSERT(mOSHE.get() == aOSHE.value())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mOSHE.get() == aOSHE.value())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mOSHE.get() == aOSHE.value()
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"mOSHE.get() == aOSHE.value()", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 12671); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mOSHE.get() == aOSHE.value()"
")"); do { MOZ_CrashSequence(__null, 12671); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12672 }
12673}
12674
12675already_AddRefed<nsISHEntry> nsDocShell::SetHistoryEntry(
12676 nsCOMPtr<nsISHEntry>* aPtr, nsISHEntry* aEntry) {
12677 // We need to sync up the docshell and session history trees for
12678 // subframe navigation. If the load was in a subframe, we forward up to
12679 // the root docshell, which will then recursively sync up all docshells
12680 // to their corresponding entries in the new session history tree.
12681 // If we don't do this, then we can cache a content viewer on the wrong
12682 // cloned entry, and subsequently restore it at the wrong time.
12683 RefPtr<BrowsingContext> topBC = mBrowsingContext->Top();
12684 if (topBC->IsDiscarded()) {
12685 topBC = nullptr;
12686 }
12687 RefPtr<BrowsingContext> currBC =
12688 mBrowsingContext->IsDiscarded() ? nullptr : mBrowsingContext;
12689 if (topBC && *aPtr) {
12690 (*aPtr)->SyncTreesForSubframeNavigation(aEntry, topBC, currBC);
12691 }
12692 nsCOMPtr<nsISHEntry> entry(aEntry);
12693 entry.swap(*aPtr);
12694 return entry.forget();
12695}
12696
12697already_AddRefed<ChildSHistory> nsDocShell::GetRootSessionHistory() {
12698 RefPtr<ChildSHistory> childSHistory =
12699 mBrowsingContext->Top()->GetChildSessionHistory();
12700 return childSHistory.forget();
12701}
12702
12703nsresult nsDocShell::GetHttpChannel(nsIChannel* aChannel,
12704 nsIHttpChannel** aReturn) {
12705 NS_ENSURE_ARG_POINTER(aReturn)do { if ((__builtin_expect(!!(!(aReturn)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aReturn" ") failed", nullptr
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 12705);
return NS_ERROR_INVALID_POINTER; } } while (false)
;
12706 if (!aChannel) {
12707 return NS_ERROR_FAILURE;
12708 }
12709
12710 nsCOMPtr<nsIMultiPartChannel> multiPartChannel(do_QueryInterface(aChannel));
12711 if (multiPartChannel) {
12712 nsCOMPtr<nsIChannel> baseChannel;
12713 multiPartChannel->GetBaseChannel(getter_AddRefs(baseChannel));
12714 nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(baseChannel));
12715 *aReturn = httpChannel;
12716 NS_IF_ADDREF(*aReturn)ns_if_addref(*aReturn);
12717 }
12718 return NS_OK;
12719}
12720
12721bool nsDocShell::ShouldDiscardLayoutState(nsIHttpChannel* aChannel) {
12722 // By default layout State will be saved.
12723 if (!aChannel) {
12724 return false;
12725 }
12726
12727 // figure out if SH should be saving layout state
12728 bool noStore = false;
12729 Unused << aChannel->IsNoStoreResponse(&noStore);
12730 return noStore;
12731}
12732
12733NS_IMETHODIMPnsresult
12734nsDocShell::GetEditor(nsIEditor** aEditor) {
12735 NS_ENSURE_ARG_POINTER(aEditor)do { if ((__builtin_expect(!!(!(aEditor)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aEditor" ") failed", nullptr
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 12735);
return NS_ERROR_INVALID_POINTER; } } while (false)
;
12736 RefPtr<HTMLEditor> htmlEditor = GetHTMLEditorInternal();
12737 htmlEditor.forget(aEditor);
12738 return NS_OK;
12739}
12740
12741NS_IMETHODIMPnsresult
12742nsDocShell::SetEditor(nsIEditor* aEditor) {
12743 HTMLEditor* htmlEditor = aEditor ? aEditor->GetAsHTMLEditor() : nullptr;
12744 // If TextEditor comes, throw an error.
12745 if (aEditor && !htmlEditor) {
12746 return NS_ERROR_INVALID_ARG;
12747 }
12748 return SetHTMLEditorInternal(htmlEditor);
12749}
12750
12751HTMLEditor* nsDocShell::GetHTMLEditorInternal() {
12752 return mEditorData ? mEditorData->GetHTMLEditor() : nullptr;
12753}
12754
12755nsresult nsDocShell::SetHTMLEditorInternal(HTMLEditor* aHTMLEditor) {
12756 if (!aHTMLEditor && !mEditorData) {
12757 return NS_OK;
12758 }
12759
12760 nsresult rv = EnsureEditorData();
12761 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
12762 return rv;
12763 }
12764
12765 return mEditorData->SetHTMLEditor(aHTMLEditor);
12766}
12767
12768NS_IMETHODIMPnsresult
12769nsDocShell::GetEditable(bool* aEditable) {
12770 NS_ENSURE_ARG_POINTER(aEditable)do { if ((__builtin_expect(!!(!(aEditable)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aEditable" ") failed", nullptr
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 12770);
return NS_ERROR_INVALID_POINTER; } } while (false)
;
12771 *aEditable = mEditorData && mEditorData->GetEditable();
12772 return NS_OK;
12773}
12774
12775NS_IMETHODIMPnsresult
12776nsDocShell::GetHasEditingSession(bool* aHasEditingSession) {
12777 NS_ENSURE_ARG_POINTER(aHasEditingSession)do { if ((__builtin_expect(!!(!(aHasEditingSession)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aHasEditingSession" ") failed"
, nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 12777); return NS_ERROR_INVALID_POINTER; } } while (false)
;
12778
12779 if (mEditorData) {
12780 *aHasEditingSession = !!mEditorData->GetEditingSession();
12781 } else {
12782 *aHasEditingSession = false;
12783 }
12784
12785 return NS_OK;
12786}
12787
12788NS_IMETHODIMPnsresult
12789nsDocShell::MakeEditable(bool aInWaitForUriLoad) {
12790 nsresult rv = EnsureEditorData();
12791 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
12792 return rv;
12793 }
12794
12795 return mEditorData->MakeEditable(aInWaitForUriLoad);
12796}
12797
12798/* static */ bool nsDocShell::ShouldAddURIVisit(nsIChannel* aChannel) {
12799 bool needToAddURIVisit = true;
12800 nsCOMPtr<nsIPropertyBag2> props(do_QueryInterface(aChannel));
12801 if (props) {
12802 mozilla::Unused << props->GetPropertyAsBool(
12803 u"docshell.needToAddURIVisit"_ns, &needToAddURIVisit);
12804 }
12805
12806 return needToAddURIVisit;
12807}
12808
12809/* static */ void nsDocShell::ExtractLastVisit(
12810 nsIChannel* aChannel, nsIURI** aURI, uint32_t* aChannelRedirectFlags) {
12811 nsCOMPtr<nsIPropertyBag2> props(do_QueryInterface(aChannel));
12812 if (!props) {
12813 return;
12814 }
12815
12816 nsresult rv;
12817 nsCOMPtr<nsIURI> uri(do_GetProperty(props, u"docshell.previousURI"_ns, &rv));
12818 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
12819 uri.forget(aURI);
12820
12821 rv = props->GetPropertyAsUint32(u"docshell.previousFlags"_ns,
12822 aChannelRedirectFlags);
12823
12824 NS_WARNING_ASSERTION(do { if (!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1
))))) { NS_DebugBreak(NS_DEBUG_WARNING, "Could not fetch previous flags, URI will be treated like referrer"
, "NS_SUCCEEDED(rv)", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 12826); } } while (false)
12825 NS_SUCCEEDED(rv),do { if (!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1
))))) { NS_DebugBreak(NS_DEBUG_WARNING, "Could not fetch previous flags, URI will be treated like referrer"
, "NS_SUCCEEDED(rv)", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 12826); } } while (false)
12826 "Could not fetch previous flags, URI will be treated like referrer")do { if (!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1
))))) { NS_DebugBreak(NS_DEBUG_WARNING, "Could not fetch previous flags, URI will be treated like referrer"
, "NS_SUCCEEDED(rv)", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 12826); } } while (false)
;
12827
12828 } else {
12829 // There is no last visit for this channel, so this must be the first
12830 // link. Link the visit to the referrer of this request, if any.
12831 // Treat referrer as null if there is an error getting it.
12832 NS_GetReferrerFromChannel(aChannel, aURI);
12833 }
12834}
12835
12836void nsDocShell::SaveLastVisit(nsIChannel* aChannel, nsIURI* aURI,
12837 uint32_t aChannelRedirectFlags) {
12838 nsCOMPtr<nsIWritablePropertyBag2> props(do_QueryInterface(aChannel));
12839 if (!props || !aURI) {
12840 return;
12841 }
12842
12843 props->SetPropertyAsInterface(u"docshell.previousURI"_ns, aURI);
12844 props->SetPropertyAsUint32(u"docshell.previousFlags"_ns,
12845 aChannelRedirectFlags);
12846}
12847
12848/* static */ void nsDocShell::InternalAddURIVisit(
12849 nsIURI* aURI, nsIURI* aPreviousURI, uint32_t aChannelRedirectFlags,
12850 uint32_t aResponseStatus, BrowsingContext* aBrowsingContext,
12851 nsIWidget* aWidget, uint32_t aLoadType, bool aWasUpgraded) {
12852 MOZ_ASSERT(aURI, "Visited URI is null!")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aURI)>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(aURI))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("aURI" " (" "Visited URI is null!"
")", "/root/firefox-clang/docshell/base/nsDocShell.cpp", 12852
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aURI" ") (" "Visited URI is null!"
")"); do { MOZ_CrashSequence(__null, 12852); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12853 MOZ_ASSERT(aLoadType != LOAD_ERROR_PAGE && aLoadType != LOAD_BYPASS_HISTORY,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aLoadType != LOAD_ERROR_PAGE && aLoadType !=
LOAD_BYPASS_HISTORY)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aLoadType != LOAD_ERROR_PAGE
&& aLoadType != LOAD_BYPASS_HISTORY))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("aLoadType != LOAD_ERROR_PAGE && aLoadType != LOAD_BYPASS_HISTORY"
" (" "Do not add error or bypass pages to global history" ")"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 12854);
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, 12854); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
12854 "Do not add error or bypass pages to global history")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aLoadType != LOAD_ERROR_PAGE && aLoadType !=
LOAD_BYPASS_HISTORY)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aLoadType != LOAD_ERROR_PAGE
&& aLoadType != LOAD_BYPASS_HISTORY))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("aLoadType != LOAD_ERROR_PAGE && aLoadType != LOAD_BYPASS_HISTORY"
" (" "Do not add error or bypass pages to global history" ")"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 12854);
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, 12854); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
12855
12856 bool usePrivateBrowsing = false;
12857 aBrowsingContext->GetUsePrivateBrowsing(&usePrivateBrowsing);
12858
12859 // Only content-type docshells save URI visits. Also don't do
12860 // anything here if we're not supposed to use global history.
12861 if (!aBrowsingContext->IsContent() ||
12862 !aBrowsingContext->GetUseGlobalHistory() || usePrivateBrowsing) {
12863 return;
12864 }
12865
12866 nsCOMPtr<IHistory> history = components::History::Service();
12867
12868 if (history) {
12869 uint32_t visitURIFlags = 0;
12870
12871 if (aBrowsingContext->IsTop()) {
12872 visitURIFlags |= IHistory::TOP_LEVEL;
12873 }
12874
12875 if (aChannelRedirectFlags & nsIChannelEventSink::REDIRECT_TEMPORARY) {
12876 visitURIFlags |= IHistory::REDIRECT_TEMPORARY;
12877 } else if (aChannelRedirectFlags &
12878 nsIChannelEventSink::REDIRECT_PERMANENT) {
12879 visitURIFlags |= IHistory::REDIRECT_PERMANENT;
12880 } else {
12881 MOZ_ASSERT(!aChannelRedirectFlags,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aChannelRedirectFlags)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!aChannelRedirectFlags))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("!aChannelRedirectFlags"
" (" "One of REDIRECT_TEMPORARY or REDIRECT_PERMANENT must be set "
"if any flags in aChannelRedirectFlags is set." ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 12883); 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, 12883); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
12882 "One of REDIRECT_TEMPORARY or REDIRECT_PERMANENT must be set "do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aChannelRedirectFlags)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!aChannelRedirectFlags))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("!aChannelRedirectFlags"
" (" "One of REDIRECT_TEMPORARY or REDIRECT_PERMANENT must be set "
"if any flags in aChannelRedirectFlags is set." ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 12883); 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, 12883); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
12883 "if any flags in aChannelRedirectFlags is set.")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aChannelRedirectFlags)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!aChannelRedirectFlags))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("!aChannelRedirectFlags"
" (" "One of REDIRECT_TEMPORARY or REDIRECT_PERMANENT must be set "
"if any flags in aChannelRedirectFlags is set." ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 12883); 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, 12883); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
12884 }
12885
12886 if (aResponseStatus >= 300 && aResponseStatus < 400) {
12887 visitURIFlags |= IHistory::REDIRECT_SOURCE;
12888 if (aResponseStatus == 301 || aResponseStatus == 308) {
12889 visitURIFlags |= IHistory::REDIRECT_SOURCE_PERMANENT;
12890 }
12891 }
12892 // Errors 400-501 and 505 are considered unrecoverable, in the sense a
12893 // simple retry attempt by the user is unlikely to solve them.
12894 // 408 is special cased, since may actually indicate a temporary
12895 // connection problem.
12896 else if (aResponseStatus != 408 &&
12897 ((aResponseStatus >= 400 && aResponseStatus <= 501) ||
12898 aResponseStatus == 505)) {
12899 visitURIFlags |= IHistory::UNRECOVERABLE_ERROR;
12900 }
12901
12902 if (aWasUpgraded) {
12903 visitURIFlags |=
12904 IHistory::REDIRECT_SOURCE | IHistory::REDIRECT_SOURCE_UPGRADED;
12905 }
12906
12907 mozilla::Unused << history->VisitURI(aWidget, aURI, aPreviousURI,
12908 visitURIFlags,
12909 aBrowsingContext->BrowserId());
12910 }
12911}
12912
12913void nsDocShell::AddURIVisit(nsIURI* aURI, nsIURI* aPreviousURI,
12914 uint32_t aChannelRedirectFlags,
12915 uint32_t aResponseStatus) {
12916 nsPIDOMWindowOuter* outer = GetWindow();
12917 nsCOMPtr<nsIWidget> widget = widget::WidgetUtils::DOMWindowToWidget(outer);
12918
12919 InternalAddURIVisit(aURI, aPreviousURI, aChannelRedirectFlags,
12920 aResponseStatus, mBrowsingContext, widget, mLoadType,
12921 false);
12922}
12923
12924//*****************************************************************************
12925// nsDocShell: Helper Routines
12926//*****************************************************************************
12927
12928NS_IMETHODIMPnsresult
12929nsDocShell::SetLoadType(uint32_t aLoadType) {
12930 mLoadType = aLoadType;
12931 return NS_OK;
12932}
12933
12934NS_IMETHODIMPnsresult
12935nsDocShell::GetLoadType(uint32_t* aLoadType) {
12936 *aLoadType = mLoadType;
12937 return NS_OK;
12938}
12939
12940nsresult nsDocShell::ConfirmRepost(bool* aRepost) {
12941 if (StaticPrefs::dom_confirm_repost_testing_always_accept()) {
12942 *aRepost = true;
12943 return NS_OK;
12944 }
12945
12946 nsCOMPtr<nsIPromptCollection> prompter =
12947 do_GetService("@mozilla.org/embedcomp/prompt-collection;1");
12948 if (!prompter) {
12949 return NS_ERROR_NOT_AVAILABLE;
12950 }
12951
12952 return prompter->ConfirmRepost(mBrowsingContext, aRepost);
12953}
12954
12955nsresult nsDocShell::GetPromptAndStringBundle(nsIPrompt** aPrompt,
12956 nsIStringBundle** aStringBundle) {
12957 NS_ENSURE_SUCCESS(GetInterface(NS_GET_IID(nsIPrompt), (void**)aPrompt),do { nsresult __rv = GetInterface((nsIPrompt::kIID), (void**)
aPrompt); if (((bool)(__builtin_expect(!!(NS_FAILED_impl(__rv
)), 0)))) { const char* name = mozilla::GetStaticErrorName(__rv
); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "GetInterface((nsIPrompt::kIID), (void**)aPrompt)"
, "NS_ERROR_FAILURE", static_cast<uint32_t>(__rv), name
? " (" : "", name ? name : "", name ? ")" : ""); NS_DebugBreak
(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 12958); return NS_ERROR_FAILURE; } } while (false)
12958 NS_ERROR_FAILURE)do { nsresult __rv = GetInterface((nsIPrompt::kIID), (void**)
aPrompt); if (((bool)(__builtin_expect(!!(NS_FAILED_impl(__rv
)), 0)))) { const char* name = mozilla::GetStaticErrorName(__rv
); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "GetInterface((nsIPrompt::kIID), (void**)aPrompt)"
, "NS_ERROR_FAILURE", static_cast<uint32_t>(__rv), name
? " (" : "", name ? name : "", name ? ")" : ""); NS_DebugBreak
(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 12958); return NS_ERROR_FAILURE; } } while (false)
;
12959
12960 nsCOMPtr<nsIStringBundleService> stringBundleService =
12961 mozilla::components::StringBundle::Service();
12962 NS_ENSURE_TRUE(stringBundleService, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(stringBundleService)), 0))) {
NS_DebugBreak(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "stringBundleService"
") failed", nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 12962); return NS_ERROR_FAILURE; } } while (false)
;
12963
12964 NS_ENSURE_SUCCESS(do { nsresult __rv = stringBundleService->CreateBundle(kAppstringsBundleURL
, aStringBundle); if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "stringBundleService->CreateBundle(kAppstringsBundleURL, aStringBundle)"
, "NS_ERROR_FAILURE", static_cast<uint32_t>(__rv), name
? " (" : "", name ? name : "", name ? ")" : ""); NS_DebugBreak
(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 12966); return NS_ERROR_FAILURE; } } while (false)
12965 stringBundleService->CreateBundle(kAppstringsBundleURL, aStringBundle),do { nsresult __rv = stringBundleService->CreateBundle(kAppstringsBundleURL
, aStringBundle); if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "stringBundleService->CreateBundle(kAppstringsBundleURL, aStringBundle)"
, "NS_ERROR_FAILURE", static_cast<uint32_t>(__rv), name
? " (" : "", name ? name : "", name ? ")" : ""); NS_DebugBreak
(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 12966); return NS_ERROR_FAILURE; } } while (false)
12966 NS_ERROR_FAILURE)do { nsresult __rv = stringBundleService->CreateBundle(kAppstringsBundleURL
, aStringBundle); if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "stringBundleService->CreateBundle(kAppstringsBundleURL, aStringBundle)"
, "NS_ERROR_FAILURE", static_cast<uint32_t>(__rv), name
? " (" : "", name ? name : "", name ? ")" : ""); NS_DebugBreak
(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 12966); return NS_ERROR_FAILURE; } } while (false)
;
12967
12968 return NS_OK;
12969}
12970
12971ScrollContainerFrame* nsDocShell::GetRootScrollContainerFrame() {
12972 PresShell* presShell = GetPresShell();
12973 NS_ENSURE_TRUE(presShell, nullptr)do { if ((__builtin_expect(!!(!(presShell)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "presShell" ") failed", nullptr
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 12973);
return nullptr; } } while (false)
;
12974
12975 return presShell->GetRootScrollContainerFrame();
12976}
12977
12978nsresult nsDocShell::EnsureScriptEnvironment() {
12979 if (mScriptGlobal) {
12980 return NS_OK;
12981 }
12982
12983 if (mIsBeingDestroyed) {
12984 return NS_ERROR_NOT_AVAILABLE;
12985 }
12986
12987#ifdef DEBUG1
12988 NS_ASSERTION(!mInEnsureScriptEnv,do { if (!(!mInEnsureScriptEnv)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "Infinite loop! Calling EnsureScriptEnvironment() from " "within EnsureScriptEnvironment()!"
, "!mInEnsureScriptEnv", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 12990); MOZ_PretendNoReturn(); } } while (0)
12989 "Infinite loop! Calling EnsureScriptEnvironment() from "do { if (!(!mInEnsureScriptEnv)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "Infinite loop! Calling EnsureScriptEnvironment() from " "within EnsureScriptEnvironment()!"
, "!mInEnsureScriptEnv", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 12990); MOZ_PretendNoReturn(); } } while (0)
12990 "within EnsureScriptEnvironment()!")do { if (!(!mInEnsureScriptEnv)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "Infinite loop! Calling EnsureScriptEnvironment() from " "within EnsureScriptEnvironment()!"
, "!mInEnsureScriptEnv", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 12990); MOZ_PretendNoReturn(); } } while (0)
;
12991
12992 // Yeah, this isn't re-entrant safe, but that's ok since if we
12993 // re-enter this method, we'll infinitely loop...
12994 AutoRestore<bool> boolSetter(mInEnsureScriptEnv);
12995 mInEnsureScriptEnv = true;
12996#endif
12997
12998 nsCOMPtr<nsIWebBrowserChrome> browserChrome(do_GetInterface(mTreeOwner));
12999 NS_ENSURE_TRUE(browserChrome, NS_ERROR_NOT_AVAILABLE)do { if ((__builtin_expect(!!(!(browserChrome)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "browserChrome" ") failed"
, nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 12999); return NS_ERROR_NOT_AVAILABLE; } } while (false)
;
13000
13001 uint32_t chromeFlags;
13002 browserChrome->GetChromeFlags(&chromeFlags);
13003
13004 // If our window is modal and we're not opened as chrome, make
13005 // this window a modal content window.
13006 mScriptGlobal = nsGlobalWindowOuter::Create(this, mItemType == typeChrome);
13007 MOZ_ASSERT(mScriptGlobal)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mScriptGlobal)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mScriptGlobal))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("mScriptGlobal",
"/root/firefox-clang/docshell/base/nsDocShell.cpp", 13007); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "mScriptGlobal" ")"); do { MOZ_CrashSequence
(__null, 13007); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
13008
13009 // Ensure the script object is set up to run script.
13010 return mScriptGlobal->EnsureScriptEnvironment();
13011}
13012
13013nsresult nsDocShell::EnsureEditorData() {
13014 MOZ_ASSERT(!mIsBeingDestroyed)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mIsBeingDestroyed)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mIsBeingDestroyed))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("!mIsBeingDestroyed"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 13014);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mIsBeingDestroyed"
")"); do { MOZ_CrashSequence(__null, 13014); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
13015
13016 bool openDocHasDetachedEditor = mOSHE && mOSHE->HasDetachedEditor();
13017 if (!mEditorData && !mIsBeingDestroyed && !openDocHasDetachedEditor) {
13018 // We shouldn't recreate the editor data if it already exists, or
13019 // we're shutting down, or we already have a detached editor data
13020 // stored in the session history. We should only have one editordata
13021 // per docshell.
13022 mEditorData = MakeUnique<nsDocShellEditorData>(this);
13023 }
13024
13025 return mEditorData ? NS_OK : NS_ERROR_NOT_AVAILABLE;
13026}
13027
13028nsresult nsDocShell::EnsureFind() {
13029 if (!mFind) {
13030 mFind = new nsWebBrowserFind();
13031 }
13032
13033 // we promise that the nsIWebBrowserFind that we return has been set
13034 // up to point to the focused, or content window, so we have to
13035 // set that up each time.
13036
13037 nsIScriptGlobalObject* scriptGO = GetScriptGlobalObject();
13038 NS_ENSURE_TRUE(scriptGO, NS_ERROR_UNEXPECTED)do { if ((__builtin_expect(!!(!(scriptGO)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "scriptGO" ") failed", nullptr
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 13038);
return NS_ERROR_UNEXPECTED; } } while (false)
;
13039
13040 // default to our window
13041 nsCOMPtr<nsPIDOMWindowOuter> ourWindow = do_QueryInterface(scriptGO);
13042 nsCOMPtr<nsPIDOMWindowOuter> windowToSearch;
13043 nsFocusManager::GetFocusedDescendant(ourWindow,
13044 nsFocusManager::eIncludeAllDescendants,
13045 getter_AddRefs(windowToSearch));
13046
13047 nsCOMPtr<nsIWebBrowserFindInFrames> findInFrames = do_QueryInterface(mFind);
13048 if (!findInFrames) {
13049 return NS_ERROR_NO_INTERFACE;
13050 }
13051
13052 nsresult rv = findInFrames->SetRootSearchFrame(ourWindow);
13053 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
13054 return rv;
13055 }
13056 rv = findInFrames->SetCurrentSearchFrame(windowToSearch);
13057 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
13058 return rv;
13059 }
13060
13061 return NS_OK;
13062}
13063
13064NS_IMETHODIMPnsresult
13065nsDocShell::IsBeingDestroyed(bool* aDoomed) {
13066 NS_ENSURE_ARG(aDoomed)do { if ((__builtin_expect(!!(!(aDoomed)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aDoomed" ") failed", nullptr
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 13066);
return NS_ERROR_INVALID_ARG; } } while (false)
;
13067 *aDoomed = mIsBeingDestroyed;
13068 return NS_OK;
13069}
13070
13071NS_IMETHODIMPnsresult
13072nsDocShell::GetIsExecutingOnLoadHandler(bool* aResult) {
13073 NS_ENSURE_ARG(aResult)do { if ((__builtin_expect(!!(!(aResult)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aResult" ") failed", nullptr
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 13073);
return NS_ERROR_INVALID_ARG; } } while (false)
;
13074 *aResult = mIsExecutingOnLoadHandler;
13075 return NS_OK;
13076}
13077
13078NS_IMETHODIMPnsresult
13079nsDocShell::GetLayoutHistoryState(nsILayoutHistoryState** aLayoutHistoryState) {
13080 nsCOMPtr<nsILayoutHistoryState> state;
13081 if (mozilla::SessionHistoryInParent()) {
13082 if (mActiveEntry) {
13083 state = mActiveEntry->GetLayoutHistoryState();
13084 }
13085 } else {
13086 if (mOSHE) {
13087 state = mOSHE->GetLayoutHistoryState();
13088 }
13089 }
13090 state.forget(aLayoutHistoryState);
13091 return NS_OK;
13092}
13093
13094NS_IMETHODIMPnsresult
13095nsDocShell::SetLayoutHistoryState(nsILayoutHistoryState* aLayoutHistoryState) {
13096 if (mOSHE) {
13097 mOSHE->SetLayoutHistoryState(aLayoutHistoryState);
13098 }
13099 if (mActiveEntry) {
13100 mActiveEntry->SetLayoutHistoryState(aLayoutHistoryState);
13101 }
13102 return NS_OK;
13103}
13104
13105nsDocShell::InterfaceRequestorProxy::InterfaceRequestorProxy(
13106 nsIInterfaceRequestor* aRequestor) {
13107 if (aRequestor) {
13108 mWeakPtr = do_GetWeakReference(aRequestor);
13109 }
13110}
13111
13112nsDocShell::InterfaceRequestorProxy::~InterfaceRequestorProxy() {
13113 mWeakPtr = nullptr;
13114}
13115
13116NS_IMPL_ISUPPORTS(nsDocShell::InterfaceRequestorProxy, nsIInterfaceRequestor)MozExternalRefCountType nsDocShell::InterfaceRequestorProxy::
AddRef(void) { static_assert(!std::is_destructible_v<nsDocShell
::InterfaceRequestorProxy>, "Reference-counted class " "nsDocShell::InterfaceRequestorProxy"
" should not have a public destructor. " "Make this class's destructor non-public"
); do { static_assert( mozilla::detail::AssertionConditionType
<decltype(int32_t(mRefCnt) >= 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) >= 0))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) >= 0"
" (" "illegal refcnt" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 13116); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { MOZ_CrashSequence(__null, 13116
); __attribute__((nomerge)) ::abort(); } while (false); } } while
(false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("nsDocShell::InterfaceRequestorProxy" != nullptr
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!("nsDocShell::InterfaceRequestorProxy" != nullptr))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("\"nsDocShell::InterfaceRequestorProxy\" != nullptr"
" (" "Must specify a name" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 13116); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"nsDocShell::InterfaceRequestorProxy\" != nullptr"
") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__null
, 13116); __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread
.AssertOwnership("nsDocShell::InterfaceRequestorProxy" " not thread-safe"
); nsrefcnt count = ++mRefCnt; NS_LogAddRef((this), (count), (
"nsDocShell::InterfaceRequestorProxy"), (uint32_t)(sizeof(*this
))); return count; } MozExternalRefCountType nsDocShell::InterfaceRequestorProxy
::Release(void) { do { static_assert( mozilla::detail::AssertionConditionType
<decltype(int32_t(mRefCnt) > 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) > 0))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) > 0"
" (" "dup release" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 13116); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { MOZ_CrashSequence(__null, 13116
); __attribute__((nomerge)) ::abort(); } while (false); } } while
(false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("nsDocShell::InterfaceRequestorProxy" != nullptr
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!("nsDocShell::InterfaceRequestorProxy" != nullptr))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("\"nsDocShell::InterfaceRequestorProxy\" != nullptr"
" (" "Must specify a name" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 13116); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"nsDocShell::InterfaceRequestorProxy\" != nullptr"
") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__null
, 13116); __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread
.AssertOwnership("nsDocShell::InterfaceRequestorProxy" " not thread-safe"
); const char* const nametmp = "nsDocShell::InterfaceRequestorProxy"
; nsrefcnt count = --mRefCnt; NS_LogRelease((this), (count), (
nametmp)); if (count == 0) { mRefCnt = 1; delete (this); return
0; } return count; } nsresult nsDocShell::InterfaceRequestorProxy
::QueryInterface(const nsIID& aIID, void** aInstancePtr) {
do { if (!(aInstancePtr)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "QueryInterface requires a non-NULL destination!", "aInstancePtr"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 13116);
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; }
13117
13118NS_IMETHODIMPnsresult
13119nsDocShell::InterfaceRequestorProxy::GetInterface(const nsIID& aIID,
13120 void** aSink) {
13121 NS_ENSURE_ARG_POINTER(aSink)do { if ((__builtin_expect(!!(!(aSink)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aSink" ") failed", nullptr
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 13121);
return NS_ERROR_INVALID_POINTER; } } while (false)
;
13122 nsCOMPtr<nsIInterfaceRequestor> ifReq = do_QueryReferent(mWeakPtr);
13123 if (ifReq) {
13124 return ifReq->GetInterface(aIID, aSink);
13125 }
13126 *aSink = nullptr;
13127 return NS_NOINTERFACE;
13128}
13129
13130//*****************************************************************************
13131// nsDocShell::nsIAuthPromptProvider
13132//*****************************************************************************
13133
13134NS_IMETHODIMPnsresult
13135nsDocShell::GetAuthPrompt(uint32_t aPromptReason, const nsIID& aIID,
13136 void** aResult) {
13137 // a priority prompt request will override a false mAllowAuth setting
13138 bool priorityPrompt = (aPromptReason == PROMPT_PROXY);
13139
13140 if (!mAllowAuth && !priorityPrompt) {
13141 return NS_ERROR_NOT_AVAILABLE;
13142 }
13143
13144 // we're either allowing auth, or it's a proxy request
13145 nsresult rv;
13146 nsCOMPtr<nsIPromptFactory> wwatch =
13147 do_GetService(NS_WINDOWWATCHER_CONTRACTID"@mozilla.org/embedcomp/window-watcher;1", &rv);
13148 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 13148); return rv; } } while (false)
;
13149
13150 rv = EnsureScriptEnvironment();
13151 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 13151); return rv; } } while (false)
;
13152
13153 // Get the an auth prompter for our window so that the parenting
13154 // of the dialogs works as it should when using tabs.
13155
13156 return wwatch->GetPrompt(mScriptGlobal, aIID,
13157 reinterpret_cast<void**>(aResult));
13158}
13159
13160//*****************************************************************************
13161// nsDocShell::nsILoadContext
13162//*****************************************************************************
13163
13164NS_IMETHODIMPnsresult
13165nsDocShell::GetAssociatedWindow(mozIDOMWindowProxy** aWindow) {
13166 CallGetInterface(this, aWindow);
13167 return NS_OK;
13168}
13169
13170NS_IMETHODIMPnsresult
13171nsDocShell::GetTopWindow(mozIDOMWindowProxy** aWindow) {
13172 return mBrowsingContext->GetTopWindow(aWindow);
13173}
13174
13175NS_IMETHODIMPnsresult
13176nsDocShell::GetTopFrameElement(Element** aElement) {
13177 return mBrowsingContext->GetTopFrameElement(aElement);
13178}
13179
13180NS_IMETHODIMPnsresult
13181nsDocShell::GetUseTrackingProtection(bool* aUseTrackingProtection) {
13182 return mBrowsingContext->GetUseTrackingProtection(aUseTrackingProtection);
13183}
13184
13185NS_IMETHODIMPnsresult
13186nsDocShell::SetUseTrackingProtection(bool aUseTrackingProtection) {
13187 return mBrowsingContext->SetUseTrackingProtection(aUseTrackingProtection);
13188}
13189
13190NS_IMETHODIMPnsresult
13191nsDocShell::GetIsContent(bool* aIsContent) {
13192 *aIsContent = (mItemType == typeContent);
13193 return NS_OK;
13194}
13195
13196bool nsDocShell::IsOKToLoadURI(nsIURI* aURI) {
13197 MOZ_ASSERT(aURI, "Must have a URI!")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aURI)>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(aURI))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("aURI" " (" "Must have a URI!" ")"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 13197);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "aURI" ") (" "Must have a URI!"
")"); do { MOZ_CrashSequence(__null, 13197); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
13198
13199 if (!mFiredUnloadEvent) {
13200 return true;
13201 }
13202
13203 if (!mLoadingURI) {
13204 return false;
13205 }
13206
13207 bool isPrivateWin = false;
13208 Document* doc = GetDocument();
13209 if (doc) {
13210 isPrivateWin =
13211 doc->NodePrincipal()->OriginAttributesRef().IsPrivateBrowsing();
13212 }
13213
13214 nsCOMPtr<nsIScriptSecurityManager> secMan =
13215 do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID"@mozilla.org/scriptsecuritymanager;1");
13216 return secMan && NS_SUCCEEDED(secMan->CheckSameOriginURI(((bool)(__builtin_expect(!!(!NS_FAILED_impl(secMan->CheckSameOriginURI
( aURI, mLoadingURI, false, isPrivateWin))), 1)))
13217 aURI, mLoadingURI, false, isPrivateWin))((bool)(__builtin_expect(!!(!NS_FAILED_impl(secMan->CheckSameOriginURI
( aURI, mLoadingURI, false, isPrivateWin))), 1)))
;
13218}
13219
13220//
13221// Routines for selection and clipboard
13222//
13223nsresult nsDocShell::GetControllerForCommand(const char* aCommand,
13224 nsIController** aResult) {
13225 NS_ENSURE_ARG_POINTER(aResult)do { if ((__builtin_expect(!!(!(aResult)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aResult" ") failed", nullptr
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 13225);
return NS_ERROR_INVALID_POINTER; } } while (false)
;
13226 *aResult = nullptr;
13227
13228 NS_ENSURE_TRUE(mScriptGlobal, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(mScriptGlobal)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "mScriptGlobal" ") failed"
, nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 13228); return NS_ERROR_FAILURE; } } while (false)
;
13229
13230 nsCOMPtr<nsPIWindowRoot> root = mScriptGlobal->GetTopWindowRoot();
13231 NS_ENSURE_TRUE(root, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(root)), 0))) { NS_DebugBreak(
NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "root" ") failed", nullptr
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 13231);
return NS_ERROR_FAILURE; } } while (false)
;
13232
13233 return root->GetControllerForCommand(aCommand, false /* for any window */,
13234 aResult);
13235}
13236
13237NS_IMETHODIMPnsresult
13238nsDocShell::IsCommandEnabled(const char* aCommand, bool* aResult) {
13239 NS_ENSURE_ARG_POINTER(aResult)do { if ((__builtin_expect(!!(!(aResult)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aResult" ") failed", nullptr
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 13239);
return NS_ERROR_INVALID_POINTER; } } while (false)
;
13240 *aResult = false;
13241
13242 nsresult rv = NS_ERROR_FAILURE;
13243
13244 nsCOMPtr<nsIController> controller;
13245 rv = GetControllerForCommand(aCommand, getter_AddRefs(controller));
13246 if (controller) {
13247 rv = controller->IsCommandEnabled(aCommand, aResult);
13248 }
13249
13250 return rv;
13251}
13252
13253NS_IMETHODIMPnsresult
13254nsDocShell::DoCommand(const char* aCommand) {
13255 nsresult rv = NS_ERROR_FAILURE;
13256
13257 nsCOMPtr<nsIController> controller;
13258 rv = GetControllerForCommand(aCommand, getter_AddRefs(controller));
13259 if (controller) {
13260 rv = controller->DoCommand(aCommand);
13261 }
13262
13263 return rv;
13264}
13265
13266NS_IMETHODIMPnsresult
13267nsDocShell::DoCommandWithParams(const char* aCommand,
13268 nsICommandParams* aParams) {
13269 nsCOMPtr<nsIController> controller;
13270 nsresult rv = GetControllerForCommand(aCommand, getter_AddRefs(controller));
13271 if (NS_WARN_IF(NS_FAILED(rv))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(rv
)), 0))), "NS_FAILED(rv)", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 13271)
) {
13272 return rv;
13273 }
13274
13275 nsCOMPtr<nsICommandController> commandController =
13276 do_QueryInterface(controller, &rv);
13277 if (NS_WARN_IF(NS_FAILED(rv))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(rv
)), 0))), "NS_FAILED(rv)", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 13277)
) {
13278 return rv;
13279 }
13280
13281 return commandController->DoCommandWithParams(aCommand, aParams);
13282}
13283
13284nsresult nsDocShell::EnsureCommandHandler() {
13285 if (!mCommandManager) {
13286 if (nsCOMPtr<nsPIDOMWindowOuter> domWindow = GetWindow()) {
13287 mCommandManager = new nsCommandManager(domWindow);
13288 }
13289 }
13290 return mCommandManager ? NS_OK : NS_ERROR_FAILURE;
13291}
13292
13293// link handling
13294
13295class OnLinkClickEvent : public Runnable {
13296 public:
13297 OnLinkClickEvent(nsDocShell* aHandler, nsIContent* aContent,
13298 nsDocShellLoadState* aLoadState, bool aNoOpenerImplied,
13299 nsIPrincipal* aTriggeringPrincipal);
13300
13301 NS_IMETHODvirtual nsresult Run() override {
13302 // We need to set up an AutoJSAPI here for the following reason: When we
13303 // do OnLinkClickSync we'll eventually end up in
13304 // nsGlobalWindow::OpenInternal which only does popup blocking if
13305 // !LegacyIsCallerChromeOrNativeCode(). So we need to fake things so that
13306 // we don't look like native code as far as LegacyIsCallerNativeCode() is
13307 // concerned. (Bug 1930445)
13308 AutoJSAPI jsapi;
13309 if (jsapi.Init(mContent->OwnerDoc()->GetScopeObject())) {
13310 mHandler->OnLinkClickSync(mContent, mLoadState, mNoOpenerImplied,
13311 mTriggeringPrincipal);
13312 }
13313 return NS_OK;
13314 }
13315
13316 private:
13317 RefPtr<nsDocShell> mHandler;
13318 nsCOMPtr<nsIContent> mContent;
13319 RefPtr<nsDocShellLoadState> mLoadState;
13320 nsCOMPtr<nsIPrincipal> mTriggeringPrincipal;
13321 bool mNoOpenerImplied;
13322};
13323
13324OnLinkClickEvent::OnLinkClickEvent(nsDocShell* aHandler, nsIContent* aContent,
13325 nsDocShellLoadState* aLoadState,
13326 bool aNoOpenerImplied,
13327 nsIPrincipal* aTriggeringPrincipal)
13328 : mozilla::Runnable("OnLinkClickEvent"),
13329 mHandler(aHandler),
13330 mContent(aContent),
13331 mLoadState(aLoadState),
13332 mTriggeringPrincipal(aTriggeringPrincipal),
13333 mNoOpenerImplied(aNoOpenerImplied) {}
13334
13335nsresult nsDocShell::OnLinkClick(
13336 nsIContent* aContent, nsIURI* aURI, const nsAString& aTargetSpec,
13337 const nsAString& aFileName, nsIInputStream* aPostDataStream,
13338 nsIInputStream* aHeadersDataStream, bool aIsUserTriggered,
13339 UserNavigationInvolvement aUserInvolvement,
13340 nsIPrincipal* aTriggeringPrincipal, nsIContentSecurityPolicy* aCsp) {
13341#ifndef ANDROID
13342 MOZ_ASSERT(aTriggeringPrincipal, "Need a valid triggeringPrincipal")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aTriggeringPrincipal)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aTriggeringPrincipal))), 0))
) { do { } while (false); MOZ_ReportAssertionFailure("aTriggeringPrincipal"
" (" "Need a valid triggeringPrincipal" ")", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 13342); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aTriggeringPrincipal"
") (" "Need a valid triggeringPrincipal" ")"); do { MOZ_CrashSequence
(__null, 13342); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
13343#endif
13344 NS_ASSERTION(NS_IsMainThread(), "wrong thread")do { if (!(NS_IsMainThread())) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "wrong thread", "NS_IsMainThread()", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 13344); MOZ_PretendNoReturn(); } } while (0)
;
13345
13346 if (!IsNavigationAllowed() || !IsOKToLoadURI(aURI)) {
13347 return NS_OK;
13348 }
13349
13350 // On history navigation through Back/Forward buttons, don't execute
13351 // automatic JavaScript redirection such as |anchorElement.click()| or
13352 // |formElement.submit()|.
13353 //
13354 // XXX |formElement.submit()| bypasses this checkpoint because it calls
13355 // nsDocShell::OnLinkClickSync(...) instead.
13356 if (ShouldBlockLoadingForBackButton()) {
13357 return NS_OK;
13358 }
13359
13360 if (aContent->IsEditable()) {
13361 return NS_OK;
13362 }
13363
13364 Document* ownerDoc = aContent->OwnerDoc();
13365 if (nsContentUtils::IsExternalProtocol(aURI)) {
13366 ownerDoc->EnsureNotEnteringAndExitFullscreen();
13367 }
13368
13369 bool noOpenerImplied = false;
13370 nsAutoString target(aTargetSpec);
13371 if (aFileName.IsVoid() &&
13372 ShouldOpenInBlankTarget(aTargetSpec, aURI, aContent, aIsUserTriggered)) {
13373 target = u"_blank";
13374 if (!aTargetSpec.Equals(target)) {
13375 noOpenerImplied = true;
13376 }
13377 }
13378
13379 // https://html.spec.whatwg.org/#downloading-hyperlinks
13380 // Step 6, step 6.1, step 6.2
13381 // aFileName not being void implies a download attribute, since we've already
13382 // checked if the attribute is present in `nsContentUtils::TriggerLinkClick`
13383 // and made it void otherwise.
13384 if (!aFileName.IsVoid() &&
13385 aUserInvolvement != UserNavigationInvolvement::BrowserUI) {
13386 if (nsCOMPtr<nsPIDOMWindowInner> window = ownerDoc->GetInnerWindow()) {
13387 if (RefPtr<Navigation> navigation = window->Navigation()) {
13388 AutoJSAPI jsapi;
13389 if (jsapi.Init(window)) {
13390 RefPtr element = aContent->AsElement();
13391 // Step 6.4
13392 bool shouldContinue = navigation->FireDownloadRequestNavigateEvent(
13393 jsapi.cx(), aURI, aUserInvolvement, element, aFileName);
13394
13395 // Step 6.5
13396 if (!shouldContinue) {
13397 return NS_OK;
13398 }
13399 }
13400 }
13401 }
13402 }
13403
13404 RefPtr<nsDocShellLoadState> loadState = new nsDocShellLoadState(aURI);
13405 loadState->SetTarget(target);
13406 loadState->SetFileName(aFileName);
13407 loadState->SetPostDataStream(aPostDataStream);
13408 loadState->SetHeadersStream(aHeadersDataStream);
13409 loadState->SetFirstParty(true);
13410 loadState->SetTriggeringPrincipal(
13411 aTriggeringPrincipal ? aTriggeringPrincipal : aContent->NodePrincipal());
13412 loadState->SetPrincipalToInherit(aContent->NodePrincipal());
13413 loadState->SetCsp(aCsp ? aCsp : aContent->GetCsp());
13414 loadState->SetAllowFocusMove(UserActivation::IsHandlingUserInput());
13415
13416 const bool hasValidUserGestureActivation =
13417 ownerDoc->HasValidTransientUserGestureActivation();
13418 loadState->SetHasValidUserGestureActivation(hasValidUserGestureActivation);
13419 loadState->SetTextDirectiveUserActivation(
13420 ownerDoc->ConsumeTextDirectiveUserActivation() ||
13421 hasValidUserGestureActivation);
13422 loadState->SetUserNavigationInvolvement(aUserInvolvement);
13423 loadState->SetTriggeringClassificationFlags(
13424 ownerDoc->GetScriptTrackingFlags());
13425
13426 nsCOMPtr<nsIRunnable> ev = new OnLinkClickEvent(
13427 this, aContent, loadState, noOpenerImplied, aTriggeringPrincipal);
13428 return Dispatch(ev.forget());
13429}
13430
13431bool nsDocShell::ShouldOpenInBlankTarget(const nsAString& aOriginalTarget,
13432 nsIURI* aLinkURI, nsIContent* aContent,
13433 bool aIsUserTriggered) {
13434 if (aLinkURI->SchemeIs("javascript")) {
13435 return false;
13436 }
13437
13438 // External links from within app tabs should always open in new tabs
13439 // instead of replacing the app tab's page (Bug 575561)
13440 // nsIURI.host can throw for non-nsStandardURL nsIURIs. If we fail to
13441 // get either host, just return false to use the original target.
13442 nsAutoCString linkHost;
13443 if (NS_FAILED(aLinkURI->GetHost(linkHost))((bool)(__builtin_expect(!!(NS_FAILED_impl(aLinkURI->GetHost
(linkHost))), 0)))
) {
13444 return false;
13445 }
13446
13447 // The targetTopLevelLinkClicksToBlank property on BrowsingContext allows
13448 // privileged code to change the default targeting behaviour. In particular,
13449 // if a user-initiated link click for the (or targetting the) top-level frame
13450 // is detected, we default the target to "_blank" to give it a new
13451 // top-level BrowsingContext.
13452 if (mBrowsingContext->TargetTopLevelLinkClicksToBlank() && aIsUserTriggered &&
13453 ((aOriginalTarget.IsEmpty() && mBrowsingContext->IsTop()) ||
13454 aOriginalTarget == u"_top"_ns)) {
13455 return true;
13456 }
13457
13458 // Don't modify non-default targets.
13459 if (!aOriginalTarget.IsEmpty()) {
13460 return false;
13461 }
13462
13463 // Only check targets that are in extension panels or app tabs.
13464 // (isAppTab will be false for app tab subframes).
13465 nsString mmGroup = mBrowsingContext->Top()->GetMessageManagerGroup();
13466 if (!mmGroup.EqualsLiteral("webext-browsers") &&
13467 !mBrowsingContext->IsAppTab()) {
13468 return false;
13469 }
13470
13471 nsCOMPtr<nsIURI> docURI = aContent->OwnerDoc()->GetDocumentURIObject();
13472 if (!docURI) {
13473 return false;
13474 }
13475
13476 nsAutoCString docHost;
13477 if (NS_FAILED(docURI->GetHost(docHost))((bool)(__builtin_expect(!!(NS_FAILED_impl(docURI->GetHost
(docHost))), 0)))
) {
13478 return false;
13479 }
13480
13481 if (linkHost.Equals(docHost)) {
13482 return false;
13483 }
13484
13485 // Special case: ignore "www" prefix if it is part of host string
13486 return linkHost.Length() < docHost.Length()
13487 ? !docHost.Equals("www."_ns + linkHost)
13488 : !linkHost.Equals("www."_ns + docHost);
13489}
13490
13491static bool ElementCanHaveNoopener(nsIContent* aContent) {
13492 // Make sure we are dealing with either an <A>, <AREA>, or <FORM> element in
13493 // the HTML, XHTML, or SVG namespace.
13494 return aContent->IsAnyOfHTMLElements(nsGkAtoms::a, nsGkAtoms::area,
13495 nsGkAtoms::form) ||
13496 aContent->IsSVGElement(nsGkAtoms::a);
13497}
13498
13499nsresult nsDocShell::OnLinkClickSync(nsIContent* aContent,
13500 nsDocShellLoadState* aLoadState,
13501 bool aNoOpenerImplied,
13502 nsIPrincipal* aTriggeringPrincipal) {
13503 if (!IsNavigationAllowed() || !IsOKToLoadURI(aLoadState->URI())) {
13504 return NS_OK;
13505 }
13506
13507 // XXX When the linking node was HTMLFormElement, it is synchronous event.
13508 // That is, the caller of this method is not |OnLinkClickEvent::Run()|
13509 // but |HTMLFormElement::SubmitSubmission(...)|.
13510 if (aContent->IsHTMLElement(nsGkAtoms::form) &&
13511 ShouldBlockLoadingForBackButton()) {
13512 return NS_OK;
13513 }
13514
13515 if (aContent->IsEditable()) {
13516 return NS_OK;
13517 }
13518
13519 // if the triggeringPrincipal is not passed explicitly, then we
13520 // fall back to using doc->NodePrincipal() as the triggeringPrincipal.
13521 nsCOMPtr<nsIPrincipal> triggeringPrincipal =
13522 aTriggeringPrincipal ? aTriggeringPrincipal : aContent->NodePrincipal();
13523
13524 {
13525 // defer to an external protocol handler if necessary...
13526 nsCOMPtr<nsIExternalProtocolService> extProtService =
13527 do_GetService(NS_EXTERNALPROTOCOLSERVICE_CONTRACTID"@mozilla.org/uriloader/external-protocol-service;1");
13528 if (extProtService) {
13529 nsAutoCString scheme;
13530 aLoadState->URI()->GetScheme(scheme);
13531 if (!scheme.IsEmpty()) {
13532 // if the URL scheme does not correspond to an exposed protocol, then
13533 // we need to hand this link click over to the external protocol
13534 // handler.
13535 bool isExposed;
13536 nsresult rv =
13537 extProtService->IsExposedProtocol(scheme.get(), &isExposed);
13538 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && !isExposed) {
13539 return extProtService->LoadURI(
13540 aLoadState->URI(), triggeringPrincipal, nullptr, mBrowsingContext,
13541 /* aTriggeredExternally */
13542 false,
13543 /* aHasValidUserGestureActivation */
13544 aContent->OwnerDoc()->HasValidTransientUserGestureActivation(),
13545 /* aNewWindowTarget */ false);
13546 }
13547 }
13548 }
13549 }
13550 uint32_t triggeringSandboxFlags = 0;
13551 uint64_t triggeringWindowId = 0;
13552 bool triggeringStorageAccess = false;
13553 if (mBrowsingContext) {
13554 triggeringSandboxFlags = aContent->OwnerDoc()->GetSandboxFlags();
13555 triggeringWindowId = aContent->OwnerDoc()->InnerWindowID();
13556 triggeringStorageAccess = aContent->OwnerDoc()->UsingStorageAccess();
13557 }
13558
13559 uint32_t flags = INTERNAL_LOAD_FLAGS_NONE;
13560 bool elementCanHaveNoopener = ElementCanHaveNoopener(aContent);
13561 bool triggeringPrincipalIsSystemPrincipal =
13562 aLoadState->TriggeringPrincipal()->IsSystemPrincipal();
13563 if (elementCanHaveNoopener) {
13564 MOZ_ASSERT(aContent->IsHTMLElement() || aContent->IsSVGElement())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aContent->IsHTMLElement() || aContent->IsSVGElement
())>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(aContent->IsHTMLElement() || aContent->IsSVGElement
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("aContent->IsHTMLElement() || aContent->IsSVGElement()"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 13564);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "aContent->IsHTMLElement() || aContent->IsSVGElement()"
")"); do { MOZ_CrashSequence(__null, 13564); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
13565 nsAutoString relString;
13566 aContent->AsElement()->GetAttr(nsGkAtoms::rel, relString);
13567 nsWhitespaceTokenizerTemplate<nsContentUtils::IsHTMLWhitespace> tok(
13568 relString);
13569
13570 bool targetBlank = aLoadState->Target().LowerCaseEqualsLiteral("_blank");
13571 bool explicitOpenerSet = false;
13572
13573 // The opener behaviour follows a hierarchy, such that if a higher
13574 // priority behaviour is specified, it always takes priority. That
13575 // priority is currently: norefrerer > noopener > opener > default
13576
13577 while (tok.hasMoreTokens()) {
13578 const nsAString& token = tok.nextToken();
13579 if (token.LowerCaseEqualsLiteral("noreferrer")) {
13580 flags |= INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER |
13581 INTERNAL_LOAD_FLAGS_NO_OPENER;
13582 // noreferrer cannot be overwritten by a 'rel=opener'.
13583 explicitOpenerSet = true;
13584 break;
13585 }
13586
13587 if (token.LowerCaseEqualsLiteral("noopener")) {
13588 flags |= INTERNAL_LOAD_FLAGS_NO_OPENER;
13589 explicitOpenerSet = true;
13590 }
13591
13592 if (targetBlank && StaticPrefs::dom_targetBlankNoOpener_enabled() &&
13593 token.LowerCaseEqualsLiteral("opener") && !explicitOpenerSet) {
13594 explicitOpenerSet = true;
13595 }
13596 }
13597
13598 if (targetBlank && StaticPrefs::dom_targetBlankNoOpener_enabled() &&
13599 !explicitOpenerSet && !triggeringPrincipalIsSystemPrincipal) {
13600 flags |= INTERNAL_LOAD_FLAGS_NO_OPENER;
13601 }
13602
13603 if (aNoOpenerImplied) {
13604 flags |= INTERNAL_LOAD_FLAGS_NO_OPENER;
13605 }
13606 }
13607
13608 // Get the owner document of the link that was clicked, this will be
13609 // the document that the link is in, or the last document that the
13610 // link was in. From that document, we'll get the URI to use as the
13611 // referrer, since the current URI in this docshell may be a
13612 // new document that we're in the process of loading.
13613 RefPtr<Document> referrerDoc = aContent->OwnerDoc();
13614
13615 // Now check that the referrerDoc's inner window is the current inner
13616 // window for mScriptGlobal. If it's not, then we don't want to
13617 // follow this link.
13618 nsPIDOMWindowInner* referrerInner = referrerDoc->GetInnerWindow();
13619 if (!mScriptGlobal || !referrerInner ||
13620 mScriptGlobal->GetCurrentInnerWindow() != referrerInner) {
13621 // We're no longer the current inner window
13622 return NS_OK;
13623 }
13624
13625 // referrer could be null here in some odd cases, but that's ok,
13626 // we'll just load the link w/o sending a referrer in those cases.
13627
13628 // If this is an anchor element, grab its type property to use as a hint
13629 nsAutoString typeHint;
13630 RefPtr<HTMLAnchorElement> anchor = HTMLAnchorElement::FromNode(aContent);
13631 if (anchor) {
13632 anchor->GetType(typeHint);
13633 NS_ConvertUTF16toUTF8 utf8Hint(typeHint);
13634 nsAutoCString type, dummy;
13635 NS_ParseRequestContentType(utf8Hint, type, dummy);
13636 CopyUTF8toUTF16(type, typeHint);
13637 }
13638
13639 uint32_t loadType = LOAD_LINK;
13640 if (aLoadState->IsFormSubmission()) {
13641 if (aLoadState->Target().IsEmpty()) {
13642 // We set the right load type here for form submissions with an empty
13643 // target. Form submission with a non-empty target are handled in
13644 // nsDocShell::PerformRetargeting after we've selected the correct target
13645 // BC.
13646 loadType = GetLoadTypeForFormSubmission(GetBrowsingContext(), aLoadState);
13647 }
13648 } else {
13649 // Link click can be triggered inside an onload handler, and we don't want
13650 // to add history entry in this case.
13651 bool inOnLoadHandler = false;
13652 GetIsExecutingOnLoadHandler(&inOnLoadHandler);
13653 if (inOnLoadHandler) {
13654 loadType = LOAD_NORMAL_REPLACE;
13655 }
13656 }
13657
13658 nsCOMPtr<nsIReferrerInfo> referrerInfo =
13659 elementCanHaveNoopener ? new ReferrerInfo(*aContent->AsElement())
13660 : new ReferrerInfo(*referrerDoc);
13661
13662 aLoadState->SetTriggeringSandboxFlags(triggeringSandboxFlags);
13663 aLoadState->SetTriggeringWindowId(triggeringWindowId);
13664 aLoadState->SetTriggeringStorageAccess(triggeringStorageAccess);
13665 aLoadState->SetReferrerInfo(referrerInfo);
13666 aLoadState->SetInternalLoadFlags(flags);
13667 aLoadState->SetTypeHint(NS_ConvertUTF16toUTF8(typeHint));
13668 aLoadState->SetLoadType(loadType);
13669 aLoadState->SetSourceBrowsingContext(mBrowsingContext);
13670 aLoadState->SetSourceElement(aContent->AsElement());
13671
13672 nsresult rv = InternalLoad(aLoadState);
13673
13674 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
13675 nsPingListener::DispatchPings(this, aContent, aLoadState->URI(),
13676 referrerInfo);
13677 }
13678
13679 return rv;
13680}
13681
13682nsresult nsDocShell::OnOverLink(nsIContent* aContent, nsIURI* aURI,
13683 const nsAString& aTargetSpec) {
13684 if (aContent->IsEditable()) {
13685 return NS_OK;
13686 }
13687
13688 nsresult rv = NS_ERROR_FAILURE;
13689
13690 nsCOMPtr<nsIWebBrowserChrome> browserChrome = do_GetInterface(mTreeOwner);
13691 if (!browserChrome) {
13692 return rv;
13693 }
13694
13695 nsCOMPtr<nsIURI> exposableURI = nsIOService::CreateExposableURI(aURI);
13696 nsAutoCString spec;
13697 rv = exposableURI->GetDisplaySpec(spec);
13698 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 13698); return rv; } } while (false)
;
13699
13700 NS_ConvertUTF8toUTF16 uStr(spec);
13701
13702 PredictorPredict(aURI, mCurrentURI, nsINetworkPredictor::PREDICT_LINK,
13703 aContent->NodePrincipal()->OriginAttributesRef(), nullptr);
13704
13705 rv = browserChrome->SetLinkStatus(uStr);
13706 return rv;
13707}
13708
13709nsresult nsDocShell::OnLeaveLink() {
13710 nsCOMPtr<nsIWebBrowserChrome> browserChrome(do_GetInterface(mTreeOwner));
13711 nsresult rv = NS_ERROR_FAILURE;
13712
13713 if (browserChrome) {
13714 rv = browserChrome->SetLinkStatus(u""_ns);
13715 }
13716 return rv;
13717}
13718
13719bool nsDocShell::ShouldBlockLoadingForBackButton() {
13720 if (!(mLoadType & LOAD_CMD_HISTORY) ||
13721 UserActivation::IsHandlingUserInput() ||
13722 !Preferences::GetBool("accessibility.blockjsredirection")) {
13723 return false;
13724 }
13725
13726 bool canGoForward = false;
13727 GetCanGoForward(&canGoForward);
13728 return canGoForward;
13729}
13730
13731//----------------------------------------------------------------------
13732// Web Shell Services API
13733
13734// This functions is only called when a new charset is detected in loading a
13735// document.
13736nsresult nsDocShell::CharsetChangeReloadDocument(
13737 mozilla::NotNull<const mozilla::Encoding*> aEncoding, int32_t aSource) {
13738 // XXX hack. keep the aCharset and aSource wait to pick it up
13739 nsCOMPtr<nsIDocumentViewer> viewer;
13740 NS_ENSURE_SUCCESS(GetDocViewer(getter_AddRefs(viewer)), NS_ERROR_FAILURE)do { nsresult __rv = GetDocViewer(getter_AddRefs(viewer)); if
(((bool)(__builtin_expect(!!(NS_FAILED_impl(__rv)), 0)))) { const
char* name = mozilla::GetStaticErrorName(__rv); mozilla::SmprintfPointer
msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "GetDocViewer(getter_AddRefs(viewer))"
, "NS_ERROR_FAILURE", static_cast<uint32_t>(__rv), name
? " (" : "", name ? name : "", name ? ")" : ""); NS_DebugBreak
(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 13740); return NS_ERROR_FAILURE; } } while (false)
;
13741 if (viewer) {
13742 int32_t source;
13743 Unused << viewer->GetReloadEncodingAndSource(&source);
13744 if (aSource > source) {
13745 viewer->SetReloadEncodingAndSource(aEncoding, aSource);
13746 if (eCharsetReloadRequested != mCharsetReloadState) {
13747 mCharsetReloadState = eCharsetReloadRequested;
13748 switch (mLoadType) {
13749 case LOAD_RELOAD_BYPASS_PROXY_AND_CACHE:
13750 return Reload(LOAD_FLAGS_CHARSET_CHANGE | LOAD_FLAGS_BYPASS_CACHE |
13751 LOAD_FLAGS_BYPASS_PROXY);
13752 case LOAD_RELOAD_BYPASS_CACHE:
13753 return Reload(LOAD_FLAGS_CHARSET_CHANGE | LOAD_FLAGS_BYPASS_CACHE);
13754 default:
13755 return Reload(LOAD_FLAGS_CHARSET_CHANGE);
13756 }
13757 }
13758 }
13759 }
13760 // return failure if this request is not accepted due to mCharsetReloadState
13761 return NS_ERROR_DOCSHELL_REQUEST_REJECTED;
13762}
13763
13764nsresult nsDocShell::CharsetChangeStopDocumentLoad() {
13765 if (eCharsetReloadRequested != mCharsetReloadState) {
13766 Stop(nsIWebNavigation::STOP_ALL);
13767 return NS_OK;
13768 }
13769 // return failer if this request is not accepted due to mCharsetReloadState
13770 return NS_ERROR_DOCSHELL_REQUEST_REJECTED;
13771}
13772
13773NS_IMETHODIMPnsresult nsDocShell::ExitPrintPreview() {
13774#if NS_PRINT_PREVIEW1
13775 nsCOMPtr<nsIWebBrowserPrint> viewer = do_QueryInterface(mDocumentViewer);
13776 return viewer->ExitPrintPreview();
13777#else
13778 return NS_OK;
13779#endif
13780}
13781
13782/* [infallible] */
13783NS_IMETHODIMPnsresult nsDocShell::GetIsTopLevelContentDocShell(
13784 bool* aIsTopLevelContentDocShell) {
13785 *aIsTopLevelContentDocShell = false;
13786
13787 if (mItemType == typeContent) {
13788 *aIsTopLevelContentDocShell = mBrowsingContext->IsTopContent();
13789 }
13790
13791 return NS_OK;
13792}
13793
13794// Implements nsILoadContext.originAttributes
13795NS_IMETHODIMPnsresult
13796nsDocShell::GetScriptableOriginAttributes(JSContext* aCx,
13797 JS::MutableHandle<JS::Value> aVal) {
13798 return mBrowsingContext->GetScriptableOriginAttributes(aCx, aVal);
13799}
13800
13801// Implements nsIDocShell.GetOriginAttributes()
13802NS_IMETHODIMPnsresult
13803nsDocShell::GetOriginAttributes(JSContext* aCx,
13804 JS::MutableHandle<JS::Value> aVal) {
13805 return mBrowsingContext->GetScriptableOriginAttributes(aCx, aVal);
13806}
13807
13808bool nsDocShell::ServiceWorkerAllowedToControlWindow(nsIPrincipal* aPrincipal,
13809 nsIURI* aURI) {
13810 MOZ_ASSERT(aPrincipal)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aPrincipal)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aPrincipal))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("aPrincipal", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 13810); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPrincipal"
")"); do { MOZ_CrashSequence(__null, 13810); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
13811 MOZ_ASSERT(aURI)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aURI)>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(aURI))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("aURI", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 13811); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aURI" ")")
; do { MOZ_CrashSequence(__null, 13811); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
13812
13813 if (UsePrivateBrowsing() || mBrowsingContext->GetSandboxFlags()) {
13814 return false;
13815 }
13816
13817 nsCOMPtr<nsIDocShellTreeItem> parent;
13818 GetInProcessSameTypeParent(getter_AddRefs(parent));
13819 nsPIDOMWindowOuter* parentOuter = parent ? parent->GetWindow() : nullptr;
13820 nsPIDOMWindowInner* parentInner =
13821 parentOuter ? parentOuter->GetCurrentInnerWindow() : nullptr;
13822
13823 StorageAccess storage =
13824 StorageAllowedForNewWindow(aPrincipal, aURI, parentInner);
13825
13826 // If the partitioned service worker is enabled, service worker is allowed to
13827 // control the window if partition is enabled.
13828 if (StaticPrefs::privacy_partition_serviceWorkers() && parentInner) {
13829 RefPtr<Document> doc = parentInner->GetExtantDoc();
13830
13831 if (doc && StoragePartitioningEnabled(storage, doc->CookieJarSettings())) {
13832 return true;
13833 }
13834 }
13835
13836 return storage == StorageAccess::eAllow;
13837}
13838
13839nsresult nsDocShell::SetOriginAttributes(const OriginAttributes& aAttrs) {
13840 MOZ_ASSERT(!mIsBeingDestroyed)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mIsBeingDestroyed)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mIsBeingDestroyed))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("!mIsBeingDestroyed"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 13840);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mIsBeingDestroyed"
")"); do { MOZ_CrashSequence(__null, 13840); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
13841 return mBrowsingContext->SetOriginAttributes(aAttrs);
13842}
13843
13844NS_IMETHODIMPnsresult
13845nsDocShell::ResumeRedirectedLoad(uint64_t aIdentifier, int32_t aHistoryIndex) {
13846 RefPtr<nsDocShell> self = this;
13847 RefPtr<ChildProcessChannelListener> cpcl =
13848 ChildProcessChannelListener::GetSingleton();
13849
13850 // Call into InternalLoad with the pending channel when it is received.
13851 cpcl->RegisterCallback(
13852 aIdentifier, [self, aHistoryIndex](
13853 nsDocShellLoadState* aLoadState,
13854 nsTArray<Endpoint<extensions::PStreamFilterParent>>&&
13855 aStreamFilterEndpoints,
13856 nsDOMNavigationTiming* aTiming) {
13857 MOZ_ASSERT(aLoadState->GetPendingRedirectedChannel())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aLoadState->GetPendingRedirectedChannel())>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(aLoadState->GetPendingRedirectedChannel()))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("aLoadState->GetPendingRedirectedChannel()"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 13857);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadState->GetPendingRedirectedChannel()"
")"); do { MOZ_CrashSequence(__null, 13857); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
13858 if (NS_WARN_IF(self->mIsBeingDestroyed)NS_warn_if_impl(self->mIsBeingDestroyed, "self->mIsBeingDestroyed"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 13858)
) {
13859 aLoadState->GetPendingRedirectedChannel()->CancelWithReason(
13860 NS_BINDING_ABORTED, "nsDocShell::mIsBeingDestroyed"_ns);
13861 return NS_BINDING_ABORTED;
13862 }
13863
13864 self->mLoadType = aLoadState->LoadType();
13865 nsCOMPtr<nsIURI> previousURI;
13866 uint32_t previousFlags = 0;
13867 ExtractLastVisit(aLoadState->GetPendingRedirectedChannel(),
13868 getter_AddRefs(previousURI), &previousFlags);
13869 self->SaveLastVisit(aLoadState->GetPendingRedirectedChannel(),
13870 previousURI, previousFlags);
13871
13872 if (aTiming) {
13873 self->mTiming = new nsDOMNavigationTiming(self, aTiming);
13874 self->mBlankTiming = false;
13875 }
13876
13877 // If we're performing a history load, locate the correct history entry,
13878 // and set the relevant bits on our loadState.
13879 if (aHistoryIndex >= 0 && self->GetSessionHistory() &&
13880 !mozilla::SessionHistoryInParent()) {
13881 nsCOMPtr<nsISHistory> legacySHistory =
13882 self->GetSessionHistory()->LegacySHistory();
13883
13884 nsCOMPtr<nsISHEntry> entry;
13885 nsresult rv = legacySHistory->GetEntryAtIndex(aHistoryIndex,
13886 getter_AddRefs(entry));
13887 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
13888 legacySHistory->InternalSetRequestedIndex(aHistoryIndex);
13889 aLoadState->SetLoadType(LOAD_HISTORY);
13890 aLoadState->SetSHEntry(entry);
13891 }
13892 }
13893
13894 self->InternalLoad(aLoadState);
13895
13896 if (aLoadState->GetOriginalURIString().isSome()) {
13897 // Save URI string in case it's needed later when
13898 // sending to search engine service in EndPageLoad()
13899 self->mOriginalUriString = *aLoadState->GetOriginalURIString();
13900 }
13901
13902 for (auto& endpoint : aStreamFilterEndpoints) {
13903 extensions::StreamFilterParent::Attach(
13904 aLoadState->GetPendingRedirectedChannel(), std::move(endpoint));
13905 }
13906
13907 // If the channel isn't pending, then it means that InternalLoad
13908 // never connected it, and we shouldn't try to continue. This
13909 // can happen even if InternalLoad returned NS_OK.
13910 bool pending = false;
13911 aLoadState->GetPendingRedirectedChannel()->IsPending(&pending);
13912 NS_ASSERTION(pending, "We should have connected the pending channel!")do { if (!(pending)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "We should have connected the pending channel!"
, "pending", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 13912); MOZ_PretendNoReturn(); } } while (0)
;
13913 if (!pending) {
13914 return NS_BINDING_ABORTED;
13915 }
13916 return NS_OK;
13917 });
13918 return NS_OK;
13919}
13920
13921NS_IMETHODIMPnsresult
13922nsDocShell::SetOriginAttributes(JS::Handle<JS::Value> aOriginAttributes,
13923 JSContext* aCx) {
13924 OriginAttributes attrs;
13925 if (!aOriginAttributes.isObject() || !attrs.Init(aCx, aOriginAttributes)) {
13926 return NS_ERROR_INVALID_ARG;
13927 }
13928
13929 return SetOriginAttributes(attrs);
13930}
13931
13932NS_IMETHODIMPnsresult
13933nsDocShell::GetAsyncPanZoomEnabled(bool* aOut) {
13934 if (PresShell* presShell = GetPresShell()) {
13935 *aOut = presShell->AsyncPanZoomEnabled();
13936 return NS_OK;
13937 }
13938
13939 // If we don't have a presShell, fall back to the default platform value of
13940 // whether or not APZ is enabled.
13941 *aOut = gfxPlatform::AsyncPanZoomEnabled();
13942 return NS_OK;
13943}
13944
13945bool nsDocShell::HasUnloadedParent() {
13946 for (WindowContext* wc = GetBrowsingContext()->GetParentWindowContext(); wc;
13947 wc = wc->GetParentWindowContext()) {
13948 if (!wc->IsCurrent() || wc->IsDiscarded() ||
13949 wc->GetBrowsingContext()->IsDiscarded()) {
13950 // If a parent is OOP and the parent WindowContext is no
13951 // longer current, we can assume the parent was unloaded.
13952 return true;
13953 }
13954
13955 if (wc->GetBrowsingContext()->IsInProcess() &&
13956 (!wc->GetBrowsingContext()->GetDocShell() ||
13957 wc->GetBrowsingContext()->GetDocShell()->GetIsInUnload())) {
13958 return true;
13959 }
13960 }
13961 return false;
13962}
13963
13964/* static */
13965bool nsDocShell::ShouldUpdateGlobalHistory(uint32_t aLoadType) {
13966 return !(aLoadType == LOAD_BYPASS_HISTORY || aLoadType == LOAD_ERROR_PAGE ||
13967 aLoadType & LOAD_CMD_HISTORY);
13968}
13969
13970void nsDocShell::UpdateGlobalHistoryTitle(nsIURI* aURI) {
13971 if (!mBrowsingContext->GetUseGlobalHistory() || UsePrivateBrowsing()) {
13972 return;
13973 }
13974
13975 // Global history is interested into sub-frame visits only for link-coloring
13976 // purposes, thus title updates are skipped for those.
13977 //
13978 // Moreover, some iframe documents (such as the ones created via
13979 // document.open()) inherit the document uri of the caller, which would cause
13980 // us to override a previously set page title with one from the subframe.
13981 if (IsSubframe()) {
13982 return;
13983 }
13984
13985 if (nsCOMPtr<IHistory> history = components::History::Service()) {
13986 history->SetURITitle(aURI, mTitle);
13987 }
13988}
13989
13990bool nsDocShell::IsInvisible() { return mInvisible; }
13991
13992void nsDocShell::SetInvisible(bool aInvisible) { mInvisible = aInvisible; }
13993
13994/* static */
13995void nsDocShell::MaybeNotifyKeywordSearchLoading(const nsString& aProvider,
13996 const nsString& aKeyword) {
13997 if (aProvider.IsEmpty()) {
13998 return;
13999 }
14000 nsresult rv;
14001 nsCOMPtr<nsISupportsString> isupportsString =
14002 do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID"@mozilla.org/supports-string;1", &rv);
14003 NS_ENSURE_SUCCESS_VOID(rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS_VOID(%s) failed with "
"result 0x%" "X" "%s%s%s", "rv", static_cast<uint32_t>
(__rv), name ? " (" : "", name ? name : "", name ? ")" : "");
NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 14003); return; } } while (false)
;
14004
14005 rv = isupportsString->SetData(aProvider);
14006 NS_ENSURE_SUCCESS_VOID(rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS_VOID(%s) failed with "
"result 0x%" "X" "%s%s%s", "rv", static_cast<uint32_t>
(__rv), name ? " (" : "", name ? name : "", name ? ")" : "");
NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 14006); return; } } while (false)
;
14007
14008 nsCOMPtr<nsIObserverService> obsSvc = services::GetObserverService();
14009 if (obsSvc) {
14010 // Note that "keyword-search" refers to a search via the url
14011 // bar, not a bookmarks keyword search.
14012 obsSvc->NotifyObservers(isupportsString, "keyword-search", aKeyword.get());
14013 }
14014}
14015
14016NS_IMETHODIMPnsresult
14017nsDocShell::ShouldPrepareForIntercept(nsIURI* aURI, nsIChannel* aChannel,
14018 bool* aShouldIntercept) {
14019 return mInterceptController->ShouldPrepareForIntercept(aURI, aChannel,
14020 aShouldIntercept);
14021}
14022
14023NS_IMETHODIMPnsresult
14024nsDocShell::ChannelIntercepted(nsIInterceptedChannel* aChannel) {
14025 return mInterceptController->ChannelIntercepted(aChannel);
14026}
14027
14028bool nsDocShell::InFrameSwap() {
14029 RefPtr<nsDocShell> shell = this;
14030 do {
14031 if (shell->mInFrameSwap) {
14032 return true;
14033 }
14034 shell = shell->GetInProcessParentDocshell();
14035 } while (shell);
14036 return false;
14037}
14038
14039UniquePtr<ClientSource> nsDocShell::TakeInitialClientSource() {
14040 return std::move(mInitialClientSource);
14041}
14042
14043NS_IMETHODIMPnsresult
14044nsDocShell::GetEditingSession(nsIEditingSession** aEditSession) {
14045 if (!NS_SUCCEEDED(EnsureEditorData())((bool)(__builtin_expect(!!(!NS_FAILED_impl(EnsureEditorData(
))), 1)))
) {
14046 return NS_ERROR_FAILURE;
14047 }
14048
14049 *aEditSession = do_AddRef(mEditorData->GetEditingSession()).take();
14050 return *aEditSession ? NS_OK : NS_ERROR_FAILURE;
14051}
14052
14053NS_IMETHODIMPnsresult
14054nsDocShell::GetScriptableBrowserChild(nsIBrowserChild** aBrowserChild) {
14055 *aBrowserChild = GetBrowserChild().take();
14056 return *aBrowserChild ? NS_OK : NS_ERROR_FAILURE;
14057}
14058
14059already_AddRefed<nsIBrowserChild> nsDocShell::GetBrowserChild() {
14060 nsCOMPtr<nsIBrowserChild> tc = do_QueryReferent(mBrowserChild);
14061 return tc.forget();
14062}
14063
14064nsCommandManager* nsDocShell::GetCommandManager() {
14065 NS_ENSURE_SUCCESS(EnsureCommandHandler(), nullptr)do { nsresult __rv = EnsureCommandHandler(); if (((bool)(__builtin_expect
(!!(NS_FAILED_impl(__rv)), 0)))) { const char* name = mozilla
::GetStaticErrorName(__rv); mozilla::SmprintfPointer msg = mozilla
::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with " "result 0x%"
"X" "%s%s%s", "EnsureCommandHandler()", "nullptr", static_cast
<uint32_t>(__rv), name ? " (" : "", name ? name : "", name
? ")" : ""); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 14065);
return nullptr; } } while (false)
;
14066 return mCommandManager;
14067}
14068
14069NS_IMETHODIMP_(void)void
14070nsDocShell::GetOriginAttributes(mozilla::OriginAttributes& aAttrs) {
14071 mBrowsingContext->GetOriginAttributes(aAttrs);
14072}
14073
14074HTMLEditor* nsIDocShell::GetHTMLEditor() {
14075 nsDocShell* docShell = static_cast<nsDocShell*>(this);
14076 return docShell->GetHTMLEditorInternal();
14077}
14078
14079nsresult nsIDocShell::SetHTMLEditor(HTMLEditor* aHTMLEditor) {
14080 nsDocShell* docShell = static_cast<nsDocShell*>(this);
14081 return docShell->SetHTMLEditorInternal(aHTMLEditor);
14082}
14083
14084#define MATRIX_LENGTH 20
14085
14086NS_IMETHODIMPnsresult
14087nsDocShell::SetColorMatrix(const nsTArray<float>& aMatrix) {
14088 if (aMatrix.Length() == MATRIX_LENGTH) {
14089 mColorMatrix.reset(new gfx::Matrix5x4());
14090 static_assert(
14091 MATRIX_LENGTH * sizeof(float) == sizeof(mColorMatrix->components),
14092 "Size mismatch for our memcpy");
14093 memcpy(mColorMatrix->components, aMatrix.Elements(),
14094 sizeof(mColorMatrix->components));
14095 } else if (aMatrix.Length() == 0) {
14096 mColorMatrix.reset();
14097 } else {
14098 return NS_ERROR_INVALID_ARG;
14099 }
14100
14101 PresShell* presShell = GetPresShell();
14102 if (!presShell) {
14103 return NS_ERROR_FAILURE;
14104 }
14105
14106 nsIFrame* frame = presShell->GetRootFrame();
14107 if (!frame) {
14108 return NS_ERROR_FAILURE;
14109 }
14110
14111 frame->SchedulePaint();
14112
14113 return NS_OK;
14114}
14115
14116NS_IMETHODIMPnsresult
14117nsDocShell::GetColorMatrix(nsTArray<float>& aMatrix) {
14118 if (mColorMatrix) {
14119 aMatrix.SetLength(MATRIX_LENGTH);
14120 static_assert(
14121 MATRIX_LENGTH * sizeof(float) == sizeof(mColorMatrix->components),
14122 "Size mismatch for our memcpy");
14123 memcpy(aMatrix.Elements(), mColorMatrix->components,
14124 MATRIX_LENGTH * sizeof(float));
14125 }
14126
14127 return NS_OK;
14128}
14129
14130#undef MATRIX_LENGTH
14131
14132NS_IMETHODIMPnsresult
14133nsDocShell::GetIsForceReloading(bool* aForceReload) {
14134 *aForceReload = IsForceReloading();
14135 return NS_OK;
14136}
14137
14138bool nsDocShell::IsForceReloading() { return IsForceReloadType(mLoadType); }
14139
14140NS_IMETHODIMPnsresult
14141nsDocShell::GetBrowsingContextXPCOM(BrowsingContext** aBrowsingContext) {
14142 *aBrowsingContext = do_AddRef(mBrowsingContext).take();
14143 return NS_OK;
14144}
14145
14146BrowsingContext* nsDocShell::GetBrowsingContext() { return mBrowsingContext; }
14147
14148bool nsDocShell::GetIsAttemptingToNavigate() {
14149 // XXXbz the document.open spec says to abort even if there's just a
14150 // queued navigation task, sort of. It's not clear whether browsers
14151 // actually do that, and we didn't use to do it, so for now let's
14152 // not do that.
14153 // https://github.com/whatwg/html/issues/3447 tracks the spec side of this.
14154 if (mDocumentRequest) {
14155 // There's definitely a navigation in progress.
14156 return true;
14157 }
14158
14159 // javascript: channels have slightly weird behavior: they're LOAD_BACKGROUND
14160 // until the script runs, which means they're not sending loadgroup
14161 // notifications and hence not getting set as mDocumentRequest. Look through
14162 // our loadgroup for document-level javascript: loads.
14163 if (!mLoadGroup) {
14164 return false;
14165 }
14166
14167 nsCOMPtr<nsISimpleEnumerator> requests;
14168 mLoadGroup->GetRequests(getter_AddRefs(requests));
14169 bool hasMore = false;
14170 while (NS_SUCCEEDED(requests->HasMoreElements(&hasMore))((bool)(__builtin_expect(!!(!NS_FAILED_impl(requests->HasMoreElements
(&hasMore))), 1)))
&& hasMore) {
14171 nsCOMPtr<nsISupports> elem;
14172 requests->GetNext(getter_AddRefs(elem));
14173 nsCOMPtr<nsIScriptChannel> scriptChannel(do_QueryInterface(elem));
14174 if (!scriptChannel) {
14175 continue;
14176 }
14177
14178 if (scriptChannel->GetIsDocumentLoad()) {
14179 // This is a javascript: load that might lead to a new document,
14180 // hence a navigation.
14181 return true;
14182 }
14183 }
14184
14185 return mCheckingSessionHistory;
14186}
14187
14188mozilla::dom::SessionHistoryInfo* nsDocShell::GetActiveSessionHistoryInfo()
14189 const {
14190 return mActiveEntry.get();
14191}
14192
14193void nsDocShell::SetLoadingSessionHistoryInfo(
14194 const mozilla::dom::LoadingSessionHistoryInfo& aLoadingInfo,
14195 bool aNeedToReportActiveAfterLoadingBecomesActive) {
14196 // FIXME Would like to assert this, but can't yet.
14197 // MOZ_ASSERT(!mLoadingEntry);
14198 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)
14199 ("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)
14200 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)
;
14201 mLoadingEntry = MakeUnique<LoadingSessionHistoryInfo>(aLoadingInfo);
14202 mNeedToReportActiveAfterLoadingBecomesActive =
14203 aNeedToReportActiveAfterLoadingBecomesActive;
14204}
14205
14206void nsDocShell::MoveLoadingToActiveEntry(bool aExpired, uint32_t aCacheKey,
14207 nsIURI* aPreviousURI) {
14208 MOZ_ASSERT(mozilla::SessionHistoryInParent())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mozilla::SessionHistoryInParent())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mozilla::SessionHistoryInParent
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("mozilla::SessionHistoryInParent()", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 14208); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mozilla::SessionHistoryInParent()"
")"); do { MOZ_CrashSequence(__null, 14208); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
14209
14210 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)
14211 ("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)
;
14212
14213 UniquePtr<SessionHistoryInfo> previousActiveEntry(mActiveEntry.release());
14214 mozilla::UniquePtr<mozilla::dom::LoadingSessionHistoryInfo> loadingEntry;
14215 mActiveEntryIsLoadingFromSessionHistory =
14216 mLoadingEntry && mLoadingEntry->mLoadIsFromSessionHistory;
14217 if (mLoadingEntry) {
14218 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)
14219 ("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)
14220 "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)
14221 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)
;
14222 mActiveEntry = MakeUnique<SessionHistoryInfo>(mLoadingEntry->mInfo);
14223 mLoadingEntry.swap(loadingEntry);
14224 if (!mActiveEntryIsLoadingFromSessionHistory) {
14225 if (mNeedToReportActiveAfterLoadingBecomesActive) {
14226 // Needed to pass various history length WPTs.
14227 mBrowsingContext->SetActiveSessionHistoryEntry(
14228 mozilla::Nothing(), mActiveEntry.get(), previousActiveEntry.get(),
14229 mLoadType,
14230 /* aUpdatedCacheKey = */ 0, false);
14231 }
14232 if (!(previousActiveEntry && previousActiveEntry->IsTransient())) {
14233 mBrowsingContext->IncrementHistoryEntryCountForBrowsingContext();
14234 }
14235 }
14236 }
14237 mNeedToReportActiveAfterLoadingBecomesActive = false;
14238
14239 if (mActiveEntry) {
14240 if (aCacheKey != 0) {
14241 mActiveEntry->SetCacheKey(aCacheKey);
14242 }
14243
14244 MOZ_ASSERT(loadingEntry)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(loadingEntry)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(loadingEntry))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("loadingEntry", "/root/firefox-clang/docshell/base/nsDocShell.cpp"
, 14244); AnnotateMozCrashReason("MOZ_ASSERT" "(" "loadingEntry"
")"); do { MOZ_CrashSequence(__null, 14244); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
14245 uint32_t loadType =
14246 mLoadType == LOAD_ERROR_PAGE ? mFailedLoadType : mLoadType;
14247
14248 if (loadingEntry->mLoadId != UINT64_MAX(18446744073709551615UL)) {
14249 // We're passing in mCurrentURI, which could be null. SessionHistoryCommit
14250 // does require a non-null uri if this is for a refresh load of the same
14251 // URI, but in that case mCurrentURI won't be null here.
14252 mBrowsingContext->SessionHistoryCommit(
14253 *loadingEntry, loadType, aPreviousURI, previousActiveEntry.get(),
14254 false, aExpired, aCacheKey);
14255 }
14256
14257 // Only update navigation if the new entry will be persisted (i.e., is not
14258 // an about: page).
14259 if (!loadingEntry->mInfo.IsTransient() && GetWindow() &&
14260 GetWindow()->GetCurrentInnerWindow()) {
14261 if (RefPtr navigation =
14262 GetWindow()->GetCurrentInnerWindow()->Navigation()) {
14263 mBrowsingContext->GetContiguousHistoryEntries(*mActiveEntry,
14264 navigation);
14265 }
14266 }
14267 }
14268}
14269
14270static bool IsFaviconLoad(nsIRequest* aRequest) {
14271 nsCOMPtr<nsIChannel> channel = do_QueryInterface(aRequest);
14272 if (!channel) {
14273 return false;
14274 }
14275
14276 nsCOMPtr<nsILoadInfo> li = channel->LoadInfo();
14277 return li && li->InternalContentPolicyType() ==
14278 nsIContentPolicy::TYPE_INTERNAL_IMAGE_FAVICON;
14279}
14280
14281void nsDocShell::RecordSingleChannelId(bool aStartRequest,
14282 nsIRequest* aRequest) {
14283 // Ignore favicon loads, they don't need to block caching.
14284 if (IsFaviconLoad(aRequest)) {
14285 return;
14286 }
14287
14288 MOZ_ASSERT_IF(!aStartRequest, mRequestForBlockingFromBFCacheCount > 0)do { if (!aStartRequest) { do { static_assert( mozilla::detail
::AssertionConditionType<decltype(mRequestForBlockingFromBFCacheCount
> 0)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(mRequestForBlockingFromBFCacheCount > 0))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("mRequestForBlockingFromBFCacheCount > 0"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 14288);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "mRequestForBlockingFromBFCacheCount > 0"
")"); do { MOZ_CrashSequence(__null, 14288); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false); } } while
(false)
;
14289
14290 mRequestForBlockingFromBFCacheCount += aStartRequest ? 1 : -1;
14291
14292 if (mBrowsingContext->GetCurrentWindowContext()) {
14293 // We have three states: no request, one request with an id and
14294 // eiher one request without an id or multiple requests. Nothing() is no
14295 // request, Some(non-zero) is one request with an id and Some(0) is one
14296 // request without an id or multiple requests.
14297 Maybe<uint64_t> singleChannelId;
14298 if (mRequestForBlockingFromBFCacheCount > 1) {
14299 singleChannelId = Some(0);
14300 } else if (mRequestForBlockingFromBFCacheCount == 1) {
14301 nsCOMPtr<nsIIdentChannel> identChannel;
14302 if (aStartRequest) {
14303 identChannel = do_QueryInterface(aRequest);
14304 } else {
14305 // aChannel is the channel that's being removed, but we need to check if
14306 // the remaining channel in the loadgroup has an id.
14307 nsCOMPtr<nsISimpleEnumerator> requests;
14308 mLoadGroup->GetRequests(getter_AddRefs(requests));
14309 for (const auto& request : SimpleEnumerator<nsIRequest>(requests)) {
14310 if (!IsFaviconLoad(request) &&
14311 !!(identChannel = do_QueryInterface(request))) {
14312 break;
14313 }
14314 }
14315 }
14316
14317 if (identChannel) {
14318 singleChannelId = Some(identChannel->ChannelId());
14319 } else {
14320 singleChannelId = Some(0);
14321 }
14322 } else {
14323 MOZ_ASSERT(mRequestForBlockingFromBFCacheCount == 0)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mRequestForBlockingFromBFCacheCount == 0)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(mRequestForBlockingFromBFCacheCount == 0))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("mRequestForBlockingFromBFCacheCount == 0"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 14323);
AnnotateMozCrashReason("MOZ_ASSERT" "(" "mRequestForBlockingFromBFCacheCount == 0"
")"); do { MOZ_CrashSequence(__null, 14323); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
14324 singleChannelId = Nothing();
14325 }
14326
14327 if (MOZ_UNLIKELY(MOZ_LOG_TEST(gSHIPBFCacheLog, LogLevel::Verbose))(__builtin_expect(!!((__builtin_expect(!!(mozilla::detail::log_test
(gSHIPBFCacheLog, LogLevel::Verbose)), 0))), 0))
) {
14328 nsAutoCString uri("[no uri]");
14329 if (mCurrentURI) {
14330 uri = mCurrentURI->GetSpecOrDefault();
14331 }
14332 if (singleChannelId.isNothing()) {
14333 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)
14334 ("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)
14335 "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)
14336 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)
;
14337 } else if (singleChannelId.value() == 0) {
14338 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)
14339 ("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)
14340 "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)
14341 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)
;
14342 } else {
14343 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)
14344 ("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)
14345 " 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)
14346 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)
;
14347 }
14348 }
14349
14350 if (mSingleChannelId != singleChannelId) {
14351 mSingleChannelId = singleChannelId;
14352 WindowGlobalChild* wgc =
14353 mBrowsingContext->GetCurrentWindowContext()->GetWindowGlobalChild();
14354 if (wgc) {
14355 wgc->SendSetSingleChannelId(singleChannelId);
14356 }
14357 }
14358 }
14359}
14360
14361NS_IMETHODIMPnsresult
14362nsDocShell::OnStartRequest(nsIRequest* aRequest) {
14363 if (MOZ_UNLIKELY(MOZ_LOG_TEST(gSHIPBFCacheLog, LogLevel::Verbose))(__builtin_expect(!!((__builtin_expect(!!(mozilla::detail::log_test
(gSHIPBFCacheLog, LogLevel::Verbose)), 0))), 0))
) {
14364 nsAutoCString uri("[no uri]");
14365 if (mCurrentURI) {
14366 uri = mCurrentURI->GetSpecOrDefault();
14367 }
14368 nsAutoCString name;
14369 aRequest->GetName(name);
14370 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)
14371 ("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)
;
14372 }
14373 RecordSingleChannelId(true, aRequest);
14374 return nsDocLoader::OnStartRequest(aRequest);
14375}
14376
14377NS_IMETHODIMPnsresult
14378nsDocShell::OnStopRequest(nsIRequest* aRequest, nsresult aStatusCode) {
14379 if (MOZ_UNLIKELY(MOZ_LOG_TEST(gSHIPBFCacheLog, LogLevel::Verbose))(__builtin_expect(!!((__builtin_expect(!!(mozilla::detail::log_test
(gSHIPBFCacheLog, LogLevel::Verbose)), 0))), 0))
) {
14380 nsAutoCString uri("[no uri]");
14381 if (mCurrentURI) {
14382 uri = mCurrentURI->GetSpecOrDefault();
14383 }
14384 nsAutoCString name;
14385 aRequest->GetName(name);
14386 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)
14387 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)
14388 ("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)
;
14389 }
14390 RecordSingleChannelId(false, aRequest);
14391 return nsDocLoader::OnStopRequest(aRequest, aStatusCode);
14392}
14393
14394void nsDocShell::MaybeDisconnectChildListenersOnPageHide() {
14395 MOZ_RELEASE_ASSERT(XRE_IsContentProcess())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(XRE_IsContentProcess())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(XRE_IsContentProcess()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("XRE_IsContentProcess()"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 14395);
AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "XRE_IsContentProcess()"
")"); do { MOZ_CrashSequence(__null, 14395); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
14396
14397 if (mChannelToDisconnectOnPageHide != 0 && mLoadGroup) {
14398 nsCOMPtr<nsISimpleEnumerator> requests;
14399 mLoadGroup->GetRequests(getter_AddRefs(requests));
14400 for (const auto& request : SimpleEnumerator<nsIRequest>(requests)) {
14401 RefPtr<DocumentChannel> channel = do_QueryObject(request);
14402 if (channel && channel->ChannelId() == mChannelToDisconnectOnPageHide) {
14403 static_cast<DocumentChannelChild*>(channel.get())
14404 ->DisconnectChildListeners(NS_BINDING_ABORTED, NS_BINDING_ABORTED);
14405 }
14406 }
14407 mChannelToDisconnectOnPageHide = 0;
14408 }
14409}
14410
14411bool nsDocShell::IsSameDocumentAsActiveEntry(
14412 const mozilla::dom::SessionHistoryInfo& aSHInfo) {
14413 return mActiveEntry ? mActiveEntry->SharesDocumentWith(aSHInfo) : false;
14414}
14415
14416// https://html.spec.whatwg.org/#nav-window
14417nsPIDOMWindowInner* nsDocShell::GetActiveWindow() {
14418 nsPIDOMWindowOuter* outer = GetWindow();
14419 return outer ? outer->GetCurrentInnerWindow() : nullptr;
14420}
14421
14422// https://html.spec.whatwg.org/#inform-the-navigation-api-about-aborting-navigation
14423void nsDocShell::InformNavigationAPIAboutAbortingNavigation() {
14424 // Step 1
14425 // This becomes an assert since we have a common event loop.
14426 MOZ_DIAGNOSTIC_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(NS_IsMainThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()"
, "/root/firefox-clang/docshell/base/nsDocShell.cpp", 14426);
AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "NS_IsMainThread()"
")"); do { MOZ_CrashSequence(__null, 14426); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
14427
14428 // No ongoing navigations if we don't have a window.
14429 RefPtr<nsPIDOMWindowInner> window = GetActiveWindow();
14430 if (!window) {
14431 return;
14432 }
14433
14434 // Step 2
14435 RefPtr<Navigation> navigation = window->Navigation();
14436 if (!navigation) {
14437 return;
14438 }
14439
14440 // Step 3
14441 if (!navigation->HasOngoingNavigateEvent()) {
14442 return;
14443 }
14444
14445 AutoJSAPI jsapi;
14446 if (!jsapi.Init(navigation->GetOwnerGlobal())) {
14447 return;
14448 }
14449
14450 // Step 4
14451 navigation->AbortOngoingNavigation(jsapi.cx());
14452}
14453
14454// https://html.spec.whatwg.org/#set-the-ongoing-navigation
14455void nsDocShell::SetOngoingNavigation(
14456 const Maybe<OngoingNavigation>& aOngoingNavigation) {
14457 // We currently only use #set-the-ongoing-navigation to call,
14458 // #inform-the-navigation-api-about-aborting-navigation, but really it should
14459 // be used for more. The spec keeps a piece of state on the navigable:
14460 // https://html.spec.whatwg.org/#ongoing-navigation. Spec uses it for several
14461 // things, for example right here in #set-the-ongoing-navigation to make sure
14462 // that we don't call #inform-the-navigation-api-about-aborting-navigation if
14463 // we're setting it to the same value. We currently only care about aborting
14464 // the currently firing navigate event. Also, in reality, this is very much
14465 // related to nsDocShell::GetIsAttemptingToNavigate() which is what we
14466 // currently use to determine if we need to stop an ongoing navigation in
14467 // Document::Open, whereas the spec checks if the ongoing navigation is a
14468 // NavigationID.
14469
14470 // Step 1, with the exception that we assume setting the ongoing navigation to
14471 // an id always means a fresh id.
14472 if (aOngoingNavigation == mOngoingNavigation &&
14473 aOngoingNavigation != Some(OngoingNavigation::NavigationID)) {
14474 return;
14475 }
14476
14477 // Step 2
14478 InformNavigationAPIAboutAbortingNavigation();
14479
14480 // Step 3
14481 mOngoingNavigation = aOngoingNavigation;
14482}